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(|_| {
149 de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID")
150 })
151 }
152}
153
154enum ExpectedFormat {
155 Simple,
156 Braced,
157 Urn,
158}
159
160impl std::fmt::Display for ExpectedFormat {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 let s = match self {
163 ExpectedFormat::Simple => "a simple Uuid string like 67e5504410b1426f9247bb680e5fe0c8",
164 ExpectedFormat::Braced => {
165 "a braced Uuid string like {67e55044-10b1-426f-9247-bb680e5fe0c8}"
166 }
167 ExpectedFormat::Urn => {
168 "a URN Uuid string like urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8"
169 }
170 };
171 f.write_str(s)
172 }
173}
174
175impl de::Expected for ExpectedFormat {
176 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
177 <ExpectedFormat as std::fmt::Display>::fmt(self, formatter)
178 }
179}
180
181pub mod compact {
182 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
190 where
191 S: serde::Serializer,
192 {
193 serde::Serialize::serialize(u.as_bytes(), serializer)
194 }
195
196 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
200 where
201 D: serde::Deserializer<'de>,
202 {
203 let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?;
204
205 Ok(crate::Uuid::from_bytes(bytes))
206 }
207
208 #[cfg(test)]
209 mod tests {
210 use serde_derive::*;
211 use serde_test::Configure;
212
213 #[test]
214 fn test_serialize_compact() {
215 #[derive(Serialize, Debug, Deserialize, PartialEq)]
216 struct UuidContainer {
217 #[serde(with = "crate::serde::compact")]
218 u: crate::Uuid,
219 }
220
221 let uuid_bytes = b"F9168C5E-CEB2-4F";
222 let container = UuidContainer {
223 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
224 };
225
226 serde_test::assert_tokens(
229 &container.compact(),
230 &[
231 serde_test::Token::Struct {
232 name: "UuidContainer",
233 len: 1,
234 },
235 serde_test::Token::Str("u"),
236 serde_test::Token::Tuple { len: 16 },
237 serde_test::Token::U8(uuid_bytes[0]),
238 serde_test::Token::U8(uuid_bytes[1]),
239 serde_test::Token::U8(uuid_bytes[2]),
240 serde_test::Token::U8(uuid_bytes[3]),
241 serde_test::Token::U8(uuid_bytes[4]),
242 serde_test::Token::U8(uuid_bytes[5]),
243 serde_test::Token::U8(uuid_bytes[6]),
244 serde_test::Token::U8(uuid_bytes[7]),
245 serde_test::Token::U8(uuid_bytes[8]),
246 serde_test::Token::U8(uuid_bytes[9]),
247 serde_test::Token::U8(uuid_bytes[10]),
248 serde_test::Token::U8(uuid_bytes[11]),
249 serde_test::Token::U8(uuid_bytes[12]),
250 serde_test::Token::U8(uuid_bytes[13]),
251 serde_test::Token::U8(uuid_bytes[14]),
252 serde_test::Token::U8(uuid_bytes[15]),
253 serde_test::Token::TupleEnd,
254 serde_test::Token::StructEnd,
255 ],
256 )
257 }
258 }
259}
260
261pub mod simple {
283 use serde::{de, Deserialize};
284
285 use crate::{parser::parse_simple, Uuid};
286
287 use super::ExpectedFormat;
288
289 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
305 where
306 S: serde::Serializer,
307 {
308 serde::Serialize::serialize(u.as_simple(), serializer)
309 }
310
311 pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
315 where
316 D: serde::Deserializer<'de>,
317 {
318 let s = <&str as Deserialize>::deserialize(deserializer)?;
319 let bytes = parse_simple(s.as_bytes()).map_err(|_| {
320 de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Simple)
321 })?;
322 Ok(Uuid::from_bytes(bytes))
323 }
324
325 #[cfg(test)]
326 mod tests {
327 use serde::de::{self, Error};
328 use serde_test::{Readable, Token};
329
330 use crate::{external::serde_support::ExpectedFormat, Uuid};
331
332 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
333 const SIMPLE_UUID_STR: &'static str = "f9168c5eceb24faab6bf329bf39fa1e4";
334
335 #[test]
336 fn test_serialize_as_simple() {
337 #[derive(serde_derive::Serialize)]
338 struct Struct(#[serde(with = "super")] crate::Uuid);
339
340 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
341 serde_test::assert_ser_tokens(
342 &u,
343 &[
344 Token::NewtypeStruct { name: "Struct" },
345 Token::Str(SIMPLE_UUID_STR),
346 ],
347 );
348 }
349
350 #[test]
351 fn test_de_from_simple() {
352 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
353 struct Struct(#[serde(with = "super")] crate::Uuid);
354 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
355 serde_test::assert_de_tokens::<Struct>(
356 &s,
357 &[
358 Token::TupleStruct {
359 name: "Struct",
360 len: 1,
361 },
362 Token::BorrowedStr(SIMPLE_UUID_STR),
363 Token::TupleStructEnd,
364 ],
365 );
366 }
367
368 #[test]
369 fn test_de_reject_hypenated() {
370 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
371 struct Struct(#[serde(with = "super")] crate::Uuid);
372 serde_test::assert_de_tokens_error::<Readable<Struct>>(
373 &[
374 Token::TupleStruct {
375 name: "Struct",
376 len: 1,
377 },
378 Token::BorrowedStr(HYPHENATED_UUID_STR),
379 Token::TupleStructEnd,
380 ],
381 &format!(
382 "{}",
383 de::value::Error::invalid_value(
384 de::Unexpected::Str(HYPHENATED_UUID_STR),
385 &ExpectedFormat::Simple,
386 )
387 ),
388 );
389 }
390 }
391}
392
393pub mod braced {
415 use serde::{de, Deserialize};
416
417 use crate::parser::parse_braced;
418
419 use super::ExpectedFormat;
420
421 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
437 where
438 S: serde::Serializer,
439 {
440 serde::Serialize::serialize(u.as_braced(), serializer)
441 }
442
443 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
447 where
448 D: serde::Deserializer<'de>,
449 {
450 let s = <&str as Deserialize>::deserialize(deserializer)?;
451 let bytes = parse_braced(s.as_bytes()).map_err(|_| {
452 de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Braced)
453 })?;
454 Ok(crate::Uuid::from_bytes(bytes))
455 }
456
457 #[cfg(test)]
458 mod tests {
459 use serde::de::{self, Error};
460 use serde_test::{Readable, Token};
461
462 use crate::{external::serde_support::ExpectedFormat, Uuid};
463
464 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
465 const BRACED_UUID_STR: &'static str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
466
467 #[test]
468 fn test_serialize_as_braced() {
469 #[derive(serde_derive::Serialize)]
470 struct Struct(#[serde(with = "super")] crate::Uuid);
471
472 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
473 serde_test::assert_ser_tokens(
474 &u,
475 &[
476 Token::NewtypeStruct { name: "Struct" },
477 Token::Str(BRACED_UUID_STR),
478 ],
479 );
480 }
481
482 #[test]
483 fn test_de_from_braced() {
484 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
485 struct Struct(#[serde(with = "super")] crate::Uuid);
486 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
487 serde_test::assert_de_tokens::<Struct>(
488 &s,
489 &[
490 Token::TupleStruct {
491 name: "Struct",
492 len: 1,
493 },
494 Token::BorrowedStr(BRACED_UUID_STR),
495 Token::TupleStructEnd,
496 ],
497 );
498 }
499
500 #[test]
501 fn test_de_reject_hypenated() {
502 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
503 struct Struct(#[serde(with = "super")] crate::Uuid);
504 serde_test::assert_de_tokens_error::<Readable<Struct>>(
505 &[
506 Token::TupleStruct {
507 name: "Struct",
508 len: 1,
509 },
510 Token::BorrowedStr(HYPHENATED_UUID_STR),
511 Token::TupleStructEnd,
512 ],
513 &format!(
514 "{}",
515 de::value::Error::invalid_value(
516 de::Unexpected::Str(HYPHENATED_UUID_STR),
517 &ExpectedFormat::Braced,
518 )
519 ),
520 );
521 }
522 }
523}
524
525pub mod urn {
547 use serde::{de, Deserialize};
548
549 use crate::parser::parse_urn;
550
551 use super::ExpectedFormat;
552
553 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
569 where
570 S: serde::Serializer,
571 {
572 serde::Serialize::serialize(u.as_urn(), serializer)
573 }
574
575 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
579 where
580 D: serde::Deserializer<'de>,
581 {
582 let s = <&str as Deserialize>::deserialize(deserializer)?;
583 let bytes = parse_urn(s.as_bytes())
584 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Urn))?;
585 Ok(crate::Uuid::from_bytes(bytes))
586 }
587
588 #[cfg(test)]
589 mod tests {
590 use serde::de::{self, Error};
591 use serde_test::{Readable, Token};
592
593 use crate::{external::serde_support::ExpectedFormat, Uuid};
594
595 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
596 const URN_UUID_STR: &'static str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
597
598 #[test]
599 fn test_serialize_as_urn() {
600 #[derive(serde_derive::Serialize)]
601 struct Struct(#[serde(with = "super")] crate::Uuid);
602
603 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
604 serde_test::assert_ser_tokens(
605 &u,
606 &[
607 Token::NewtypeStruct { name: "Struct" },
608 Token::Str(URN_UUID_STR),
609 ],
610 );
611 }
612
613 #[test]
614 fn test_de_from_urn() {
615 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
616 struct Struct(#[serde(with = "super")] crate::Uuid);
617 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
618 serde_test::assert_de_tokens::<Struct>(
619 &s,
620 &[
621 Token::TupleStruct {
622 name: "Struct",
623 len: 1,
624 },
625 Token::BorrowedStr(URN_UUID_STR),
626 Token::TupleStructEnd,
627 ],
628 );
629 }
630
631 #[test]
632 fn test_de_reject_hypenated() {
633 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
634 struct Struct(#[serde(with = "super")] crate::Uuid);
635 serde_test::assert_de_tokens_error::<Readable<Struct>>(
636 &[
637 Token::TupleStruct {
638 name: "Struct",
639 len: 1,
640 },
641 Token::BorrowedStr(HYPHENATED_UUID_STR),
642 Token::TupleStructEnd,
643 ],
644 &format!(
645 "{}",
646 de::value::Error::invalid_value(
647 de::Unexpected::Str(HYPHENATED_UUID_STR),
648 &ExpectedFormat::Urn,
649 )
650 ),
651 );
652 }
653 }
654}
655
656#[cfg(test)]
657mod serde_tests {
658 use super::*;
659
660 use serde_test::{Compact, Configure, Readable, Token};
661
662 #[test]
663 fn test_serialize_readable_string() {
664 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
665 let u = Uuid::parse_str(uuid_str).unwrap();
666 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
667 }
668
669 #[test]
670 fn test_deserialize_readable_compact() {
671 let uuid_bytes = b"F9168C5E-CEB2-4F";
672 let u = Uuid::from_slice(uuid_bytes).unwrap();
673
674 serde_test::assert_de_tokens(
675 &u.readable(),
676 &[
677 serde_test::Token::Tuple { len: 16 },
678 serde_test::Token::U8(uuid_bytes[0]),
679 serde_test::Token::U8(uuid_bytes[1]),
680 serde_test::Token::U8(uuid_bytes[2]),
681 serde_test::Token::U8(uuid_bytes[3]),
682 serde_test::Token::U8(uuid_bytes[4]),
683 serde_test::Token::U8(uuid_bytes[5]),
684 serde_test::Token::U8(uuid_bytes[6]),
685 serde_test::Token::U8(uuid_bytes[7]),
686 serde_test::Token::U8(uuid_bytes[8]),
687 serde_test::Token::U8(uuid_bytes[9]),
688 serde_test::Token::U8(uuid_bytes[10]),
689 serde_test::Token::U8(uuid_bytes[11]),
690 serde_test::Token::U8(uuid_bytes[12]),
691 serde_test::Token::U8(uuid_bytes[13]),
692 serde_test::Token::U8(uuid_bytes[14]),
693 serde_test::Token::U8(uuid_bytes[15]),
694 serde_test::Token::TupleEnd,
695 ],
696 );
697 }
698
699 #[test]
700 fn test_deserialize_readable_bytes() {
701 let uuid_bytes = b"F9168C5E-CEB2-4F";
702 let u = Uuid::from_slice(uuid_bytes).unwrap();
703
704 serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
705 }
706
707 #[test]
708 fn test_serialize_hyphenated() {
709 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
710 let u = Uuid::parse_str(uuid_str).unwrap();
711 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
712 }
713
714 #[test]
715 fn test_serialize_simple() {
716 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
717 let u = Uuid::parse_str(uuid_str).unwrap();
718 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
719 }
720
721 #[test]
722 fn test_serialize_urn() {
723 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
724 let u = Uuid::parse_str(uuid_str).unwrap();
725 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
726 }
727
728 #[test]
729 fn test_serialize_braced() {
730 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
731 let u = Uuid::parse_str(uuid_str).unwrap();
732 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
733 }
734
735 #[test]
736 fn test_serialize_non_human_readable() {
737 let uuid_bytes = b"F9168C5E-CEB2-4F";
738 let u = Uuid::from_slice(uuid_bytes).unwrap();
739 serde_test::assert_tokens(
740 &u.compact(),
741 &[serde_test::Token::Bytes(&[
742 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
743 ])],
744 );
745 }
746
747 #[test]
748 fn test_de_failure() {
749 serde_test::assert_de_tokens_error::<Readable<Uuid>>(
750 &[Token::Str("hello_world")],
751 "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1",
752 );
753
754 serde_test::assert_de_tokens_error::<Compact<Uuid>>(
755 &[Token::Bytes(b"hello_world")],
756 "UUID parsing failed: invalid length: expected 16 bytes, found 11",
757 );
758 }
759
760 #[test]
761 fn test_serde_non_nil_uuid() {
762 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
763 let uuid = Uuid::parse_str(uuid_str).unwrap();
764 let non_nil_uuid = NonNilUuid::try_from(uuid).unwrap();
765
766 serde_test::assert_ser_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
767 serde_test::assert_de_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
768 }
769}