Skip to main content

uuid/
serde.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 std::fmt;
13
14use serde::{
15    Deserialize, Deserializer, Serialize, Serializer,
16    de::{self, Error as _},
17};
18
19use crate::{Error, Uuid};
20
21impl Serialize for Uuid {
22    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
23        if serializer.is_human_readable() {
24            serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
25        } else {
26            serializer.serialize_bytes(self.as_bytes())
27        }
28    }
29}
30
31impl<'de> Deserialize<'de> for Uuid {
32    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33        fn de_error<E: de::Error>(err: Error) -> E {
34            E::custom(format_args!("UUID parsing failed: {}", err))
35        }
36
37        if deserializer.is_human_readable() {
38            struct UuidVisitor;
39
40            impl<'vi> de::Visitor<'vi> for UuidVisitor {
41                type Value = Uuid;
42
43                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
44                    write!(formatter, "a UUID string")
45                }
46
47                fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
48                    value.parse::<Uuid>().map_err(de_error)
49                }
50
51                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
52                    Uuid::from_slice(value).map_err(de_error)
53                }
54
55                fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error>
56                where
57                    A: de::SeqAccess<'vi>,
58                {
59                    #[rustfmt::skip]
60                    let bytes = [
61                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(0, &self)) },
62                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(1, &self)) },
63                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(2, &self)) },
64                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(3, &self)) },
65                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(4, &self)) },
66                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(5, &self)) },
67                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(6, &self)) },
68                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(7, &self)) },
69                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(8, &self)) },
70                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(9, &self)) },
71                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(10, &self)) },
72                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(11, &self)) },
73                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(12, &self)) },
74                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(13, &self)) },
75                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(14, &self)) },
76                        match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(15, &self)) },
77                    ];
78
79                    Ok(Uuid::from_bytes(bytes))
80                }
81            }
82
83            deserializer.deserialize_str(UuidVisitor)
84        } else {
85            struct UuidBytesVisitor;
86
87            impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
88                type Value = Uuid;
89
90                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
91                    write!(formatter, "bytes")
92                }
93
94                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
95                    Uuid::from_slice(value).map_err(de_error)
96                }
97            }
98
99            deserializer.deserialize_bytes(UuidBytesVisitor)
100        }
101    }
102}
103
104// #[cfg(test)]
105// mod serde_tests {
106//     use super::*;
107
108//     use serde::serde_test::{Compact, Configure, Readable, Token};
109
110//     #[test]
111//     fn test_serialize_readable_string() {
112//         let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
113//         let u = Uuid::parse_str(uuid_str).unwrap();
114//         serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
115//     }
116// }
117
118//     #[test]
119//     fn test_deserialize_readable_compact() {
120//         let uuid_bytes = b"F9168C5E-CEB2-4F";
121//         let u = Uuid::from_slice(uuid_bytes).unwrap();
122
123//         serde_test::assert_de_tokens(
124//             &u.readable(),
125//             &[
126//                 serde_test::Token::Tuple { len: 16 },
127//                 serde_test::Token::U8(uuid_bytes[0]),
128//                 serde_test::Token::U8(uuid_bytes[1]),
129//                 serde_test::Token::U8(uuid_bytes[2]),
130//                 serde_test::Token::U8(uuid_bytes[3]),
131//                 serde_test::Token::U8(uuid_bytes[4]),
132//                 serde_test::Token::U8(uuid_bytes[5]),
133//                 serde_test::Token::U8(uuid_bytes[6]),
134//                 serde_test::Token::U8(uuid_bytes[7]),
135//                 serde_test::Token::U8(uuid_bytes[8]),
136//                 serde_test::Token::U8(uuid_bytes[9]),
137//                 serde_test::Token::U8(uuid_bytes[10]),
138//                 serde_test::Token::U8(uuid_bytes[11]),
139//                 serde_test::Token::U8(uuid_bytes[12]),
140//                 serde_test::Token::U8(uuid_bytes[13]),
141//                 serde_test::Token::U8(uuid_bytes[14]),
142//                 serde_test::Token::U8(uuid_bytes[15]),
143//                 serde_test::Token::TupleEnd,
144//             ],
145//         );
146//     }
147
148//     #[test]
149//     fn test_deserialize_readable_bytes() {
150//         let uuid_bytes = b"F9168C5E-CEB2-4F";
151//         let u = Uuid::from_slice(uuid_bytes).unwrap();
152
153//         serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
154//     }
155
156//     #[test]
157//     fn test_serialize_hyphenated() {
158//         let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
159//         let u = Uuid::parse_str(uuid_str).unwrap();
160//         serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
161//     }
162
163//     #[test]
164//     fn test_serialize_simple() {
165//         let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
166//         let u = Uuid::parse_str(uuid_str).unwrap();
167//         serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
168//     }
169
170//     #[test]
171//     fn test_serialize_urn() {
172//         let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
173//         let u = Uuid::parse_str(uuid_str).unwrap();
174//         serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
175//     }
176
177//     #[test]
178//     fn test_serialize_braced() {
179//         let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
180//         let u = Uuid::parse_str(uuid_str).unwrap();
181//         serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
182//     }
183
184//     #[test]
185//     fn test_serialize_non_human_readable() {
186//         let uuid_bytes = b"F9168C5E-CEB2-4F";
187//         let u = Uuid::from_slice(uuid_bytes).unwrap();
188//         serde_test::assert_tokens(
189//             &u.compact(),
190//             &[serde_test::Token::Bytes(&[
191//                 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
192//             ])],
193//         );
194//     }
195
196//     #[test]
197//     fn test_de_failure() {
198//         serde_test::assert_de_tokens_error::<Readable<Uuid>>(
199//             &[Token::Str("hello_world")],
200//             "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1",
201//         );
202
203//         serde_test::assert_de_tokens_error::<Compact<Uuid>>(
204//             &[Token::Bytes(b"hello_world")],
205//             "UUID parsing failed: invalid length: expected 16 bytes, found 11",
206//         );
207//     }
208// }