1 // Copyright 2013-2014 The Rust Project Developers. 2 // Copyright 2018 The Uuid Project Developers. 3 // 4 // See the COPYRIGHT file at the top-level directory of this distribution. 5 // 6 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 7 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 8 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 9 // option. This file may not be copied, modified, or distributed 10 // except according to those terms. 11 12 use crate::prelude::*; 13 use core::fmt; 14 use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; 15 16 impl Serialize for Uuid { serialize<S: Serializer>( &self, serializer: S, ) -> Result<S::Ok, S::Error>17 fn serialize<S: Serializer>( 18 &self, 19 serializer: S, 20 ) -> Result<S::Ok, S::Error> { 21 if serializer.is_human_readable() { 22 serializer 23 .serialize_str(&self.to_hyphenated().encode_lower(&mut [0; 36])) 24 } else { 25 serializer.serialize_bytes(self.as_bytes()) 26 } 27 } 28 } 29 30 impl<'de> Deserialize<'de> for Uuid { deserialize<D: Deserializer<'de>>( deserializer: D, ) -> Result<Self, D::Error>31 fn deserialize<D: Deserializer<'de>>( 32 deserializer: D, 33 ) -> Result<Self, D::Error> { 34 fn de_error<E: de::Error>(e: crate::Error) -> E { 35 E::custom(format_args!("UUID parsing failed: {}", e)) 36 } 37 38 if deserializer.is_human_readable() { 39 struct UuidStringVisitor; 40 41 impl<'vi> de::Visitor<'vi> for UuidStringVisitor { 42 type Value = Uuid; 43 44 fn expecting( 45 &self, 46 formatter: &mut fmt::Formatter<'_>, 47 ) -> fmt::Result { 48 write!(formatter, "a UUID string") 49 } 50 51 fn visit_str<E: de::Error>( 52 self, 53 value: &str, 54 ) -> Result<Uuid, E> { 55 value.parse::<Uuid>().map_err(de_error) 56 } 57 58 fn visit_bytes<E: de::Error>( 59 self, 60 value: &[u8], 61 ) -> Result<Uuid, E> { 62 Uuid::from_slice(value).map_err(de_error) 63 } 64 } 65 66 deserializer.deserialize_str(UuidStringVisitor) 67 } else { 68 struct UuidBytesVisitor; 69 70 impl<'vi> de::Visitor<'vi> for UuidBytesVisitor { 71 type Value = Uuid; 72 73 fn expecting( 74 &self, 75 formatter: &mut fmt::Formatter<'_>, 76 ) -> fmt::Result { 77 write!(formatter, "bytes") 78 } 79 80 fn visit_bytes<E: de::Error>( 81 self, 82 value: &[u8], 83 ) -> Result<Uuid, E> { 84 Uuid::from_slice(value).map_err(de_error) 85 } 86 } 87 88 deserializer.deserialize_bytes(UuidBytesVisitor) 89 } 90 } 91 } 92 93 #[cfg(test)] 94 mod serde_tests { 95 use serde_test::{Compact, Configure, Readable, Token}; 96 97 use crate::prelude::*; 98 99 #[test] test_serialize_readable()100 fn test_serialize_readable() { 101 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 102 let u = Uuid::parse_str(uuid_str).unwrap(); 103 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]); 104 } 105 106 #[test] test_serialize_compact()107 fn test_serialize_compact() { 108 let uuid_bytes = b"F9168C5E-CEB2-4F"; 109 let u = Uuid::from_slice(uuid_bytes).unwrap(); 110 serde_test::assert_tokens(&u.compact(), &[Token::Bytes(uuid_bytes)]); 111 } 112 113 #[test] test_de_failure()114 fn test_de_failure() { 115 serde_test::assert_de_tokens_error::<Readable<Uuid>>( 116 &[Token::Str("hello_world")], 117 "UUID parsing failed: invalid length: expected one of [36, 32], found 11", 118 ); 119 120 serde_test::assert_de_tokens_error::<Compact<Uuid>>( 121 &[Token::Bytes(b"hello_world")], 122 "UUID parsing failed: invalid bytes length: expected 16, found 11", 123 ); 124 } 125 } 126