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::{ 13 error::*, 14 fmt::{Braced, Hyphenated, Simple, Urn}, 15 std::fmt, 16 Uuid, 17 }; 18 use serde::{ 19 de::{self, Error as _}, 20 Deserialize, Deserializer, Serialize, Serializer, 21 }; 22 23 impl Serialize for Uuid { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>24 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 25 if serializer.is_human_readable() { 26 serializer.serialize_str(self.hyphenated().encode_lower(&mut Uuid::encode_buffer())) 27 } else { 28 serializer.serialize_bytes(self.as_bytes()) 29 } 30 } 31 } 32 33 impl Serialize for Hyphenated { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>34 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 35 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 36 } 37 } 38 39 impl Serialize for Simple { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>40 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 41 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 42 } 43 } 44 45 impl Serialize for Urn { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>46 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 47 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 48 } 49 } 50 51 impl Serialize for Braced { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>52 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 53 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 54 } 55 } 56 57 impl<'de> Deserialize<'de> for Uuid { deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>58 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { 59 fn de_error<E: de::Error>(e: Error) -> E { 60 E::custom(format_args!("UUID parsing failed: {}", e)) 61 } 62 63 if deserializer.is_human_readable() { 64 struct UuidVisitor; 65 66 impl<'vi> de::Visitor<'vi> for UuidVisitor { 67 type Value = Uuid; 68 69 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 70 write!(formatter, "a UUID string") 71 } 72 73 fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> { 74 value.parse::<Uuid>().map_err(de_error) 75 } 76 77 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> { 78 Uuid::from_slice(value).map_err(de_error) 79 } 80 81 fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error> 82 where 83 A: de::SeqAccess<'vi>, 84 { 85 #[rustfmt::skip] 86 let bytes = [ 87 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 88 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 89 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 90 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 91 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 92 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 93 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 94 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 95 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 96 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 97 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 98 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 99 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 100 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 101 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 102 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) }, 103 ]; 104 105 Ok(Uuid::from_bytes(bytes)) 106 } 107 } 108 109 deserializer.deserialize_str(UuidVisitor) 110 } else { 111 struct UuidBytesVisitor; 112 113 impl<'vi> de::Visitor<'vi> for UuidBytesVisitor { 114 type Value = Uuid; 115 116 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 117 write!(formatter, "bytes") 118 } 119 120 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> { 121 Uuid::from_slice(value).map_err(de_error) 122 } 123 } 124 125 deserializer.deserialize_bytes(UuidBytesVisitor) 126 } 127 } 128 } 129 130 pub mod compact { 131 //! Serialize a [`Uuid`] as a `[u8; 16]`. 132 //! 133 //! [`Uuid`]: ../../struct.Uuid.html 134 135 /// Serialize from a [`Uuid`] as a `[u8; 16]` 136 /// 137 /// [`Uuid`]: ../../struct.Uuid.html serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,138 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> 139 where 140 S: serde::Serializer, 141 { 142 serde::Serialize::serialize(u.as_bytes(), serializer) 143 } 144 145 /// Deserialize a `[u8; 16]` as a [`Uuid`] 146 /// 147 /// [`Uuid`]: ../../struct.Uuid.html deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> where D: serde::Deserializer<'de>,148 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> 149 where 150 D: serde::Deserializer<'de>, 151 { 152 let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?; 153 154 Ok(crate::Uuid::from_bytes(bytes)) 155 } 156 157 #[cfg(test)] 158 mod tests { 159 use serde_derive::*; 160 use serde_test::{self, Configure}; 161 162 #[test] test_serialize_compact()163 fn test_serialize_compact() { 164 #[derive(Serialize, Debug, Deserialize, PartialEq)] 165 struct UuidContainer { 166 #[serde(with = "crate::serde::compact")] 167 u: crate::Uuid, 168 } 169 170 let uuid_bytes = b"F9168C5E-CEB2-4F"; 171 let container = UuidContainer { 172 u: crate::Uuid::from_slice(uuid_bytes).unwrap(), 173 }; 174 175 // more complex because of the struct wrapping the actual UUID 176 // serialization 177 serde_test::assert_tokens( 178 &container.compact(), 179 &[ 180 serde_test::Token::Struct { 181 name: "UuidContainer", 182 len: 1, 183 }, 184 serde_test::Token::Str("u"), 185 serde_test::Token::Tuple { len: 16 }, 186 serde_test::Token::U8(uuid_bytes[0]), 187 serde_test::Token::U8(uuid_bytes[1]), 188 serde_test::Token::U8(uuid_bytes[2]), 189 serde_test::Token::U8(uuid_bytes[3]), 190 serde_test::Token::U8(uuid_bytes[4]), 191 serde_test::Token::U8(uuid_bytes[5]), 192 serde_test::Token::U8(uuid_bytes[6]), 193 serde_test::Token::U8(uuid_bytes[7]), 194 serde_test::Token::U8(uuid_bytes[8]), 195 serde_test::Token::U8(uuid_bytes[9]), 196 serde_test::Token::U8(uuid_bytes[10]), 197 serde_test::Token::U8(uuid_bytes[11]), 198 serde_test::Token::U8(uuid_bytes[12]), 199 serde_test::Token::U8(uuid_bytes[13]), 200 serde_test::Token::U8(uuid_bytes[14]), 201 serde_test::Token::U8(uuid_bytes[15]), 202 serde_test::Token::TupleEnd, 203 serde_test::Token::StructEnd, 204 ], 205 ) 206 } 207 } 208 } 209 210 #[cfg(test)] 211 mod serde_tests { 212 use super::*; 213 214 use serde_test::{Compact, Configure, Readable, Token}; 215 216 #[test] test_serialize_readable_string()217 fn test_serialize_readable_string() { 218 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 219 let u = Uuid::parse_str(uuid_str).unwrap(); 220 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]); 221 } 222 223 #[test] test_deserialize_readable_compact()224 fn test_deserialize_readable_compact() { 225 let uuid_bytes = b"F9168C5E-CEB2-4F"; 226 let u = Uuid::from_slice(uuid_bytes).unwrap(); 227 228 serde_test::assert_de_tokens( 229 &u.readable(), 230 &[ 231 serde_test::Token::Tuple { len: 16 }, 232 serde_test::Token::U8(uuid_bytes[0]), 233 serde_test::Token::U8(uuid_bytes[1]), 234 serde_test::Token::U8(uuid_bytes[2]), 235 serde_test::Token::U8(uuid_bytes[3]), 236 serde_test::Token::U8(uuid_bytes[4]), 237 serde_test::Token::U8(uuid_bytes[5]), 238 serde_test::Token::U8(uuid_bytes[6]), 239 serde_test::Token::U8(uuid_bytes[7]), 240 serde_test::Token::U8(uuid_bytes[8]), 241 serde_test::Token::U8(uuid_bytes[9]), 242 serde_test::Token::U8(uuid_bytes[10]), 243 serde_test::Token::U8(uuid_bytes[11]), 244 serde_test::Token::U8(uuid_bytes[12]), 245 serde_test::Token::U8(uuid_bytes[13]), 246 serde_test::Token::U8(uuid_bytes[14]), 247 serde_test::Token::U8(uuid_bytes[15]), 248 serde_test::Token::TupleEnd, 249 ], 250 ); 251 } 252 253 #[test] test_deserialize_readable_bytes()254 fn test_deserialize_readable_bytes() { 255 let uuid_bytes = b"F9168C5E-CEB2-4F"; 256 let u = Uuid::from_slice(uuid_bytes).unwrap(); 257 258 serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]); 259 } 260 261 #[test] test_serialize_hyphenated()262 fn test_serialize_hyphenated() { 263 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 264 let u = Uuid::parse_str(uuid_str).unwrap(); 265 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]); 266 } 267 268 #[test] test_serialize_simple()269 fn test_serialize_simple() { 270 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4"; 271 let u = Uuid::parse_str(uuid_str).unwrap(); 272 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]); 273 } 274 275 #[test] test_serialize_urn()276 fn test_serialize_urn() { 277 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 278 let u = Uuid::parse_str(uuid_str).unwrap(); 279 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]); 280 } 281 282 #[test] test_serialize_braced()283 fn test_serialize_braced() { 284 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}"; 285 let u = Uuid::parse_str(uuid_str).unwrap(); 286 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]); 287 } 288 289 #[test] test_serialize_non_human_readable()290 fn test_serialize_non_human_readable() { 291 let uuid_bytes = b"F9168C5E-CEB2-4F"; 292 let u = Uuid::from_slice(uuid_bytes).unwrap(); 293 serde_test::assert_tokens( 294 &u.compact(), 295 &[serde_test::Token::Bytes(&[ 296 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70, 297 ])], 298 ); 299 } 300 301 #[test] test_de_failure()302 fn test_de_failure() { 303 serde_test::assert_de_tokens_error::<Readable<Uuid>>( 304 &[Token::Str("hello_world")], 305 "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1", 306 ); 307 308 serde_test::assert_de_tokens_error::<Compact<Uuid>>( 309 &[Token::Bytes(b"hello_world")], 310 "UUID parsing failed: invalid length: expected 16 bytes, found 11", 311 ); 312 } 313 } 314