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>(&self, serializer: S) -> Result<S::Ok, S::Error> {
25 if serializer.is_human_readable() {
26 serializer.serialize_str(self.hyphenated().encode_lower(&mut Uuid::encode_buffer()))
27 } else {
28 serializer.serialize_bytes(self.as_bytes())
29 }
30 }
31}
32
33impl Serialize for Hyphenated {
34 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
35 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
36 }
37}
38
39impl Serialize for Simple {
40 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
41 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
42 }
43}
44
45impl Serialize for Urn {
46 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
47 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
48 }
49}
50
51impl Serialize for Braced {
52 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
53 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
54 }
55}
56
57impl<'de> Deserialize<'de> for Uuid {
58 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
59 fn de_error<E: de::Error>(e: Error) -> E {
60 E::custom(format_args!("UUID parsing failed: {}", e))
61 }
62
63 if deserializer.is_human_readable() {
64 struct UuidVisitor;
65
66 impl<'vi> de::Visitor<'vi> for UuidVisitor {
67 type Value = Uuid;
68
69 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(formatter, "a UUID string")
71 }
72
73 fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
74 value.parse::<Uuid>().map_err(de_error)
75 }
76
77 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
78 Uuid::from_slice(value).map_err(de_error)
79 }
80
81 fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error>
82 where
83 A: de::SeqAccess<'vi>,
84 {
85 #[rustfmt::skip]
86 let bytes = [
87 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(0, &self)) },
88 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(1, &self)) },
89 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(2, &self)) },
90 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(3, &self)) },
91 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(4, &self)) },
92 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(5, &self)) },
93 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(6, &self)) },
94 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(7, &self)) },
95 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(8, &self)) },
96 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(9, &self)) },
97 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(10, &self)) },
98 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(11, &self)) },
99 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(12, &self)) },
100 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(13, &self)) },
101 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(14, &self)) },
102 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(15, &self)) },
103 ];
104
105 Ok(Uuid::from_bytes(bytes))
106 }
107 }
108
109 deserializer.deserialize_str(UuidVisitor)
110 } else {
111 struct UuidBytesVisitor;
112
113 impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
114 type Value = Uuid;
115
116 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
117 write!(formatter, "bytes")
118 }
119
120 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
121 Uuid::from_slice(value).map_err(de_error)
122 }
123 }
124
125 deserializer.deserialize_bytes(UuidBytesVisitor)
126 }
127 }
128}
129
130enum ExpectedFormat {
131 Simple,
132 Braced,
133 Urn,
134}
135
136impl std::fmt::Display for ExpectedFormat {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 let s = match self {
139 ExpectedFormat::Simple => "a simple Uuid string like 67e5504410b1426f9247bb680e5fe0c8",
140 ExpectedFormat::Braced => {
141 "a braced Uuid string like {67e55044-10b1-426f-9247-bb680e5fe0c8}"
142 }
143 ExpectedFormat::Urn => {
144 "a URN Uuid string like urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8"
145 }
146 };
147 f.write_str(s)
148 }
149}
150
151impl de::Expected for ExpectedFormat {
152 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
153 <ExpectedFormat as std::fmt::Display>::fmt(self, formatter)
154 }
155}
156
157pub mod compact {
158 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
166 where
167 S: serde::Serializer,
168 {
169 serde::Serialize::serialize(u.as_bytes(), serializer)
170 }
171
172 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
176 where
177 D: serde::Deserializer<'de>,
178 {
179 let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?;
180
181 Ok(crate::Uuid::from_bytes(bytes))
182 }
183
184 #[cfg(test)]
185 mod tests {
186 use serde_derive::*;
187 use serde_test::Configure;
188
189 #[test]
190 fn test_serialize_compact() {
191 #[derive(Serialize, Debug, Deserialize, PartialEq)]
192 struct UuidContainer {
193 #[serde(with = "crate::serde::compact")]
194 u: crate::Uuid,
195 }
196
197 let uuid_bytes = b"F9168C5E-CEB2-4F";
198 let container = UuidContainer {
199 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
200 };
201
202 serde_test::assert_tokens(
205 &container.compact(),
206 &[
207 serde_test::Token::Struct {
208 name: "UuidContainer",
209 len: 1,
210 },
211 serde_test::Token::Str("u"),
212 serde_test::Token::Tuple { len: 16 },
213 serde_test::Token::U8(uuid_bytes[0]),
214 serde_test::Token::U8(uuid_bytes[1]),
215 serde_test::Token::U8(uuid_bytes[2]),
216 serde_test::Token::U8(uuid_bytes[3]),
217 serde_test::Token::U8(uuid_bytes[4]),
218 serde_test::Token::U8(uuid_bytes[5]),
219 serde_test::Token::U8(uuid_bytes[6]),
220 serde_test::Token::U8(uuid_bytes[7]),
221 serde_test::Token::U8(uuid_bytes[8]),
222 serde_test::Token::U8(uuid_bytes[9]),
223 serde_test::Token::U8(uuid_bytes[10]),
224 serde_test::Token::U8(uuid_bytes[11]),
225 serde_test::Token::U8(uuid_bytes[12]),
226 serde_test::Token::U8(uuid_bytes[13]),
227 serde_test::Token::U8(uuid_bytes[14]),
228 serde_test::Token::U8(uuid_bytes[15]),
229 serde_test::Token::TupleEnd,
230 serde_test::Token::StructEnd,
231 ],
232 )
233 }
234 }
235}
236
237pub mod simple {
259 use serde::{de, Deserialize};
260
261 use crate::{parser::parse_simple, Uuid};
262
263 use super::ExpectedFormat;
264
265 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
281 where
282 S: serde::Serializer,
283 {
284 serde::Serialize::serialize(u.as_simple(), serializer)
285 }
286
287 pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
291 where
292 D: serde::Deserializer<'de>,
293 {
294 let s = <&str as Deserialize>::deserialize(deserializer)?;
295 let bytes = parse_simple(s.as_bytes()).map_err(|_| {
296 de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Simple)
297 })?;
298 Ok(Uuid::from_bytes(bytes))
299 }
300
301 #[cfg(test)]
302 mod tests {
303 use serde::de::{self, Error};
304 use serde_test::{Readable, Token};
305
306 use crate::{external::serde_support::ExpectedFormat, Uuid};
307
308 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
309 const SIMPLE_UUID_STR: &'static str = "f9168c5eceb24faab6bf329bf39fa1e4";
310
311 #[test]
312 fn test_serialize_as_simple() {
313 #[derive(serde_derive::Serialize)]
314 struct Struct(#[serde(with = "super")] crate::Uuid);
315
316 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
317 serde_test::assert_ser_tokens(
318 &u,
319 &[
320 Token::NewtypeStruct { name: "Struct" },
321 Token::Str(SIMPLE_UUID_STR),
322 ],
323 );
324 }
325
326 #[test]
327 fn test_de_from_simple() {
328 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
329 struct Struct(#[serde(with = "super")] crate::Uuid);
330 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
331 serde_test::assert_de_tokens::<Struct>(
332 &s,
333 &[
334 Token::TupleStruct {
335 name: "Struct",
336 len: 1,
337 },
338 Token::BorrowedStr(SIMPLE_UUID_STR),
339 Token::TupleStructEnd,
340 ],
341 );
342 }
343
344 #[test]
345 fn test_de_reject_hypenated() {
346 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
347 struct Struct(#[serde(with = "super")] crate::Uuid);
348 serde_test::assert_de_tokens_error::<Readable<Struct>>(
349 &[
350 Token::TupleStruct {
351 name: "Struct",
352 len: 1,
353 },
354 Token::BorrowedStr(HYPHENATED_UUID_STR),
355 Token::TupleStructEnd,
356 ],
357 &format!(
358 "{}",
359 de::value::Error::invalid_value(
360 de::Unexpected::Str(HYPHENATED_UUID_STR),
361 &ExpectedFormat::Simple,
362 )
363 ),
364 );
365 }
366 }
367}
368
369pub mod braced {
391 use serde::{de, Deserialize};
392
393 use crate::parser::parse_braced;
394
395 use super::ExpectedFormat;
396
397 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
413 where
414 S: serde::Serializer,
415 {
416 serde::Serialize::serialize(u.as_braced(), serializer)
417 }
418
419 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
423 where
424 D: serde::Deserializer<'de>,
425 {
426 let s = <&str as Deserialize>::deserialize(deserializer)?;
427 let bytes = parse_braced(s.as_bytes()).map_err(|_| {
428 de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Braced)
429 })?;
430 Ok(crate::Uuid::from_bytes(bytes))
431 }
432
433 #[cfg(test)]
434 mod tests {
435 use serde::de::{self, Error};
436 use serde_test::{Readable, Token};
437
438 use crate::{external::serde_support::ExpectedFormat, Uuid};
439
440 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
441 const BRACED_UUID_STR: &'static str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
442
443 #[test]
444 fn test_serialize_as_braced() {
445 #[derive(serde_derive::Serialize)]
446 struct Struct(#[serde(with = "super")] crate::Uuid);
447
448 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
449 serde_test::assert_ser_tokens(
450 &u,
451 &[
452 Token::NewtypeStruct { name: "Struct" },
453 Token::Str(BRACED_UUID_STR),
454 ],
455 );
456 }
457
458 #[test]
459 fn test_de_from_braced() {
460 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
461 struct Struct(#[serde(with = "super")] crate::Uuid);
462 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
463 serde_test::assert_de_tokens::<Struct>(
464 &s,
465 &[
466 Token::TupleStruct {
467 name: "Struct",
468 len: 1,
469 },
470 Token::BorrowedStr(BRACED_UUID_STR),
471 Token::TupleStructEnd,
472 ],
473 );
474 }
475
476 #[test]
477 fn test_de_reject_hypenated() {
478 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
479 struct Struct(#[serde(with = "super")] crate::Uuid);
480 serde_test::assert_de_tokens_error::<Readable<Struct>>(
481 &[
482 Token::TupleStruct {
483 name: "Struct",
484 len: 1,
485 },
486 Token::BorrowedStr(HYPHENATED_UUID_STR),
487 Token::TupleStructEnd,
488 ],
489 &format!(
490 "{}",
491 de::value::Error::invalid_value(
492 de::Unexpected::Str(HYPHENATED_UUID_STR),
493 &ExpectedFormat::Braced,
494 )
495 ),
496 );
497 }
498 }
499}
500
501pub mod urn {
523 use serde::{de, Deserialize};
524
525 use crate::parser::parse_urn;
526
527 use super::ExpectedFormat;
528
529 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
545 where
546 S: serde::Serializer,
547 {
548 serde::Serialize::serialize(u.as_urn(), serializer)
549 }
550
551 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
555 where
556 D: serde::Deserializer<'de>,
557 {
558 let s = <&str as Deserialize>::deserialize(deserializer)?;
559 let bytes = parse_urn(s.as_bytes())
560 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Urn))?;
561 Ok(crate::Uuid::from_bytes(bytes))
562 }
563
564 #[cfg(test)]
565 mod tests {
566 use serde::de::{self, Error};
567 use serde_test::{Readable, Token};
568
569 use crate::{external::serde_support::ExpectedFormat, Uuid};
570
571 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
572 const URN_UUID_STR: &'static str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
573
574 #[test]
575 fn test_serialize_as_urn() {
576 #[derive(serde_derive::Serialize)]
577 struct Struct(#[serde(with = "super")] crate::Uuid);
578
579 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
580 serde_test::assert_ser_tokens(
581 &u,
582 &[
583 Token::NewtypeStruct { name: "Struct" },
584 Token::Str(URN_UUID_STR),
585 ],
586 );
587 }
588
589 #[test]
590 fn test_de_from_urn() {
591 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
592 struct Struct(#[serde(with = "super")] crate::Uuid);
593 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
594 serde_test::assert_de_tokens::<Struct>(
595 &s,
596 &[
597 Token::TupleStruct {
598 name: "Struct",
599 len: 1,
600 },
601 Token::BorrowedStr(URN_UUID_STR),
602 Token::TupleStructEnd,
603 ],
604 );
605 }
606
607 #[test]
608 fn test_de_reject_hypenated() {
609 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
610 struct Struct(#[serde(with = "super")] crate::Uuid);
611 serde_test::assert_de_tokens_error::<Readable<Struct>>(
612 &[
613 Token::TupleStruct {
614 name: "Struct",
615 len: 1,
616 },
617 Token::BorrowedStr(HYPHENATED_UUID_STR),
618 Token::TupleStructEnd,
619 ],
620 &format!(
621 "{}",
622 de::value::Error::invalid_value(
623 de::Unexpected::Str(HYPHENATED_UUID_STR),
624 &ExpectedFormat::Urn,
625 )
626 ),
627 );
628 }
629 }
630}
631
632#[cfg(test)]
633mod serde_tests {
634 use super::*;
635
636 use serde_test::{Compact, Configure, Readable, Token};
637
638 #[test]
639 fn test_serialize_readable_string() {
640 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
641 let u = Uuid::parse_str(uuid_str).unwrap();
642 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
643 }
644
645 #[test]
646 fn test_deserialize_readable_compact() {
647 let uuid_bytes = b"F9168C5E-CEB2-4F";
648 let u = Uuid::from_slice(uuid_bytes).unwrap();
649
650 serde_test::assert_de_tokens(
651 &u.readable(),
652 &[
653 serde_test::Token::Tuple { len: 16 },
654 serde_test::Token::U8(uuid_bytes[0]),
655 serde_test::Token::U8(uuid_bytes[1]),
656 serde_test::Token::U8(uuid_bytes[2]),
657 serde_test::Token::U8(uuid_bytes[3]),
658 serde_test::Token::U8(uuid_bytes[4]),
659 serde_test::Token::U8(uuid_bytes[5]),
660 serde_test::Token::U8(uuid_bytes[6]),
661 serde_test::Token::U8(uuid_bytes[7]),
662 serde_test::Token::U8(uuid_bytes[8]),
663 serde_test::Token::U8(uuid_bytes[9]),
664 serde_test::Token::U8(uuid_bytes[10]),
665 serde_test::Token::U8(uuid_bytes[11]),
666 serde_test::Token::U8(uuid_bytes[12]),
667 serde_test::Token::U8(uuid_bytes[13]),
668 serde_test::Token::U8(uuid_bytes[14]),
669 serde_test::Token::U8(uuid_bytes[15]),
670 serde_test::Token::TupleEnd,
671 ],
672 );
673 }
674
675 #[test]
676 fn test_deserialize_readable_bytes() {
677 let uuid_bytes = b"F9168C5E-CEB2-4F";
678 let u = Uuid::from_slice(uuid_bytes).unwrap();
679
680 serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
681 }
682
683 #[test]
684 fn test_serialize_hyphenated() {
685 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
686 let u = Uuid::parse_str(uuid_str).unwrap();
687 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
688 }
689
690 #[test]
691 fn test_serialize_simple() {
692 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
693 let u = Uuid::parse_str(uuid_str).unwrap();
694 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
695 }
696
697 #[test]
698 fn test_serialize_urn() {
699 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
700 let u = Uuid::parse_str(uuid_str).unwrap();
701 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
702 }
703
704 #[test]
705 fn test_serialize_braced() {
706 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
707 let u = Uuid::parse_str(uuid_str).unwrap();
708 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
709 }
710
711 #[test]
712 fn test_serialize_non_human_readable() {
713 let uuid_bytes = b"F9168C5E-CEB2-4F";
714 let u = Uuid::from_slice(uuid_bytes).unwrap();
715 serde_test::assert_tokens(
716 &u.compact(),
717 &[serde_test::Token::Bytes(&[
718 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
719 ])],
720 );
721 }
722
723 #[test]
724 fn test_de_failure() {
725 serde_test::assert_de_tokens_error::<Readable<Uuid>>(
726 &[Token::Str("hello_world")],
727 "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1",
728 );
729
730 serde_test::assert_de_tokens_error::<Compact<Uuid>>(
731 &[Token::Bytes(b"hello_world")],
732 "UUID parsing failed: invalid length: expected 16 bytes, found 11",
733 );
734 }
735}