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