sentry_types/
macros.rs
1#![cfg_attr(not(feature = "protocol"), allow(unused))]
2
3macro_rules! impl_str_ser {
9 ($type:ty) => {
10 impl ::serde::ser::Serialize for $type {
11 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12 where
13 S: ::serde::ser::Serializer,
14 {
15 serializer.serialize_str(&self.to_string())
16 }
17 }
18 };
19}
20
21#[allow(unused_macros)]
27macro_rules! impl_str_de {
28 ($type:ty) => {
29 impl<'de> ::serde::de::Deserialize<'de> for $type {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where
32 D: ::serde::de::Deserializer<'de>,
33 {
34 <::std::borrow::Cow<str>>::deserialize(deserializer)?
35 .parse()
36 .map_err(::serde::de::Error::custom)
37 }
38 }
39 };
40}
41
42#[allow(unused_macros)]
48macro_rules! impl_str_serde {
49 ($type:ty) => {
50 impl_str_ser!($type);
51 impl_str_de!($type);
52 };
53}
54
55#[cfg(test)]
56mod str_tests {
57 use std::fmt;
58 use std::io::Cursor;
59 use std::str::FromStr;
60
61 struct Test;
62
63 impl FromStr for Test {
64 type Err = &'static str;
65
66 fn from_str(string: &str) -> Result<Self, Self::Err> {
67 match string {
68 "test" => Ok(Test),
69 _ => Err("failed"),
70 }
71 }
72 }
73
74 impl fmt::Display for Test {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 write!(f, "test")
77 }
78 }
79
80 impl_str_serde!(Test);
81
82 #[test]
83 fn test_serialize_string() {
84 assert_eq!("\"test\"", serde_json::to_string(&Test).unwrap());
85 }
86
87 #[test]
88 fn test_deserialize() {
89 assert!(serde_json::from_str::<Test>("\"test\"").is_ok());
90 }
91
92 #[test]
93 fn test_deserialize_owned() {
94 assert!(serde_json::from_reader::<_, Test>(Cursor::new("\"test\"")).is_ok());
95 }
96}
97
98macro_rules! impl_hex_ser {
101 ($type:ident) => {
102 impl ::std::fmt::Display for $type {
103 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
104 write!(f, "{:#x}", self.0)
105 }
106 }
107
108 impl ::serde::ser::Serialize for $type {
109 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110 where
111 S: ::serde::ser::Serializer,
112 {
113 serializer.serialize_str(&self.to_string())
114 }
115 }
116 };
117}
118
119macro_rules! impl_hex_de {
123 ($type:ident, $num:ident) => {
124 impl ::std::str::FromStr for $type {
125 type Err = ::std::num::ParseIntError;
126
127 fn from_str(s: &str) -> Result<$type, ::std::num::ParseIntError> {
128 if s.starts_with("0x") || s.starts_with("0X") {
129 $num::from_str_radix(&s[2..], 16).map($type)
130 } else {
131 s.parse::<$num>().map($type)
132 }
133 }
134 }
135
136 impl<'de> ::serde::de::Deserialize<'de> for $type {
137 fn deserialize<D>(deserializer: D) -> Result<$type, D::Error>
138 where
139 D: ::serde::de::Deserializer<'de>,
140 {
141 struct HexVisitor;
142
143 impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
144 type Value = $type;
145
146 fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
147 write!(f, "a number or hex string")
148 }
149
150 fn visit_i64<E: ::serde::de::Error>(self, v: i64) -> Result<Self::Value, E> {
151 Ok($type(v as $num))
152 }
153
154 fn visit_u64<E: ::serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
155 Ok($type(v as $num))
156 }
157
158 fn visit_str<E: ::serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
159 v.parse().map_err(::serde::de::Error::custom)
160 }
161 }
162
163 deserializer.deserialize_any(HexVisitor)
164 }
165 }
166 };
167}
168
169macro_rules! impl_hex_serde {
177 ($type:ident, $num:ident) => {
178 impl_hex_ser!($type);
179 impl_hex_de!($type, $num);
180 };
181}
182
183#[cfg(test)]
184mod hex_tests {
185 use std::io::Cursor;
186
187 #[derive(Debug, PartialEq)]
188 struct Hex(u32);
189
190 impl_hex_serde!(Hex, u32);
191
192 #[test]
193 fn test_hex_to_string() {
194 assert_eq!("0x0", &Hex(0).to_string());
195 assert_eq!("0x2a", &Hex(42).to_string());
196 }
197
198 #[test]
199 fn test_hex_serialize() {
200 assert_eq!("\"0x0\"", serde_json::to_string(&Hex(0)).unwrap());
201 assert_eq!("\"0x2a\"", serde_json::to_string(&Hex(42)).unwrap());
202 }
203
204 #[test]
205 fn test_hex_from_string() {
206 assert_eq!(Hex(0), "0".parse().unwrap());
207 assert_eq!(Hex(42), "42".parse().unwrap());
208 assert_eq!(Hex(42), "0x2a".parse().unwrap());
209 assert_eq!(Hex(42), "0X2A".parse().unwrap());
210 }
211
212 #[test]
213 fn test_hex_deserialize() {
214 assert_eq!(Hex(0), serde_json::from_str("\"0\"").unwrap());
215 assert_eq!(Hex(42), serde_json::from_str("\"42\"").unwrap());
216 assert_eq!(Hex(42), serde_json::from_str("\"0x2a\"").unwrap());
217 assert_eq!(Hex(42), serde_json::from_str("\"0X2A\"").unwrap());
218 }
219
220 #[test]
221 fn test_hex_deserialize_owned() {
222 assert_eq!(
223 Hex(0),
224 serde_json::from_reader(Cursor::new("\"0\"")).unwrap()
225 );
226 assert_eq!(
227 Hex(42),
228 serde_json::from_reader(Cursor::new("\"42\"")).unwrap()
229 );
230 assert_eq!(
231 Hex(42),
232 serde_json::from_reader(Cursor::new("\"0x2a\"")).unwrap()
233 );
234 assert_eq!(
235 Hex(42),
236 serde_json::from_reader(Cursor::new("\"0X2A\"")).unwrap()
237 );
238 }
239
240 #[test]
241 fn test_invalid() {
242 let result = serde_json::from_str::<Hex>("true").unwrap_err();
243 assert_eq!(
244 "invalid type: boolean `true`, expected a number or hex string at line 1 column 4",
245 result.to_string()
246 );
247 }
248}