1use crate::{
13 error::*,
14 fmt::{Braced, Hyphenated, Simple, Urn},
15 std::fmt,
16 Uuid,
17};
18use serde::{
19 de::{self, Error as _},
20 Deserialize, Deserializer, Serialize, Serializer,
21};
22
23impl Serialize for Uuid {
24 fn serialize<S: Serializer>(
25 &self,
26 serializer: S,
27 ) -> Result<S::Ok, S::Error> {
28 if serializer.is_human_readable() {
29 serializer.serialize_str(
30 self.hyphenated().encode_lower(&mut Uuid::encode_buffer()),
31 )
32 } else {
33 serializer.serialize_bytes(self.as_bytes())
34 }
35 }
36}
37
38impl Serialize for Hyphenated {
39 fn serialize<S: Serializer>(
40 &self,
41 serializer: S,
42 ) -> Result<S::Ok, S::Error> {
43 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
44 }
45}
46
47impl Serialize for Simple {
48 fn serialize<S: Serializer>(
49 &self,
50 serializer: S,
51 ) -> 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>(
58 &self,
59 serializer: S,
60 ) -> Result<S::Ok, S::Error> {
61 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
62 }
63}
64
65impl Serialize for Braced {
66 fn serialize<S: Serializer>(
67 &self,
68 serializer: S,
69 ) -> Result<S::Ok, S::Error> {
70 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
71 }
72}
73
74impl<'de> Deserialize<'de> for Uuid {
75 fn deserialize<D: Deserializer<'de>>(
76 deserializer: D,
77 ) -> Result<Self, D::Error> {
78 fn de_error<E: de::Error>(e: Error) -> E {
79 E::custom(format_args!("UUID parsing failed: {}", e))
80 }
81
82 if deserializer.is_human_readable() {
83 struct UuidVisitor;
84
85 impl<'vi> de::Visitor<'vi> for UuidVisitor {
86 type Value = Uuid;
87
88 fn expecting(
89 &self,
90 formatter: &mut fmt::Formatter<'_>,
91 ) -> fmt::Result {
92 write!(formatter, "a UUID string")
93 }
94
95 fn visit_str<E: de::Error>(
96 self,
97 value: &str,
98 ) -> Result<Uuid, E> {
99 value.parse::<Uuid>().map_err(de_error)
100 }
101
102 fn visit_bytes<E: de::Error>(
103 self,
104 value: &[u8],
105 ) -> Result<Uuid, E> {
106 Uuid::from_slice(value).map_err(de_error)
107 }
108
109 fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error>
110 where
111 A: de::SeqAccess<'vi>,
112 {
113 #[rustfmt::skip]
114 let bytes = [
115 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
116 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
117 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
118 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
119 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
120 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
121 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
122 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
123 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
124 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
125 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
126 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
127 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
128 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
129 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
130 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
131 ];
132
133 Ok(Uuid::from_bytes(bytes))
134 }
135 }
136
137 deserializer.deserialize_str(UuidVisitor)
138 } else {
139 struct UuidBytesVisitor;
140
141 impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
142 type Value = Uuid;
143
144 fn expecting(
145 &self,
146 formatter: &mut fmt::Formatter<'_>,
147 ) -> fmt::Result {
148 write!(formatter, "bytes")
149 }
150
151 fn visit_bytes<E: de::Error>(
152 self,
153 value: &[u8],
154 ) -> Result<Uuid, E> {
155 Uuid::from_slice(value).map_err(de_error)
156 }
157 }
158
159 deserializer.deserialize_bytes(UuidBytesVisitor)
160 }
161 }
162}
163
164pub mod compact {
165 pub fn serialize<S>(
173 u: &crate::Uuid,
174 serializer: S,
175 ) -> Result<S::Ok, S::Error>
176 where
177 S: serde::Serializer,
178 {
179 serde::Serialize::serialize(u.as_bytes(), serializer)
180 }
181
182 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
186 where
187 D: serde::Deserializer<'de>,
188 {
189 let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?;
190
191 Ok(crate::Uuid::from_bytes(bytes))
192 }
193
194 #[cfg(test)]
195 mod tests {
196 use serde_derive::*;
197 use serde_test::{self, Configure};
198
199 #[test]
200 fn test_serialize_compact() {
201 #[derive(Serialize, Debug, Deserialize, PartialEq)]
202 struct UuidContainer {
203 #[serde(with = "crate::serde::compact")]
204 u: crate::Uuid,
205 }
206
207 let uuid_bytes = b"F9168C5E-CEB2-4F";
208 let container = UuidContainer {
209 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
210 };
211
212 serde_test::assert_tokens(
215 &container.compact(),
216 &[
217 serde_test::Token::Struct {
218 name: "UuidContainer",
219 len: 1,
220 },
221 serde_test::Token::Str("u"),
222 serde_test::Token::Tuple { len: 16 },
223 serde_test::Token::U8(uuid_bytes[0]),
224 serde_test::Token::U8(uuid_bytes[1]),
225 serde_test::Token::U8(uuid_bytes[2]),
226 serde_test::Token::U8(uuid_bytes[3]),
227 serde_test::Token::U8(uuid_bytes[4]),
228 serde_test::Token::U8(uuid_bytes[5]),
229 serde_test::Token::U8(uuid_bytes[6]),
230 serde_test::Token::U8(uuid_bytes[7]),
231 serde_test::Token::U8(uuid_bytes[8]),
232 serde_test::Token::U8(uuid_bytes[9]),
233 serde_test::Token::U8(uuid_bytes[10]),
234 serde_test::Token::U8(uuid_bytes[11]),
235 serde_test::Token::U8(uuid_bytes[12]),
236 serde_test::Token::U8(uuid_bytes[13]),
237 serde_test::Token::U8(uuid_bytes[14]),
238 serde_test::Token::U8(uuid_bytes[15]),
239 serde_test::Token::TupleEnd,
240 serde_test::Token::StructEnd,
241 ],
242 )
243 }
244 }
245}
246
247#[cfg(test)]
248mod serde_tests {
249 use super::*;
250
251 use serde_test::{Compact, Configure, Readable, Token};
252
253 #[test]
254 fn test_serialize_readable_string() {
255 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
256 let u = Uuid::parse_str(uuid_str).unwrap();
257 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
258 }
259
260 #[test]
261 fn test_deserialize_readable_compact() {
262 let uuid_bytes = b"F9168C5E-CEB2-4F";
263 let u = Uuid::from_slice(uuid_bytes).unwrap();
264
265 serde_test::assert_de_tokens(
266 &u.readable(),
267 &[
268 serde_test::Token::Tuple { len: 16 },
269 serde_test::Token::U8(uuid_bytes[0]),
270 serde_test::Token::U8(uuid_bytes[1]),
271 serde_test::Token::U8(uuid_bytes[2]),
272 serde_test::Token::U8(uuid_bytes[3]),
273 serde_test::Token::U8(uuid_bytes[4]),
274 serde_test::Token::U8(uuid_bytes[5]),
275 serde_test::Token::U8(uuid_bytes[6]),
276 serde_test::Token::U8(uuid_bytes[7]),
277 serde_test::Token::U8(uuid_bytes[8]),
278 serde_test::Token::U8(uuid_bytes[9]),
279 serde_test::Token::U8(uuid_bytes[10]),
280 serde_test::Token::U8(uuid_bytes[11]),
281 serde_test::Token::U8(uuid_bytes[12]),
282 serde_test::Token::U8(uuid_bytes[13]),
283 serde_test::Token::U8(uuid_bytes[14]),
284 serde_test::Token::U8(uuid_bytes[15]),
285 serde_test::Token::TupleEnd,
286 ],
287 );
288 }
289
290 #[test]
291 fn test_deserialize_readable_bytes() {
292 let uuid_bytes = b"F9168C5E-CEB2-4F";
293 let u = Uuid::from_slice(uuid_bytes).unwrap();
294
295 serde_test::assert_de_tokens(
296 &u.readable(),
297 &[serde_test::Token::Bytes(uuid_bytes)],
298 );
299 }
300
301 #[test]
302 fn test_serialize_hyphenated() {
303 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
304 let u = Uuid::parse_str(uuid_str).unwrap();
305 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
306 }
307
308 #[test]
309 fn test_serialize_simple() {
310 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
311 let u = Uuid::parse_str(uuid_str).unwrap();
312 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
313 }
314
315 #[test]
316 fn test_serialize_urn() {
317 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
318 let u = Uuid::parse_str(uuid_str).unwrap();
319 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
320 }
321
322 #[test]
323 fn test_serialize_braced() {
324 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
325 let u = Uuid::parse_str(uuid_str).unwrap();
326 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
327 }
328
329 #[test]
330 fn test_serialize_non_human_readable() {
331 let uuid_bytes = b"F9168C5E-CEB2-4F";
332 let u = Uuid::from_slice(uuid_bytes).unwrap();
333 serde_test::assert_tokens(
334 &u.compact(),
335 &[serde_test::Token::Bytes(&[
336 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
337 ])],
338 );
339 }
340
341 #[test]
342 fn test_de_failure() {
343 serde_test::assert_de_tokens_error::<Readable<Uuid>>(
344 &[Token::Str("hello_world")],
345 "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `h` at 1",
346 );
347
348 serde_test::assert_de_tokens_error::<Compact<Uuid>>(
349 &[Token::Bytes(b"hello_world")],
350 "UUID parsing failed: invalid length: expected 16 bytes, found 11",
351 );
352 }
353}