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