1use core::marker::PhantomData;
13
14use crate::{
15 error::*,
16 fmt::{Braced, Hyphenated, Simple, Urn},
17 non_nil::NonNilUuid,
18 std::fmt,
19 Bytes, Uuid,
20};
21use serde_core::{
22 de::{self, Error as _},
23 Deserialize, Deserializer, Serialize, Serializer,
24};
25
26impl Serialize for Uuid {
27 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
28 if serializer.is_human_readable() {
29 serializer.serialize_str(self.hyphenated().encode_lower(&mut Uuid::encode_buffer()))
30 } else {
31 serializer.serialize_bytes(self.as_bytes())
32 }
33 }
34}
35
36impl Serialize for NonNilUuid {
37 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38 where
39 S: serde_core::Serializer,
40 {
41 Uuid::from(*self).serialize(serializer)
42 }
43}
44
45impl Serialize for Hyphenated {
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 Simple {
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 Serialize for Urn {
58 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
59 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
60 }
61}
62
63impl Serialize for Braced {
64 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
65 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
66 }
67}
68
69struct UuidReadableVisitor<T> {
70 expecting: &'static str,
71 _marker: PhantomData<T>,
72}
73
74impl<'vi, T: UuidDeserialize> de::Visitor<'vi> for UuidReadableVisitor<T> {
75 type Value = T;
76
77 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
78 formatter.write_str(self.expecting)
79 }
80
81 fn visit_str<E: de::Error>(self, value: &str) -> Result<T, E> {
82 T::from_str(value).map_err(de_error)
83 }
84
85 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<T, E> {
86 T::from_slice(value).map_err(de_error)
87 }
88
89 fn visit_seq<A>(self, mut seq: A) -> Result<T, A::Error>
90 where
91 A: de::SeqAccess<'vi>,
92 {
93 #[rustfmt::skip]
94 let bytes = [
95 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(0, &self)) },
96 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(1, &self)) },
97 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(2, &self)) },
98 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(3, &self)) },
99 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(4, &self)) },
100 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(5, &self)) },
101 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(6, &self)) },
102 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(7, &self)) },
103 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(8, &self)) },
104 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(9, &self)) },
105 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(10, &self)) },
106 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(11, &self)) },
107 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(12, &self)) },
108 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(13, &self)) },
109 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(14, &self)) },
110 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(15, &self)) },
111 ];
112
113 T::from_bytes(bytes).map_err(de_error)
114 }
115}
116
117struct UuidBytesVisitor<T> {
118 _marker: PhantomData<T>,
119}
120
121impl<'vi, T: UuidDeserialize> de::Visitor<'vi> for UuidBytesVisitor<T> {
122 type Value = T;
123
124 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(formatter, "a 16 byte array")
126 }
127
128 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<T, E> {
129 T::from_slice(value).map_err(de_error)
130 }
131}
132
133fn de_error<E: de::Error>(e: Error) -> E {
134 E::custom(format_args!("UUID parsing failed: {}", e))
135}
136
137trait UuidDeserialize {
138 fn from_str(formatted: &str) -> Result<Self, Error>
139 where
140 Self: Sized;
141 fn from_slice(bytes: &[u8]) -> Result<Self, Error>
142 where
143 Self: Sized;
144 fn from_bytes(bytes: Bytes) -> Result<Self, Error>
145 where
146 Self: Sized;
147}
148
149impl UuidDeserialize for Uuid {
150 fn from_str(formatted: &str) -> Result<Self, Error> {
151 formatted.parse()
152 }
153
154 fn from_slice(bytes: &[u8]) -> Result<Self, Error> {
155 Uuid::from_slice(bytes)
156 }
157
158 fn from_bytes(bytes: Bytes) -> Result<Self, Error> {
159 Ok(Uuid::from_bytes(bytes))
160 }
161}
162
163impl<'de> Deserialize<'de> for Uuid {
164 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
165 if deserializer.is_human_readable() {
166 deserializer.deserialize_str(UuidReadableVisitor {
167 expecting: "a formatted UUID string",
168 _marker: PhantomData::<Uuid>,
169 })
170 } else {
171 deserializer.deserialize_bytes(UuidBytesVisitor {
172 _marker: PhantomData::<Uuid>,
173 })
174 }
175 }
176}
177
178impl UuidDeserialize for Braced {
179 fn from_str(formatted: &str) -> Result<Self, Error> {
180 formatted.parse()
181 }
182
183 fn from_slice(bytes: &[u8]) -> Result<Self, Error> {
184 Ok(Uuid::from_slice(bytes)?.into())
185 }
186
187 fn from_bytes(bytes: Bytes) -> Result<Self, Error> {
188 Ok(Uuid::from_bytes(bytes).into())
189 }
190}
191
192impl<'de> Deserialize<'de> for Braced {
193 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
194 deserializer.deserialize_str(UuidReadableVisitor {
195 expecting: "a UUID string in the braced format",
196 _marker: PhantomData::<Braced>,
197 })
198 }
199}
200
201impl UuidDeserialize for Hyphenated {
202 fn from_str(formatted: &str) -> Result<Self, Error> {
203 formatted.parse()
204 }
205
206 fn from_slice(bytes: &[u8]) -> Result<Self, Error> {
207 Ok(Uuid::from_slice(bytes)?.into())
208 }
209
210 fn from_bytes(bytes: Bytes) -> Result<Self, Error> {
211 Ok(Uuid::from_bytes(bytes).into())
212 }
213}
214
215impl<'de> Deserialize<'de> for Hyphenated {
216 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
217 deserializer.deserialize_str(UuidReadableVisitor {
218 expecting: "a UUID string in the hyphenated format",
219 _marker: PhantomData::<Hyphenated>,
220 })
221 }
222}
223
224impl UuidDeserialize for Simple {
225 fn from_str(formatted: &str) -> Result<Self, Error> {
226 formatted.parse()
227 }
228
229 fn from_slice(bytes: &[u8]) -> Result<Self, Error> {
230 Ok(Uuid::from_slice(bytes)?.into())
231 }
232
233 fn from_bytes(bytes: Bytes) -> Result<Self, Error> {
234 Ok(Uuid::from_bytes(bytes).into())
235 }
236}
237
238impl<'de> Deserialize<'de> for Simple {
239 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
240 deserializer.deserialize_str(UuidReadableVisitor {
241 expecting: "a UUID string in the simple format",
242 _marker: PhantomData::<Simple>,
243 })
244 }
245}
246
247impl UuidDeserialize for Urn {
248 fn from_str(formatted: &str) -> Result<Self, Error> {
249 formatted.parse()
250 }
251
252 fn from_slice(bytes: &[u8]) -> Result<Self, Error> {
253 Ok(Uuid::from_slice(bytes)?.into())
254 }
255
256 fn from_bytes(bytes: Bytes) -> Result<Self, Error> {
257 Ok(Uuid::from_bytes(bytes).into())
258 }
259}
260
261impl<'de> Deserialize<'de> for Urn {
262 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
263 deserializer.deserialize_str(UuidReadableVisitor {
264 expecting: "a UUID string in the URN format",
265 _marker: PhantomData::<Urn>,
266 })
267 }
268}
269
270impl<'de> Deserialize<'de> for NonNilUuid {
271 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
272 where
273 D: serde_core::Deserializer<'de>,
274 {
275 let uuid = Uuid::deserialize(deserializer)?;
276
277 NonNilUuid::try_from(uuid).map_err(|_| {
278 de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID")
279 })
280 }
281}
282
283pub mod compact {
284 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
292 where
293 S: serde_core::Serializer,
294 {
295 serde_core::Serialize::serialize(u.as_bytes(), serializer)
296 }
297
298 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
302 where
303 D: serde_core::Deserializer<'de>,
304 {
305 let bytes: [u8; 16] = serde_core::Deserialize::deserialize(deserializer)?;
306
307 Ok(crate::Uuid::from_bytes(bytes))
308 }
309
310 #[cfg(test)]
311 mod tests {
312 use serde_derive::*;
313 use serde_test::Configure;
314
315 #[test]
316 fn test_serialize_compact() {
317 #[derive(Serialize, Debug, Deserialize, PartialEq)]
318 struct UuidContainer {
319 #[serde(with = "crate::serde::compact")]
320 u: crate::Uuid,
321 }
322
323 let uuid_bytes = b"F9168C5E-CEB2-4F";
324 let container = UuidContainer {
325 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
326 };
327
328 serde_test::assert_tokens(
331 &container.compact(),
332 &[
333 serde_test::Token::Struct {
334 name: "UuidContainer",
335 len: 1,
336 },
337 serde_test::Token::Str("u"),
338 serde_test::Token::Tuple { len: 16 },
339 serde_test::Token::U8(uuid_bytes[0]),
340 serde_test::Token::U8(uuid_bytes[1]),
341 serde_test::Token::U8(uuid_bytes[2]),
342 serde_test::Token::U8(uuid_bytes[3]),
343 serde_test::Token::U8(uuid_bytes[4]),
344 serde_test::Token::U8(uuid_bytes[5]),
345 serde_test::Token::U8(uuid_bytes[6]),
346 serde_test::Token::U8(uuid_bytes[7]),
347 serde_test::Token::U8(uuid_bytes[8]),
348 serde_test::Token::U8(uuid_bytes[9]),
349 serde_test::Token::U8(uuid_bytes[10]),
350 serde_test::Token::U8(uuid_bytes[11]),
351 serde_test::Token::U8(uuid_bytes[12]),
352 serde_test::Token::U8(uuid_bytes[13]),
353 serde_test::Token::U8(uuid_bytes[14]),
354 serde_test::Token::U8(uuid_bytes[15]),
355 serde_test::Token::TupleEnd,
356 serde_test::Token::StructEnd,
357 ],
358 )
359 }
360 }
361}
362
363pub mod bytes {
386 use super::*;
387
388 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
392 where
393 S: serde_core::Serializer,
394 {
395 serializer.serialize_bytes(u.as_bytes())
396 }
397
398 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
402 where
403 D: serde_core::Deserializer<'de>,
404 {
405 deserializer.deserialize_bytes(UuidBytesVisitor {
406 _marker: PhantomData::<crate::Uuid>,
407 })
408 }
409
410 #[cfg(test)]
411 mod tests {
412 use serde_derive::*;
413
414 #[test]
415 fn test_serialize_bytes() {
416 #[derive(Serialize, Debug, Deserialize, PartialEq)]
417 struct UuidContainer {
418 #[serde(with = "crate::serde::bytes")]
419 u: crate::Uuid,
420 }
421
422 let uuid_bytes = b"F9168C5E-CEB2-4F";
423 let container = UuidContainer {
424 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
425 };
426
427 serde_test::assert_tokens(
428 &container,
429 &[
430 serde_test::Token::Struct {
431 name: "UuidContainer",
432 len: 1,
433 },
434 serde_test::Token::Str("u"),
435 serde_test::Token::Bytes(uuid_bytes),
436 serde_test::Token::StructEnd,
437 ],
438 )
439 }
440 }
441}
442
443pub mod simple {
470 use super::*;
471
472 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
487 where
488 S: serde_core::Serializer,
489 {
490 serde_core::Serialize::serialize(u.as_simple(), serializer)
491 }
492
493 pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
497 where
498 D: serde_core::Deserializer<'de>,
499 {
500 Ok(Simple::deserialize(deserializer)?.into())
501 }
502
503 #[cfg(test)]
504 mod tests {
505 use serde::de::{self, Error};
506 use serde_test::{Readable, Token};
507
508 use super::*;
509
510 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
511 const SIMPLE_UUID_STR: &str = "f9168c5eceb24faab6bf329bf39fa1e4";
512
513 #[test]
514 fn test_serialize_as_simple() {
515 #[derive(serde_derive::Serialize)]
516 struct Struct(#[serde(with = "super")] crate::Uuid);
517
518 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
519 serde_test::assert_ser_tokens(
520 &u,
521 &[
522 Token::NewtypeStruct { name: "Struct" },
523 Token::Str(SIMPLE_UUID_STR),
524 ],
525 );
526 }
527
528 #[test]
529 fn test_de_from_simple() {
530 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
531 struct Struct(#[serde(with = "super")] crate::Uuid);
532 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
533 serde_test::assert_de_tokens::<Struct>(
534 &s,
535 &[
536 Token::TupleStruct {
537 name: "Struct",
538 len: 1,
539 },
540 Token::BorrowedStr(SIMPLE_UUID_STR),
541 Token::TupleStructEnd,
542 ],
543 );
544 }
545
546 #[test]
547 fn test_de_reject_hyphenated() {
548 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
549 struct Struct(#[serde(with = "super")] crate::Uuid);
550 serde_test::assert_de_tokens_error::<Readable<Struct>>(
551 &[
552 Token::TupleStruct {
553 name: "Struct",
554 len: 1,
555 },
556 Token::BorrowedStr(HYPHENATED_UUID_STR),
557 Token::TupleStructEnd,
558 ],
559 &format!(
560 "{}",
561 de::value::Error::custom(
562 "UUID parsing failed: invalid character: found `-` at 8"
563 )
564 ),
565 );
566 }
567 }
568}
569
570pub mod braced {
597 use super::*;
598
599 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
614 where
615 S: serde_core::Serializer,
616 {
617 serde_core::Serialize::serialize(u.as_braced(), serializer)
618 }
619
620 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
624 where
625 D: serde_core::Deserializer<'de>,
626 {
627 Ok(Braced::deserialize(deserializer)?.into())
628 }
629
630 #[cfg(test)]
631 mod tests {
632
633 use serde::de::{self, Error};
634 use serde_test::{Readable, Token};
635
636 use super::*;
637
638 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
639 const BRACED_UUID_STR: &str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
640
641 #[test]
642 fn test_serialize_as_braced() {
643 #[derive(serde_derive::Serialize)]
644 struct Struct(#[serde(with = "super")] crate::Uuid);
645
646 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
647 serde_test::assert_ser_tokens(
648 &u,
649 &[
650 Token::NewtypeStruct { name: "Struct" },
651 Token::Str(BRACED_UUID_STR),
652 ],
653 );
654 }
655
656 #[test]
657 fn test_de_from_braced() {
658 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
659 struct Struct(#[serde(with = "super")] crate::Uuid);
660 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
661 serde_test::assert_de_tokens::<Struct>(
662 &s,
663 &[
664 Token::TupleStruct {
665 name: "Struct",
666 len: 1,
667 },
668 Token::BorrowedStr(BRACED_UUID_STR),
669 Token::TupleStructEnd,
670 ],
671 );
672 }
673
674 #[test]
675 fn test_de_reject_hyphenated() {
676 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
677 struct Struct(#[serde(with = "super")] crate::Uuid);
678 serde_test::assert_de_tokens_error::<Readable<Struct>>(
679 &[
680 Token::TupleStruct {
681 name: "Struct",
682 len: 1,
683 },
684 Token::BorrowedStr(HYPHENATED_UUID_STR),
685 Token::TupleStructEnd,
686 ],
687 &format!(
688 "{}",
689 de::value::Error::custom(
690 "UUID parsing failed: invalid character: found `f` at 0"
691 )
692 ),
693 );
694 }
695 }
696}
697
698pub mod hyphenated {
725
726 use super::*;
727
728 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
743 where
744 S: serde_core::Serializer,
745 {
746 serde_core::Serialize::serialize(u.as_hyphenated(), serializer)
747 }
748
749 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
753 where
754 D: serde_core::Deserializer<'de>,
755 {
756 Ok(Hyphenated::deserialize(deserializer)?.into())
757 }
758
759 #[cfg(test)]
760 mod tests {
761
762 use serde::de::{self, Error};
763 use serde_test::{Readable, Token};
764
765 use super::*;
766
767 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
768 const BRACED_UUID_STR: &str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
769
770 #[test]
771 fn test_serialize_as_hyphenated() {
772 #[derive(serde_derive::Serialize)]
773 struct Struct(#[serde(with = "super")] crate::Uuid);
774
775 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
776 serde_test::assert_ser_tokens(
777 &u,
778 &[
779 Token::NewtypeStruct { name: "Struct" },
780 Token::Str(HYPHENATED_UUID_STR),
781 ],
782 );
783 }
784
785 #[test]
786 fn test_de_from_hyphenated() {
787 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
788 struct Struct(#[serde(with = "super")] crate::Uuid);
789 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
790 serde_test::assert_de_tokens::<Struct>(
791 &s,
792 &[
793 Token::TupleStruct {
794 name: "Struct",
795 len: 1,
796 },
797 Token::BorrowedStr(HYPHENATED_UUID_STR),
798 Token::TupleStructEnd,
799 ],
800 );
801 }
802
803 #[test]
804 fn test_de_reject_braced() {
805 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
806 struct Struct(#[serde(with = "super")] crate::Uuid);
807 serde_test::assert_de_tokens_error::<Readable<Struct>>(
808 &[
809 Token::TupleStruct {
810 name: "Struct",
811 len: 1,
812 },
813 Token::BorrowedStr(BRACED_UUID_STR),
814 Token::TupleStructEnd,
815 ],
816 &format!(
817 "{}",
818 de::value::Error::custom(
819 "UUID parsing failed: invalid character: found `{` at 0"
820 )
821 ),
822 );
823 }
824 }
825}
826
827pub mod urn {
854 use super::*;
855
856 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
871 where
872 S: serde_core::Serializer,
873 {
874 serde_core::Serialize::serialize(u.as_urn(), serializer)
875 }
876
877 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
881 where
882 D: serde_core::Deserializer<'de>,
883 {
884 Ok(Urn::deserialize(deserializer)?.into())
885 }
886
887 #[cfg(test)]
888 mod tests {
889 use serde::de::{self, Error};
890 use serde_test::{Readable, Token};
891
892 use super::*;
893
894 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
895 const URN_UUID_STR: &str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
896
897 #[test]
898 fn test_serialize_as_urn() {
899 #[derive(serde_derive::Serialize)]
900 struct Struct(#[serde(with = "super")] crate::Uuid);
901
902 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
903 serde_test::assert_ser_tokens(
904 &u,
905 &[
906 Token::NewtypeStruct { name: "Struct" },
907 Token::Str(URN_UUID_STR),
908 ],
909 );
910 }
911
912 #[test]
913 fn test_de_from_urn() {
914 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
915 struct Struct(#[serde(with = "super")] crate::Uuid);
916 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
917 serde_test::assert_de_tokens::<Struct>(
918 &s,
919 &[
920 Token::TupleStruct {
921 name: "Struct",
922 len: 1,
923 },
924 Token::BorrowedStr(URN_UUID_STR),
925 Token::TupleStructEnd,
926 ],
927 );
928 }
929
930 #[test]
931 fn test_de_reject_hyphenated() {
932 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
933 struct Struct(#[serde(with = "super")] crate::Uuid);
934 serde_test::assert_de_tokens_error::<Readable<Struct>>(
935 &[
936 Token::TupleStruct {
937 name: "Struct",
938 len: 1,
939 },
940 Token::BorrowedStr(HYPHENATED_UUID_STR),
941 Token::TupleStructEnd,
942 ],
943 &format!(
944 "{}",
945 de::value::Error::custom(
946 "UUID parsing failed: invalid character: found `f` at 0"
947 )
948 ),
949 );
950 }
951 }
952}
953
954#[cfg(test)]
955mod serde_tests {
956 use super::*;
957
958 use serde_test::{Compact, Configure, Readable, Token};
959
960 #[test]
961 fn test_serialize_readable_string() {
962 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
963 let u = Uuid::parse_str(uuid_str).unwrap();
964 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
965 }
966
967 #[test]
968 fn test_deserialize_readable_compact() {
969 let uuid_bytes = b"F9168C5E-CEB2-4F";
970 let u = Uuid::from_slice(uuid_bytes).unwrap();
971
972 serde_test::assert_de_tokens(
973 &u.readable(),
974 &[
975 serde_test::Token::Tuple { len: 16 },
976 serde_test::Token::U8(uuid_bytes[0]),
977 serde_test::Token::U8(uuid_bytes[1]),
978 serde_test::Token::U8(uuid_bytes[2]),
979 serde_test::Token::U8(uuid_bytes[3]),
980 serde_test::Token::U8(uuid_bytes[4]),
981 serde_test::Token::U8(uuid_bytes[5]),
982 serde_test::Token::U8(uuid_bytes[6]),
983 serde_test::Token::U8(uuid_bytes[7]),
984 serde_test::Token::U8(uuid_bytes[8]),
985 serde_test::Token::U8(uuid_bytes[9]),
986 serde_test::Token::U8(uuid_bytes[10]),
987 serde_test::Token::U8(uuid_bytes[11]),
988 serde_test::Token::U8(uuid_bytes[12]),
989 serde_test::Token::U8(uuid_bytes[13]),
990 serde_test::Token::U8(uuid_bytes[14]),
991 serde_test::Token::U8(uuid_bytes[15]),
992 serde_test::Token::TupleEnd,
993 ],
994 );
995 }
996
997 #[test]
998 fn test_deserialize_readable_bytes() {
999 let uuid_bytes = b"F9168C5E-CEB2-4F";
1000 let u = Uuid::from_slice(uuid_bytes).unwrap();
1001
1002 serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
1003 }
1004
1005 #[test]
1006 fn test_serialize_hyphenated() {
1007 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1008 let u = Uuid::parse_str(uuid_str).unwrap();
1009 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
1010 serde_test::assert_de_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
1011 }
1012
1013 #[test]
1014 fn test_serialize_simple() {
1015 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
1016 let u = Uuid::parse_str(uuid_str).unwrap();
1017 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
1018 serde_test::assert_de_tokens(&u.simple(), &[Token::Str(uuid_str)]);
1019 }
1020
1021 #[test]
1022 fn test_serialize_urn() {
1023 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1024 let u = Uuid::parse_str(uuid_str).unwrap();
1025 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
1026 serde_test::assert_de_tokens(&u.urn(), &[Token::Str(uuid_str)]);
1027 }
1028
1029 #[test]
1030 fn test_serialize_braced() {
1031 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
1032 let u = Uuid::parse_str(uuid_str).unwrap();
1033 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
1034 serde_test::assert_de_tokens(&u.braced(), &[Token::Str(uuid_str)]);
1035 }
1036
1037 #[test]
1038 fn test_serialize_non_human_readable() {
1039 let uuid_bytes = b"F9168C5E-CEB2-4F";
1040 let u = Uuid::from_slice(uuid_bytes).unwrap();
1041 serde_test::assert_tokens(
1042 &u.compact(),
1043 &[serde_test::Token::Bytes(&[
1044 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
1045 ])],
1046 );
1047 }
1048
1049 #[test]
1050 fn test_de_failure() {
1051 serde_test::assert_de_tokens_error::<Readable<Uuid>>(
1052 &[Token::Str("hello_world")],
1053 "UUID parsing failed: invalid character: found `h` at 0",
1054 );
1055
1056 serde_test::assert_de_tokens_error::<Compact<Uuid>>(
1057 &[Token::Bytes(b"hello_world")],
1058 "UUID parsing failed: invalid length: expected 16 bytes, found 11",
1059 );
1060 }
1061
1062 #[test]
1063 fn test_serde_non_nil_uuid() {
1064 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1065 let uuid = Uuid::parse_str(uuid_str).unwrap();
1066 let non_nil_uuid = NonNilUuid::try_from(uuid).unwrap();
1067
1068 serde_test::assert_ser_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
1069 serde_test::assert_de_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
1070 }
1071}