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 pub mod option {
312 pub fn serialize<S>(u: &Option<crate::Uuid>, serializer: S) -> Result<S::Ok, S::Error>
314 where
315 S: serde_core::Serializer,
316 {
317 match u {
318 Some(u) => serializer.serialize_some(u.as_bytes()),
319 None => serializer.serialize_none(),
320 }
321 }
322
323 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<crate::Uuid>, D::Error>
325 where
326 D: serde_core::Deserializer<'de>,
327 {
328 <Option<[u8; 16]> as serde_core::Deserialize>::deserialize(deserializer)
329 .map(|bytes| bytes.map(crate::Uuid::from_bytes))
330 }
331 }
332
333 #[cfg(test)]
334 mod tests {
335 use serde_derive::*;
336 use serde_test::{Configure, Token};
337
338 use crate::Uuid;
339
340 const BYTES: [u8; 16] = [
341 0xf9, 0x16, 0x8c, 0x5e, 0xce, 0xb2, 0x4f, 0xaa, 0xb6, 0xbf, 0x32, 0x9b, 0xf3, 0x9f,
342 0xa1, 0xe4,
343 ];
344
345 #[test]
346 fn test_compact_option() {
347 #[derive(Debug, PartialEq, Serialize, Deserialize)]
348 struct Field {
349 #[serde(with = "crate::serde::compact::option")]
350 id: Option<Uuid>,
351 }
352
353 let present = Field {
354 id: Some(Uuid::from_bytes(BYTES)),
355 };
356 let absent = Field { id: None };
357 let tokens = [
358 Token::Struct {
359 name: "Field",
360 len: 1,
361 },
362 Token::Str("id"),
363 Token::Some,
364 Token::Tuple { len: 16 },
365 Token::U8(BYTES[0]),
366 Token::U8(BYTES[1]),
367 Token::U8(BYTES[2]),
368 Token::U8(BYTES[3]),
369 Token::U8(BYTES[4]),
370 Token::U8(BYTES[5]),
371 Token::U8(BYTES[6]),
372 Token::U8(BYTES[7]),
373 Token::U8(BYTES[8]),
374 Token::U8(BYTES[9]),
375 Token::U8(BYTES[10]),
376 Token::U8(BYTES[11]),
377 Token::U8(BYTES[12]),
378 Token::U8(BYTES[13]),
379 Token::U8(BYTES[14]),
380 Token::U8(BYTES[15]),
381 Token::TupleEnd,
382 Token::StructEnd,
383 ];
384 serde_test::assert_tokens(&present, &tokens);
385 let none_tokens = [
386 Token::Struct {
387 name: "Field",
388 len: 1,
389 },
390 Token::Str("id"),
391 Token::None,
392 Token::StructEnd,
393 ];
394 serde_test::assert_tokens(&absent, &none_tokens);
395 }
396
397 #[test]
398 fn test_serialize_compact() {
399 #[derive(Serialize, Debug, Deserialize, PartialEq)]
400 struct UuidContainer {
401 #[serde(with = "crate::serde::compact")]
402 u: crate::Uuid,
403 }
404
405 let uuid_bytes = b"F9168C5E-CEB2-4F";
406 let container = UuidContainer {
407 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
408 };
409
410 serde_test::assert_tokens(
413 &container.compact(),
414 &[
415 serde_test::Token::Struct {
416 name: "UuidContainer",
417 len: 1,
418 },
419 serde_test::Token::Str("u"),
420 serde_test::Token::Tuple { len: 16 },
421 serde_test::Token::U8(uuid_bytes[0]),
422 serde_test::Token::U8(uuid_bytes[1]),
423 serde_test::Token::U8(uuid_bytes[2]),
424 serde_test::Token::U8(uuid_bytes[3]),
425 serde_test::Token::U8(uuid_bytes[4]),
426 serde_test::Token::U8(uuid_bytes[5]),
427 serde_test::Token::U8(uuid_bytes[6]),
428 serde_test::Token::U8(uuid_bytes[7]),
429 serde_test::Token::U8(uuid_bytes[8]),
430 serde_test::Token::U8(uuid_bytes[9]),
431 serde_test::Token::U8(uuid_bytes[10]),
432 serde_test::Token::U8(uuid_bytes[11]),
433 serde_test::Token::U8(uuid_bytes[12]),
434 serde_test::Token::U8(uuid_bytes[13]),
435 serde_test::Token::U8(uuid_bytes[14]),
436 serde_test::Token::U8(uuid_bytes[15]),
437 serde_test::Token::TupleEnd,
438 serde_test::Token::StructEnd,
439 ],
440 )
441 }
442 }
443}
444
445pub mod bytes {
468 use super::*;
469
470 struct ByteUuid(crate::Uuid);
471
472 impl serde_core::Serialize for ByteUuid {
473 fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
474 serializer.serialize_bytes(self.0.as_bytes())
475 }
476 }
477
478 impl<'de> serde_core::Deserialize<'de> for ByteUuid {
479 fn deserialize<D: serde_core::Deserializer<'de>>(
480 deserializer: D,
481 ) -> Result<Self, D::Error> {
482 deserializer
483 .deserialize_bytes(UuidBytesVisitor {
484 _marker: PhantomData::<crate::Uuid>,
485 })
486 .map(Self)
487 }
488 }
489
490 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
494 where
495 S: serde_core::Serializer,
496 {
497 ByteUuid(*u).serialize(serializer)
498 }
499
500 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
504 where
505 D: serde_core::Deserializer<'de>,
506 {
507 ByteUuid::deserialize(deserializer).map(|u| u.0)
508 }
509
510 pub mod option {
512 use super::*;
513
514 pub fn serialize<S>(u: &Option<crate::Uuid>, serializer: S) -> Result<S::Ok, S::Error>
516 where
517 S: serde_core::Serializer,
518 {
519 match u {
520 Some(u) => serializer.serialize_some(&ByteUuid(*u)),
521 None => serializer.serialize_none(),
522 }
523 }
524
525 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<crate::Uuid>, D::Error>
527 where
528 D: serde_core::Deserializer<'de>,
529 {
530 Option::<ByteUuid>::deserialize(deserializer).map(|u| u.map(|u| u.0))
531 }
532 }
533
534 #[cfg(test)]
535 mod tests {
536 use serde_derive::*;
537
538 use crate::Uuid;
539 use serde_test::Token;
540
541 const BYTES: [u8; 16] = [
542 0xf9, 0x16, 0x8c, 0x5e, 0xce, 0xb2, 0x4f, 0xaa, 0xb6, 0xbf, 0x32, 0x9b, 0xf3, 0x9f,
543 0xa1, 0xe4,
544 ];
545
546 #[test]
547 fn test_bytes_option() {
548 #[derive(Debug, PartialEq, Serialize, Deserialize)]
549 struct Field {
550 #[serde(with = "crate::serde::bytes::option")]
551 id: Option<Uuid>,
552 }
553
554 let present = Field {
555 id: Some(Uuid::from_bytes(BYTES)),
556 };
557 let absent = Field { id: None };
558 let present_tokens = [
559 Token::Struct {
560 name: "Field",
561 len: 1,
562 },
563 Token::Str("id"),
564 Token::Some,
565 Token::Bytes(&BYTES),
566 Token::StructEnd,
567 ];
568 let none_tokens = [
569 Token::Struct {
570 name: "Field",
571 len: 1,
572 },
573 Token::Str("id"),
574 Token::None,
575 Token::StructEnd,
576 ];
577 serde_test::assert_tokens(&present, &present_tokens);
578 serde_test::assert_tokens(&absent, &none_tokens);
579 }
580
581 #[test]
582 fn test_serialize_bytes() {
583 #[derive(Serialize, Debug, Deserialize, PartialEq)]
584 struct UuidContainer {
585 #[serde(with = "crate::serde::bytes")]
586 u: crate::Uuid,
587 }
588
589 let uuid_bytes = b"F9168C5E-CEB2-4F";
590 let container = UuidContainer {
591 u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
592 };
593
594 serde_test::assert_tokens(
595 &container,
596 &[
597 serde_test::Token::Struct {
598 name: "UuidContainer",
599 len: 1,
600 },
601 serde_test::Token::Str("u"),
602 serde_test::Token::Bytes(uuid_bytes),
603 serde_test::Token::StructEnd,
604 ],
605 )
606 }
607 }
608}
609
610pub mod simple {
637 use super::*;
638
639 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
654 where
655 S: serde_core::Serializer,
656 {
657 serde_core::Serialize::serialize(u.as_simple(), serializer)
658 }
659
660 pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
664 where
665 D: serde_core::Deserializer<'de>,
666 {
667 Ok(Simple::deserialize(deserializer)?.into())
668 }
669
670 pub mod option {
672 use super::*;
673
674 pub fn serialize<S>(u: &Option<Uuid>, serializer: S) -> Result<S::Ok, S::Error>
676 where
677 S: serde_core::Serializer,
678 {
679 match u {
680 Some(u) => serializer.serialize_some(u.as_simple()),
681 None => serializer.serialize_none(),
682 }
683 }
684
685 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Uuid>, D::Error>
687 where
688 D: serde_core::Deserializer<'de>,
689 {
690 Option::<Simple>::deserialize(deserializer).map(|u| u.map(Into::into))
691 }
692 }
693
694 #[cfg(test)]
695 mod tests {
696 use serde::de::{self, Error};
697 use serde_test::{Readable, Token};
698
699 use super::*;
700
701 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
702 const SIMPLE_UUID_STR: &str = "f9168c5eceb24faab6bf329bf39fa1e4";
703
704 #[test]
705 fn test_simple_option() {
706 #[derive(Debug, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
707 struct Field {
708 #[serde(with = "crate::serde::simple::option")]
709 id: Option<Uuid>,
710 }
711
712 let present = Field {
713 id: Some(HYPHENATED_UUID_STR.parse().unwrap()),
714 };
715 let absent = Field { id: None };
716 let present_tokens = [
717 Token::Struct {
718 name: "Field",
719 len: 1,
720 },
721 Token::Str("id"),
722 Token::Some,
723 Token::Str(SIMPLE_UUID_STR),
724 Token::StructEnd,
725 ];
726 let absent_tokens = [
727 Token::Struct {
728 name: "Field",
729 len: 1,
730 },
731 Token::Str("id"),
732 Token::None,
733 Token::StructEnd,
734 ];
735
736 serde_test::assert_tokens(&present, &present_tokens);
737 serde_test::assert_tokens(&absent, &absent_tokens);
738 }
739
740 #[test]
741 fn test_serialize_as_simple() {
742 #[derive(serde_derive::Serialize)]
743 struct Struct(#[serde(with = "super")] crate::Uuid);
744
745 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
746 serde_test::assert_ser_tokens(
747 &u,
748 &[
749 Token::NewtypeStruct { name: "Struct" },
750 Token::Str(SIMPLE_UUID_STR),
751 ],
752 );
753 }
754
755 #[test]
756 fn test_de_from_simple() {
757 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
758 struct Struct(#[serde(with = "super")] crate::Uuid);
759 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
760 serde_test::assert_de_tokens::<Struct>(
761 &s,
762 &[
763 Token::TupleStruct {
764 name: "Struct",
765 len: 1,
766 },
767 Token::BorrowedStr(SIMPLE_UUID_STR),
768 Token::TupleStructEnd,
769 ],
770 );
771 }
772
773 #[test]
774 fn test_de_reject_hyphenated() {
775 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
776 struct Struct(#[serde(with = "super")] crate::Uuid);
777 serde_test::assert_de_tokens_error::<Readable<Struct>>(
778 &[
779 Token::TupleStruct {
780 name: "Struct",
781 len: 1,
782 },
783 Token::BorrowedStr(HYPHENATED_UUID_STR),
784 Token::TupleStructEnd,
785 ],
786 &format!(
787 "{}",
788 de::value::Error::custom(
789 "UUID parsing failed: invalid character: found `-` at 8"
790 )
791 ),
792 );
793 }
794 }
795}
796
797pub mod braced {
824 use super::*;
825
826 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
841 where
842 S: serde_core::Serializer,
843 {
844 serde_core::Serialize::serialize(u.as_braced(), serializer)
845 }
846
847 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
851 where
852 D: serde_core::Deserializer<'de>,
853 {
854 Ok(Braced::deserialize(deserializer)?.into())
855 }
856
857 pub mod option {
859 use super::*;
860
861 pub fn serialize<S>(u: &Option<Uuid>, serializer: S) -> Result<S::Ok, S::Error>
863 where
864 S: serde_core::Serializer,
865 {
866 match u {
867 Some(u) => serializer.serialize_some(u.as_braced()),
868 None => serializer.serialize_none(),
869 }
870 }
871
872 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Uuid>, D::Error>
874 where
875 D: serde_core::Deserializer<'de>,
876 {
877 Option::<Braced>::deserialize(deserializer).map(|u| u.map(Into::into))
878 }
879 }
880
881 #[cfg(test)]
882 mod tests {
883
884 use serde::de::{self, Error};
885 use serde_test::{Readable, Token};
886
887 use super::*;
888
889 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
890 const BRACED_UUID_STR: &str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
891
892 #[test]
893 fn test_braced_option() {
894 #[derive(Debug, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
895 struct Field {
896 #[serde(with = "crate::serde::braced::option")]
897 id: Option<Uuid>,
898 }
899
900 let present = Field {
901 id: Some(HYPHENATED_UUID_STR.parse().unwrap()),
902 };
903 let absent = Field { id: None };
904 let present_tokens = [
905 Token::Struct {
906 name: "Field",
907 len: 1,
908 },
909 Token::Str("id"),
910 Token::Some,
911 Token::Str(BRACED_UUID_STR),
912 Token::StructEnd,
913 ];
914 let absent_tokens = [
915 Token::Struct {
916 name: "Field",
917 len: 1,
918 },
919 Token::Str("id"),
920 Token::None,
921 Token::StructEnd,
922 ];
923
924 serde_test::assert_tokens(&present, &present_tokens);
925 serde_test::assert_tokens(&absent, &absent_tokens);
926 }
927
928 #[test]
929 fn test_serialize_as_braced() {
930 #[derive(serde_derive::Serialize)]
931 struct Struct(#[serde(with = "super")] crate::Uuid);
932
933 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
934 serde_test::assert_ser_tokens(
935 &u,
936 &[
937 Token::NewtypeStruct { name: "Struct" },
938 Token::Str(BRACED_UUID_STR),
939 ],
940 );
941 }
942
943 #[test]
944 fn test_de_from_braced() {
945 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
946 struct Struct(#[serde(with = "super")] crate::Uuid);
947 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
948 serde_test::assert_de_tokens::<Struct>(
949 &s,
950 &[
951 Token::TupleStruct {
952 name: "Struct",
953 len: 1,
954 },
955 Token::BorrowedStr(BRACED_UUID_STR),
956 Token::TupleStructEnd,
957 ],
958 );
959 }
960
961 #[test]
962 fn test_de_reject_hyphenated() {
963 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
964 struct Struct(#[serde(with = "super")] crate::Uuid);
965 serde_test::assert_de_tokens_error::<Readable<Struct>>(
966 &[
967 Token::TupleStruct {
968 name: "Struct",
969 len: 1,
970 },
971 Token::BorrowedStr(HYPHENATED_UUID_STR),
972 Token::TupleStructEnd,
973 ],
974 &format!(
975 "{}",
976 de::value::Error::custom(
977 "UUID parsing failed: invalid character: found `f` at 0"
978 )
979 ),
980 );
981 }
982 }
983}
984
985pub mod hyphenated {
1012
1013 use super::*;
1014
1015 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
1030 where
1031 S: serde_core::Serializer,
1032 {
1033 serde_core::Serialize::serialize(u.as_hyphenated(), serializer)
1034 }
1035
1036 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
1040 where
1041 D: serde_core::Deserializer<'de>,
1042 {
1043 Ok(Hyphenated::deserialize(deserializer)?.into())
1044 }
1045
1046 pub mod option {
1048 use super::*;
1049
1050 pub fn serialize<S>(u: &Option<Uuid>, serializer: S) -> Result<S::Ok, S::Error>
1052 where
1053 S: serde_core::Serializer,
1054 {
1055 match u {
1056 Some(u) => serializer.serialize_some(u.as_hyphenated()),
1057 None => serializer.serialize_none(),
1058 }
1059 }
1060
1061 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Uuid>, D::Error>
1063 where
1064 D: serde_core::Deserializer<'de>,
1065 {
1066 Option::<Hyphenated>::deserialize(deserializer).map(|u| u.map(Into::into))
1067 }
1068 }
1069
1070 #[cfg(test)]
1071 mod tests {
1072
1073 use serde::de::{self, Error};
1074 use serde_test::{Readable, Token};
1075
1076 use super::*;
1077
1078 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1079 const BRACED_UUID_STR: &str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
1080
1081 #[test]
1082 fn test_hyphenated_option() {
1083 #[derive(Debug, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
1084 struct Field {
1085 #[serde(with = "crate::serde::hyphenated::option")]
1086 id: Option<Uuid>,
1087 }
1088
1089 let present = Field {
1090 id: Some(HYPHENATED_UUID_STR.parse().unwrap()),
1091 };
1092 let absent = Field { id: None };
1093 let present_tokens = [
1094 Token::Struct {
1095 name: "Field",
1096 len: 1,
1097 },
1098 Token::Str("id"),
1099 Token::Some,
1100 Token::Str(HYPHENATED_UUID_STR),
1101 Token::StructEnd,
1102 ];
1103 let absent_tokens = [
1104 Token::Struct {
1105 name: "Field",
1106 len: 1,
1107 },
1108 Token::Str("id"),
1109 Token::None,
1110 Token::StructEnd,
1111 ];
1112
1113 serde_test::assert_tokens(&present, &present_tokens);
1114 serde_test::assert_tokens(&absent, &absent_tokens);
1115 }
1116
1117 #[test]
1118 fn test_serialize_as_hyphenated() {
1119 #[derive(serde_derive::Serialize)]
1120 struct Struct(#[serde(with = "super")] crate::Uuid);
1121
1122 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
1123 serde_test::assert_ser_tokens(
1124 &u,
1125 &[
1126 Token::NewtypeStruct { name: "Struct" },
1127 Token::Str(HYPHENATED_UUID_STR),
1128 ],
1129 );
1130 }
1131
1132 #[test]
1133 fn test_de_from_hyphenated() {
1134 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
1135 struct Struct(#[serde(with = "super")] crate::Uuid);
1136 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
1137 serde_test::assert_de_tokens::<Struct>(
1138 &s,
1139 &[
1140 Token::TupleStruct {
1141 name: "Struct",
1142 len: 1,
1143 },
1144 Token::BorrowedStr(HYPHENATED_UUID_STR),
1145 Token::TupleStructEnd,
1146 ],
1147 );
1148 }
1149
1150 #[test]
1151 fn test_de_reject_braced() {
1152 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
1153 struct Struct(#[serde(with = "super")] crate::Uuid);
1154 serde_test::assert_de_tokens_error::<Readable<Struct>>(
1155 &[
1156 Token::TupleStruct {
1157 name: "Struct",
1158 len: 1,
1159 },
1160 Token::BorrowedStr(BRACED_UUID_STR),
1161 Token::TupleStructEnd,
1162 ],
1163 &format!(
1164 "{}",
1165 de::value::Error::custom(
1166 "UUID parsing failed: invalid character: found `{` at 0"
1167 )
1168 ),
1169 );
1170 }
1171 }
1172}
1173
1174pub mod urn {
1201 use super::*;
1202
1203 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
1218 where
1219 S: serde_core::Serializer,
1220 {
1221 serde_core::Serialize::serialize(u.as_urn(), serializer)
1222 }
1223
1224 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
1228 where
1229 D: serde_core::Deserializer<'de>,
1230 {
1231 Ok(Urn::deserialize(deserializer)?.into())
1232 }
1233
1234 pub mod option {
1236 use super::*;
1237
1238 pub fn serialize<S>(u: &Option<Uuid>, serializer: S) -> Result<S::Ok, S::Error>
1240 where
1241 S: serde_core::Serializer,
1242 {
1243 match u {
1244 Some(u) => serializer.serialize_some(u.as_urn()),
1245 None => serializer.serialize_none(),
1246 }
1247 }
1248
1249 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Uuid>, D::Error>
1251 where
1252 D: serde_core::Deserializer<'de>,
1253 {
1254 Option::<Urn>::deserialize(deserializer).map(|u| u.map(Into::into))
1255 }
1256 }
1257
1258 #[cfg(test)]
1259 mod tests {
1260 use serde::de::{self, Error};
1261 use serde_test::{Readable, Token};
1262
1263 use super::*;
1264
1265 const HYPHENATED_UUID_STR: &str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1266 const URN_UUID_STR: &str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1267
1268 #[test]
1269 fn test_urn_option() {
1270 #[derive(Debug, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
1271 struct Field {
1272 #[serde(with = "crate::serde::urn::option")]
1273 id: Option<Uuid>,
1274 }
1275
1276 let present = Field {
1277 id: Some(HYPHENATED_UUID_STR.parse().unwrap()),
1278 };
1279 let absent = Field { id: None };
1280 let present_tokens = [
1281 Token::Struct {
1282 name: "Field",
1283 len: 1,
1284 },
1285 Token::Str("id"),
1286 Token::Some,
1287 Token::Str(URN_UUID_STR),
1288 Token::StructEnd,
1289 ];
1290 let absent_tokens = [
1291 Token::Struct {
1292 name: "Field",
1293 len: 1,
1294 },
1295 Token::Str("id"),
1296 Token::None,
1297 Token::StructEnd,
1298 ];
1299
1300 serde_test::assert_tokens(&present, &present_tokens);
1301 serde_test::assert_tokens(&absent, &absent_tokens);
1302 }
1303
1304 #[test]
1305 fn test_serialize_as_urn() {
1306 #[derive(serde_derive::Serialize)]
1307 struct Struct(#[serde(with = "super")] crate::Uuid);
1308
1309 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap());
1310 serde_test::assert_ser_tokens(
1311 &u,
1312 &[
1313 Token::NewtypeStruct { name: "Struct" },
1314 Token::Str(URN_UUID_STR),
1315 ],
1316 );
1317 }
1318
1319 #[test]
1320 fn test_de_from_urn() {
1321 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
1322 struct Struct(#[serde(with = "super")] crate::Uuid);
1323 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap());
1324 serde_test::assert_de_tokens::<Struct>(
1325 &s,
1326 &[
1327 Token::TupleStruct {
1328 name: "Struct",
1329 len: 1,
1330 },
1331 Token::BorrowedStr(URN_UUID_STR),
1332 Token::TupleStructEnd,
1333 ],
1334 );
1335 }
1336
1337 #[test]
1338 fn test_de_reject_hyphenated() {
1339 #[derive(PartialEq, Debug, serde_derive::Deserialize)]
1340 struct Struct(#[serde(with = "super")] crate::Uuid);
1341 serde_test::assert_de_tokens_error::<Readable<Struct>>(
1342 &[
1343 Token::TupleStruct {
1344 name: "Struct",
1345 len: 1,
1346 },
1347 Token::BorrowedStr(HYPHENATED_UUID_STR),
1348 Token::TupleStructEnd,
1349 ],
1350 &format!(
1351 "{}",
1352 de::value::Error::custom(
1353 "UUID parsing failed: invalid character: found `f` at 0"
1354 )
1355 ),
1356 );
1357 }
1358 }
1359}
1360
1361#[cfg(test)]
1362mod serde_tests {
1363 use super::*;
1364
1365 use serde_test::{Compact, Configure, Readable, Token};
1366
1367 #[test]
1368 fn test_serialize_readable_string() {
1369 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1370 let u = Uuid::parse_str(uuid_str).unwrap();
1371 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
1372 }
1373
1374 #[test]
1375 fn test_deserialize_readable_compact() {
1376 let uuid_bytes = b"F9168C5E-CEB2-4F";
1377 let u = Uuid::from_slice(uuid_bytes).unwrap();
1378
1379 serde_test::assert_de_tokens(
1380 &u.readable(),
1381 &[
1382 serde_test::Token::Tuple { len: 16 },
1383 serde_test::Token::U8(uuid_bytes[0]),
1384 serde_test::Token::U8(uuid_bytes[1]),
1385 serde_test::Token::U8(uuid_bytes[2]),
1386 serde_test::Token::U8(uuid_bytes[3]),
1387 serde_test::Token::U8(uuid_bytes[4]),
1388 serde_test::Token::U8(uuid_bytes[5]),
1389 serde_test::Token::U8(uuid_bytes[6]),
1390 serde_test::Token::U8(uuid_bytes[7]),
1391 serde_test::Token::U8(uuid_bytes[8]),
1392 serde_test::Token::U8(uuid_bytes[9]),
1393 serde_test::Token::U8(uuid_bytes[10]),
1394 serde_test::Token::U8(uuid_bytes[11]),
1395 serde_test::Token::U8(uuid_bytes[12]),
1396 serde_test::Token::U8(uuid_bytes[13]),
1397 serde_test::Token::U8(uuid_bytes[14]),
1398 serde_test::Token::U8(uuid_bytes[15]),
1399 serde_test::Token::TupleEnd,
1400 ],
1401 );
1402 }
1403
1404 #[test]
1405 fn test_deserialize_readable_bytes() {
1406 let uuid_bytes = b"F9168C5E-CEB2-4F";
1407 let u = Uuid::from_slice(uuid_bytes).unwrap();
1408
1409 serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
1410 }
1411
1412 #[test]
1413 fn test_serialize_hyphenated() {
1414 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1415 let u = Uuid::parse_str(uuid_str).unwrap();
1416 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
1417 serde_test::assert_de_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
1418 }
1419
1420 #[test]
1421 fn test_serialize_simple() {
1422 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
1423 let u = Uuid::parse_str(uuid_str).unwrap();
1424 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
1425 serde_test::assert_de_tokens(&u.simple(), &[Token::Str(uuid_str)]);
1426 }
1427
1428 #[test]
1429 fn test_serialize_urn() {
1430 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1431 let u = Uuid::parse_str(uuid_str).unwrap();
1432 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
1433 serde_test::assert_de_tokens(&u.urn(), &[Token::Str(uuid_str)]);
1434 }
1435
1436 #[test]
1437 fn test_serialize_braced() {
1438 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
1439 let u = Uuid::parse_str(uuid_str).unwrap();
1440 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
1441 serde_test::assert_de_tokens(&u.braced(), &[Token::Str(uuid_str)]);
1442 }
1443
1444 #[test]
1445 fn test_serialize_non_human_readable() {
1446 let uuid_bytes = b"F9168C5E-CEB2-4F";
1447 let u = Uuid::from_slice(uuid_bytes).unwrap();
1448 serde_test::assert_tokens(
1449 &u.compact(),
1450 &[serde_test::Token::Bytes(&[
1451 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
1452 ])],
1453 );
1454 }
1455
1456 #[test]
1457 fn test_de_failure() {
1458 serde_test::assert_de_tokens_error::<Readable<Uuid>>(
1459 &[Token::Str("hello_world")],
1460 "UUID parsing failed: invalid character: found `h` at 0",
1461 );
1462
1463 serde_test::assert_de_tokens_error::<Compact<Uuid>>(
1464 &[Token::Bytes(b"hello_world")],
1465 "UUID parsing failed: invalid length: expected 16 bytes, found 11",
1466 );
1467 }
1468
1469 #[test]
1470 fn test_serde_non_nil_uuid() {
1471 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
1472 let uuid = Uuid::parse_str(uuid_str).unwrap();
1473 let non_nil_uuid = NonNilUuid::try_from(uuid).unwrap();
1474
1475 serde_test::assert_ser_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
1476 serde_test::assert_de_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
1477 }
1478}