uuid/external/
serde_support.rs

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
12use crate::{
13    convert::TryFrom,
14    error::*,
15    fmt::{Braced, Hyphenated, Simple, Urn},
16    non_nil::NonNilUuid,
17    std::fmt,
18    Uuid,
19};
20use serde::{
21    de::{self, Error as _},
22    Deserialize, Deserializer, Serialize, Serializer,
23};
24
25impl Serialize for Uuid {
26    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
27        if serializer.is_human_readable() {
28            serializer.serialize_str(self.hyphenated().encode_lower(&mut Uuid::encode_buffer()))
29        } else {
30            serializer.serialize_bytes(self.as_bytes())
31        }
32    }
33}
34
35impl Serialize for NonNilUuid {
36    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
37    where
38        S: serde::Serializer,
39    {
40        Uuid::from(*self).serialize(serializer)
41    }
42}
43
44impl Serialize for Hyphenated {
45    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
46        serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
47    }
48}
49
50impl Serialize for Simple {
51    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
52        serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
53    }
54}
55
56impl Serialize for Urn {
57    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
58        serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
59    }
60}
61
62impl Serialize for Braced {
63    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
64        serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
65    }
66}
67
68impl<'de> Deserialize<'de> for Uuid {
69    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
70        fn de_error<E: de::Error>(e: Error) -> E {
71            E::custom(format_args!("UUID parsing failed: {}", e))
72        }
73
74        if deserializer.is_human_readable() {
75            struct UuidVisitor;
76
77            impl<'vi> de::Visitor<'vi> for UuidVisitor {
78                type Value = Uuid;
79
80                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
81                    write!(formatter, "a UUID string")
82                }
83
84                fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
85                    value.parse::<Uuid>().map_err(de_error)
86                }
87
88                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
89                    Uuid::from_slice(value).map_err(de_error)
90                }
91
92                fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error>
93                where
94                    A: de::SeqAccess<'vi>,
95                {
96                    #[rustfmt::skip]
97                    let bytes = [
98                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(0, &self)) },
99                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(1, &self)) },
100                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(2, &self)) },
101                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(3, &self)) },
102                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(4, &self)) },
103                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(5, &self)) },
104                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(6, &self)) },
105                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(7, &self)) },
106                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(8, &self)) },
107                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(9, &self)) },
108                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(10, &self)) },
109                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(11, &self)) },
110                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(12, &self)) },
111                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(13, &self)) },
112                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(14, &self)) },
113                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(15, &self)) },
114                    ];
115
116                    Ok(Uuid::from_bytes(bytes))
117                }
118            }
119
120            deserializer.deserialize_str(UuidVisitor)
121        } else {
122            struct UuidBytesVisitor;
123
124            impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
125                type Value = Uuid;
126
127                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
128                    write!(formatter, "bytes")
129                }
130
131                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
132                    Uuid::from_slice(value).map_err(de_error)
133                }
134            }
135
136            deserializer.deserialize_bytes(UuidBytesVisitor)
137        }
138    }
139}
140
141impl<'de> Deserialize<'de> for NonNilUuid {
142    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
143    where
144        D: serde::Deserializer<'de>,
145    {
146        let uuid = Uuid::deserialize(deserializer)?;
147
148        NonNilUuid::try_from(uuid).map_err(|_| {
149            de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID")
150        })
151    }
152}
153
154enum ExpectedFormat {
155    Simple,
156    Braced,
157    Urn,
158}
159
160impl std::fmt::Display for ExpectedFormat {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        let s = match self {
163            ExpectedFormat::Simple => "a simple Uuid string like 67e5504410b1426f9247bb680e5fe0c8",
164            ExpectedFormat::Braced => {
165                "a braced Uuid string like {67e55044-10b1-426f-9247-bb680e5fe0c8}"
166            }
167            ExpectedFormat::Urn => {
168                "a URN Uuid string like urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8"
169            }
170        };
171        f.write_str(s)
172    }
173}
174
175impl de::Expected for ExpectedFormat {
176    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
177        <ExpectedFormat as std::fmt::Display>::fmt(self, formatter)
178    }
179}
180
181pub mod compact {
182    //! Serialize a [`Uuid`] as a `[u8; 16]`.
183    //!
184    //! [`Uuid`]: ../../struct.Uuid.html
185
186    /// Serialize from a [`Uuid`] as a `[u8; 16]`
187    ///
188    /// [`Uuid`]: ../../struct.Uuid.html
189    pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
190    where
191        S: serde::Serializer,
192    {
193        serde::Serialize::serialize(u.as_bytes(), serializer)
194    }
195
196    /// Deserialize a `[u8; 16]` as a [`Uuid`]
197    ///
198    /// [`Uuid`]: ../../struct.Uuid.html
199    pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
200    where
201        D: serde::Deserializer<'de>,
202    {
203        let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?;
204
205        Ok(crate::Uuid::from_bytes(bytes))
206    }
207
208    #[cfg(test)]
209    mod tests {
210        use serde_derive::*;
211        use serde_test::Configure;
212
213        #[test]
214        fn test_serialize_compact() {
215            #[derive(Serialize, Debug, Deserialize, PartialEq)]
216            struct UuidContainer {
217                #[serde(with = "crate::serde::compact")]
218                u: crate::Uuid,
219            }
220
221            let uuid_bytes = b"F9168C5E-CEB2-4F";
222            let container = UuidContainer {
223                u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
224            };
225
226            // more complex because of the struct wrapping the actual UUID
227            // serialization
228            serde_test::assert_tokens(
229                &container.compact(),
230                &[
231                    serde_test::Token::Struct {
232                        name: "UuidContainer",
233                        len: 1,
234                    },
235                    serde_test::Token::Str("u"),
236                    serde_test::Token::Tuple { len: 16 },
237                    serde_test::Token::U8(uuid_bytes[0]),
238                    serde_test::Token::U8(uuid_bytes[1]),
239                    serde_test::Token::U8(uuid_bytes[2]),
240                    serde_test::Token::U8(uuid_bytes[3]),
241                    serde_test::Token::U8(uuid_bytes[4]),
242                    serde_test::Token::U8(uuid_bytes[5]),
243                    serde_test::Token::U8(uuid_bytes[6]),
244                    serde_test::Token::U8(uuid_bytes[7]),
245                    serde_test::Token::U8(uuid_bytes[8]),
246                    serde_test::Token::U8(uuid_bytes[9]),
247                    serde_test::Token::U8(uuid_bytes[10]),
248                    serde_test::Token::U8(uuid_bytes[11]),
249                    serde_test::Token::U8(uuid_bytes[12]),
250                    serde_test::Token::U8(uuid_bytes[13]),
251                    serde_test::Token::U8(uuid_bytes[14]),
252                    serde_test::Token::U8(uuid_bytes[15]),
253                    serde_test::Token::TupleEnd,
254                    serde_test::Token::StructEnd,
255                ],
256            )
257        }
258    }
259}
260
261/// Serialize from a [`Uuid`] as a `uuid::fmt::Simple`
262///
263/// [`Uuid`]: ../../struct.Uuid.html
264///
265/// ## Example
266///
267/// ```rust
268/// #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
269/// struct StructA {
270///     // This will change both serailization and deserialization
271///     #[serde(with = "uuid::serde::simple")]
272///     id: uuid::Uuid,
273/// }
274///
275/// #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
276/// struct StructB {
277///     // This will be serialized as uuid::fmt::Simple and deserialize from all valid formats
278///     #[serde(serialize_with = "uuid::serde::simple::serialize")]
279///     id: uuid::Uuid,
280/// }
281/// ```
282pub mod simple {
283    use serde::{de, Deserialize};
284
285    use crate::{parser::parse_simple, Uuid};
286
287    use super::ExpectedFormat;
288
289    /// Serialize from a [`Uuid`] as a `uuid::fmt::Simple`
290    ///
291    /// [`Uuid`]: ../../struct.Uuid.html
292    ///
293    /// # Example
294    ///
295    /// ```rust
296    /// #[derive(serde_derive::Serialize)]
297    /// struct Struct {
298    ///     // This will be serialize as uuid::fmt::Simple
299    ///     #[serde(serialize_with = "uuid::serde::simple::serialize")]
300    ///     id: uuid::Uuid,
301    /// }
302    ///
303    /// ```
304    pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
305    where
306        S: serde::Serializer,
307    {
308        serde::Serialize::serialize(u.as_simple(), serializer)
309    }
310
311    /// Deserialize a simple Uuid string as a [`Uuid`]
312    ///
313    /// [`Uuid`]: ../../struct.Uuid.html
314    pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
315    where
316        D: serde::Deserializer<'de>,
317    {
318        let s = <&str as Deserialize>::deserialize(deserializer)?;
319        let bytes = parse_simple(s.as_bytes()).map_err(|_| {
320            de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Simple)
321        })?;
322        Ok(Uuid::from_bytes(bytes))
323    }
324
325    #[cfg(test)]
326    mod tests {
327        use serde::de::{self, Error};
328        use serde_test::{Readable, Token};
329
330        use crate::{external::serde_support::ExpectedFormat, Uuid};
331
332        const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
333        const SIMPLE_UUID_STR: &'static str = "f9168c5eceb24faab6bf329bf39fa1e4";
334
335        #[test]
336        fn test_serialize_as_simple() {
337            #[derive(serde_derive::Serialize)]
338            struct Struct(#[serde(with = "super")] crate::Uuid);
339
340            let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
341            serde_test::assert_ser_tokens(
342                &u,
343                &[
344                    Token::NewtypeStruct { name: "Struct" },
345                    Token::Str(SIMPLE_UUID_STR),
346                ],
347            );
348        }
349
350        #[test]
351        fn test_de_from_simple() {
352            #[derive(PartialEq, Debug, serde_derive::Deserialize)]
353            struct Struct(#[serde(with = "super")] crate::Uuid);
354            let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
355            serde_test::assert_de_tokens::<Struct>(
356                &s,
357                &[
358                    Token::TupleStruct {
359                        name: "Struct",
360                        len: 1,
361                    },
362                    Token::BorrowedStr(SIMPLE_UUID_STR),
363                    Token::TupleStructEnd,
364                ],
365            );
366        }
367
368        #[test]
369        fn test_de_reject_hypenated() {
370            #[derive(PartialEq, Debug, serde_derive::Deserialize)]
371            struct Struct(#[serde(with = "super")] crate::Uuid);
372            serde_test::assert_de_tokens_error::<Readable<Struct>>(
373                &[
374                    Token::TupleStruct {
375                        name: "Struct",
376                        len: 1,
377                    },
378                    Token::BorrowedStr(HYPHENATED_UUID_STR),
379                    Token::TupleStructEnd,
380                ],
381                &format!(
382                    "{}",
383                    de::value::Error::invalid_value(
384                        de::Unexpected::Str(HYPHENATED_UUID_STR),
385                        &ExpectedFormat::Simple,
386                    )
387                ),
388            );
389        }
390    }
391}
392
393/// Serialize from a [`Uuid`] as a `uuid::fmt::Braced`
394///
395/// [`Uuid`]: ../../struct.Uuid.html
396///
397/// ## Example
398///
399/// ```rust
400/// #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
401/// struct StructA {
402///     // This will change both serailization and deserialization
403///     #[serde(with = "uuid::serde::braced")]
404///     id: uuid::Uuid,
405/// }
406///
407/// #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
408/// struct StructB {
409///     // This will be serialized as uuid::fmt::Urn and deserialize from all valid formats
410///     #[serde(serialize_with = "uuid::serde::braced::serialize")]
411///     id: uuid::Uuid,
412/// }
413/// ```
414pub mod braced {
415    use serde::{de, Deserialize};
416
417    use crate::parser::parse_braced;
418
419    use super::ExpectedFormat;
420
421    /// Serialize from a [`Uuid`] as a `uuid::fmt::Braced`
422    ///
423    /// [`Uuid`]: ../../struct.Uuid.html
424    ///
425    /// # Example
426    ///
427    /// ```rust
428    /// #[derive(serde_derive::Serialize)]
429    /// struct Struct {
430    ///     // This will be serialize as uuid::fmt::Braced
431    ///     #[serde(serialize_with = "uuid::serde::braced::serialize")]
432    ///     id: uuid::Uuid,
433    /// }
434    ///
435    /// ```
436    pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
437    where
438        S: serde::Serializer,
439    {
440        serde::Serialize::serialize(u.as_braced(), serializer)
441    }
442
443    /// Deserialize a braced Uuid string as a [`Uuid`]
444    ///
445    /// [`Uuid`]: ../../struct.Uuid.html
446    pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
447    where
448        D: serde::Deserializer<'de>,
449    {
450        let s = <&str as Deserialize>::deserialize(deserializer)?;
451        let bytes = parse_braced(s.as_bytes()).map_err(|_| {
452            de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Braced)
453        })?;
454        Ok(crate::Uuid::from_bytes(bytes))
455    }
456
457    #[cfg(test)]
458    mod tests {
459        use serde::de::{self, Error};
460        use serde_test::{Readable, Token};
461
462        use crate::{external::serde_support::ExpectedFormat, Uuid};
463
464        const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
465        const BRACED_UUID_STR: &'static str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
466
467        #[test]
468        fn test_serialize_as_braced() {
469            #[derive(serde_derive::Serialize)]
470            struct Struct(#[serde(with = "super")] crate::Uuid);
471
472            let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
473            serde_test::assert_ser_tokens(
474                &u,
475                &[
476                    Token::NewtypeStruct { name: "Struct" },
477                    Token::Str(BRACED_UUID_STR),
478                ],
479            );
480        }
481
482        #[test]
483        fn test_de_from_braced() {
484            #[derive(PartialEq, Debug, serde_derive::Deserialize)]
485            struct Struct(#[serde(with = "super")] crate::Uuid);
486            let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
487            serde_test::assert_de_tokens::<Struct>(
488                &s,
489                &[
490                    Token::TupleStruct {
491                        name: "Struct",
492                        len: 1,
493                    },
494                    Token::BorrowedStr(BRACED_UUID_STR),
495                    Token::TupleStructEnd,
496                ],
497            );
498        }
499
500        #[test]
501        fn test_de_reject_hypenated() {
502            #[derive(PartialEq, Debug, serde_derive::Deserialize)]
503            struct Struct(#[serde(with = "super")] crate::Uuid);
504            serde_test::assert_de_tokens_error::<Readable<Struct>>(
505                &[
506                    Token::TupleStruct {
507                        name: "Struct",
508                        len: 1,
509                    },
510                    Token::BorrowedStr(HYPHENATED_UUID_STR),
511                    Token::TupleStructEnd,
512                ],
513                &format!(
514                    "{}",
515                    de::value::Error::invalid_value(
516                        de::Unexpected::Str(HYPHENATED_UUID_STR),
517                        &ExpectedFormat::Braced,
518                    )
519                ),
520            );
521        }
522    }
523}
524
525/// Serialize from a [`Uuid`] as a `uuid::fmt::Urn`
526///
527/// [`Uuid`]: ../../struct.Uuid.html
528///
529/// ## Example
530///
531/// ```rust
532/// #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
533/// struct StructA {
534///     // This will change both serailization and deserialization
535///     #[serde(with = "uuid::serde::urn")]
536///     id: uuid::Uuid,
537/// }
538///
539/// #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
540/// struct StructB {
541///     // This will be serialized as uuid::fmt::Urn and deserialize from all valid formats
542///     #[serde(serialize_with = "uuid::serde::urn::serialize")]
543///     id: uuid::Uuid,
544/// }
545/// ```
546pub mod urn {
547    use serde::{de, Deserialize};
548
549    use crate::parser::parse_urn;
550
551    use super::ExpectedFormat;
552
553    /// Serialize from a [`Uuid`] as a `uuid::fmt::Urn`
554    ///
555    /// [`Uuid`]: ../../struct.Uuid.html
556    ///
557    /// # Example
558    ///
559    /// ```rust
560    /// #[derive(serde_derive::Serialize)]
561    /// struct Struct {
562    ///     // This will be serialize as uuid::fmt::Urn
563    ///     #[serde(serialize_with = "uuid::serde::urn::serialize")]
564    ///     id: uuid::Uuid,
565    /// }
566    ///
567    /// ```
568    pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
569    where
570        S: serde::Serializer,
571    {
572        serde::Serialize::serialize(u.as_urn(), serializer)
573    }
574
575    /// Deserialize a urn Uuid string as a [`Uuid`]
576    ///
577    /// [`Uuid`]: ../../struct.Uuid.html
578    pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
579    where
580        D: serde::Deserializer<'de>,
581    {
582        let s = <&str as Deserialize>::deserialize(deserializer)?;
583        let bytes = parse_urn(s.as_bytes())
584            .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Urn))?;
585        Ok(crate::Uuid::from_bytes(bytes))
586    }
587
588    #[cfg(test)]
589    mod tests {
590        use serde::de::{self, Error};
591        use serde_test::{Readable, Token};
592
593        use crate::{external::serde_support::ExpectedFormat, Uuid};
594
595        const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
596        const URN_UUID_STR: &'static str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
597
598        #[test]
599        fn test_serialize_as_urn() {
600            #[derive(serde_derive::Serialize)]
601            struct Struct(#[serde(with = "super")] crate::Uuid);
602
603            let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
604            serde_test::assert_ser_tokens(
605                &u,
606                &[
607                    Token::NewtypeStruct { name: "Struct" },
608                    Token::Str(URN_UUID_STR),
609                ],
610            );
611        }
612
613        #[test]
614        fn test_de_from_urn() {
615            #[derive(PartialEq, Debug, serde_derive::Deserialize)]
616            struct Struct(#[serde(with = "super")] crate::Uuid);
617            let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
618            serde_test::assert_de_tokens::<Struct>(
619                &s,
620                &[
621                    Token::TupleStruct {
622                        name: "Struct",
623                        len: 1,
624                    },
625                    Token::BorrowedStr(URN_UUID_STR),
626                    Token::TupleStructEnd,
627                ],
628            );
629        }
630
631        #[test]
632        fn test_de_reject_hypenated() {
633            #[derive(PartialEq, Debug, serde_derive::Deserialize)]
634            struct Struct(#[serde(with = "super")] crate::Uuid);
635            serde_test::assert_de_tokens_error::<Readable<Struct>>(
636                &[
637                    Token::TupleStruct {
638                        name: "Struct",
639                        len: 1,
640                    },
641                    Token::BorrowedStr(HYPHENATED_UUID_STR),
642                    Token::TupleStructEnd,
643                ],
644                &format!(
645                    "{}",
646                    de::value::Error::invalid_value(
647                        de::Unexpected::Str(HYPHENATED_UUID_STR),
648                        &ExpectedFormat::Urn,
649                    )
650                ),
651            );
652        }
653    }
654}
655
656#[cfg(test)]
657mod serde_tests {
658    use super::*;
659
660    use serde_test::{Compact, Configure, Readable, Token};
661
662    #[test]
663    fn test_serialize_readable_string() {
664        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
665        let u = Uuid::parse_str(uuid_str).unwrap();
666        serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
667    }
668
669    #[test]
670    fn test_deserialize_readable_compact() {
671        let uuid_bytes = b"F9168C5E-CEB2-4F";
672        let u = Uuid::from_slice(uuid_bytes).unwrap();
673
674        serde_test::assert_de_tokens(
675            &u.readable(),
676            &[
677                serde_test::Token::Tuple { len: 16 },
678                serde_test::Token::U8(uuid_bytes[0]),
679                serde_test::Token::U8(uuid_bytes[1]),
680                serde_test::Token::U8(uuid_bytes[2]),
681                serde_test::Token::U8(uuid_bytes[3]),
682                serde_test::Token::U8(uuid_bytes[4]),
683                serde_test::Token::U8(uuid_bytes[5]),
684                serde_test::Token::U8(uuid_bytes[6]),
685                serde_test::Token::U8(uuid_bytes[7]),
686                serde_test::Token::U8(uuid_bytes[8]),
687                serde_test::Token::U8(uuid_bytes[9]),
688                serde_test::Token::U8(uuid_bytes[10]),
689                serde_test::Token::U8(uuid_bytes[11]),
690                serde_test::Token::U8(uuid_bytes[12]),
691                serde_test::Token::U8(uuid_bytes[13]),
692                serde_test::Token::U8(uuid_bytes[14]),
693                serde_test::Token::U8(uuid_bytes[15]),
694                serde_test::Token::TupleEnd,
695            ],
696        );
697    }
698
699    #[test]
700    fn test_deserialize_readable_bytes() {
701        let uuid_bytes = b"F9168C5E-CEB2-4F";
702        let u = Uuid::from_slice(uuid_bytes).unwrap();
703
704        serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
705    }
706
707    #[test]
708    fn test_serialize_hyphenated() {
709        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
710        let u = Uuid::parse_str(uuid_str).unwrap();
711        serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
712    }
713
714    #[test]
715    fn test_serialize_simple() {
716        let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
717        let u = Uuid::parse_str(uuid_str).unwrap();
718        serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
719    }
720
721    #[test]
722    fn test_serialize_urn() {
723        let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
724        let u = Uuid::parse_str(uuid_str).unwrap();
725        serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
726    }
727
728    #[test]
729    fn test_serialize_braced() {
730        let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
731        let u = Uuid::parse_str(uuid_str).unwrap();
732        serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
733    }
734
735    #[test]
736    fn test_serialize_non_human_readable() {
737        let uuid_bytes = b"F9168C5E-CEB2-4F";
738        let u = Uuid::from_slice(uuid_bytes).unwrap();
739        serde_test::assert_tokens(
740            &u.compact(),
741            &[serde_test::Token::Bytes(&[
742                70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
743            ])],
744        );
745    }
746
747    #[test]
748    fn test_de_failure() {
749        serde_test::assert_de_tokens_error::<Readable<Uuid>>(
750            &[Token::Str("hello_world")],
751            "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1",
752        );
753
754        serde_test::assert_de_tokens_error::<Compact<Uuid>>(
755            &[Token::Bytes(b"hello_world")],
756            "UUID parsing failed: invalid length: expected 16 bytes, found 11",
757        );
758    }
759
760    #[test]
761    fn test_serde_non_nil_uuid() {
762        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
763        let uuid = Uuid::parse_str(uuid_str).unwrap();
764        let non_nil_uuid = NonNilUuid::try_from(uuid).unwrap();
765
766        serde_test::assert_ser_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
767        serde_test::assert_de_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
768    }
769}