evtc\content/
serde_guid.rs
1use crate::content::{GuidExt, GUID};
2use serde::{
3 de::{Error, Visitor},
4 Deserializer, Serializer,
5};
6use std::fmt;
7
8#[inline]
9pub fn serialize<S>(guid: &GUID, serializer: S) -> Result<S::Ok, S::Error>
10where
11 S: Serializer,
12{
13 serializer.serialize_str(&guid.format_hyphenated())
14}
15
16#[inline]
17pub fn deserialize<'de, D>(deserializer: D) -> Result<GUID, D::Error>
18where
19 D: Deserializer<'de>,
20{
21 deserializer.deserialize_str(GuidVisitor)
22}
23
24struct GuidVisitor;
25
26impl GuidVisitor {
27 fn parse(string: &str) -> Option<GUID> {
28 GUID::try_from(string)
29 .ok()
30 .or_else(|| u128::from_str_radix(string, 16).ok().map(GUID::from_u128))
31 }
32
33 fn deserialize_parse<E>(string: &str) -> Result<GUID, E>
34 where
35 E: Error,
36 {
37 Self::parse(string).ok_or_else(|| E::custom("invalid guid"))
38 }
39
40 fn deserialize_convert<T, E>(value: T) -> Result<GUID, E>
41 where
42 T: Into<u128>,
43 {
44 Ok(GUID::from_u128(value.into()))
45 }
46}
47
48impl Visitor<'_> for GuidVisitor {
49 type Value = GUID;
50
51 #[inline]
52 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
53 formatter.write_str("a number or a hexadecimal string")
54 }
55
56 #[inline]
57 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
58 where
59 E: Error,
60 {
61 Self::deserialize_convert(v)
62 }
63
64 #[inline]
65 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
66 where
67 E: Error,
68 {
69 Self::deserialize_convert(v)
70 }
71
72 #[inline]
73 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
74 where
75 E: Error,
76 {
77 Self::deserialize_convert(v)
78 }
79
80 #[inline]
81 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
82 where
83 E: Error,
84 {
85 Self::deserialize_convert(v)
86 }
87
88 #[inline]
89 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
90 where
91 E: Error,
92 {
93 Self::deserialize_convert(v)
94 }
95
96 #[inline]
97 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
98 where
99 E: Error,
100 {
101 Self::deserialize_parse(v)
102 }
103
104 #[inline]
105 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
106 where
107 E: Error,
108 {
109 Self::deserialize_parse(&v)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 const TEST_GUID: GUID = GUID::from_u128(0x1B56F702912BE7428182CA57036AEE99);
118
119 #[test]
120 fn parse() {
121 assert_eq!(
122 GuidVisitor::parse("1B56F702912BE7428182CA57036AEE99"),
123 Some(TEST_GUID)
124 );
125 assert_eq!(
126 GuidVisitor::parse("1B56F702-912B-E742-8182-CA57036AEE99"),
127 Some(TEST_GUID)
128 );
129 }
130
131 #[test]
132 fn roundtrip() {
133 let string = TEST_GUID.format_hyphenated();
134 assert_eq!(GuidVisitor::parse(&string), Some(TEST_GUID));
135 }
136}