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