1use 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 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 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 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
259pub mod simple {
281 use serde::{de, Deserialize};
282
283 use crate::{parser::parse_simple, Uuid};
284
285 use super::ExpectedFormat;
286
287 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 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
391pub mod braced {
413 use serde::{de, Deserialize};
414
415 use crate::parser::parse_braced;
416
417 use super::ExpectedFormat;
418
419 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 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
523pub mod urn {
545 use serde::{de, Deserialize};
546
547 use crate::parser::parse_urn;
548
549 use super::ExpectedFormat;
550
551 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 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}