serde_plain/
macros.rs

1#[macro_export]
2/// Implements [`FromStr`](std::str::FromStr) for a type that forwards to [`Deserialize`](serde::Deserialize).
3///
4/// ```rust
5/// # #[macro_use] extern crate serde_derive;
6/// use serde::Deserialize;
7/// use serde_plain::derive_fromstr_from_deserialize;
8/// # fn main() {
9///
10/// #[derive(Deserialize, Debug)]
11/// pub enum MyEnum {
12///     VariantA,
13///     VariantB,
14/// }
15///
16/// derive_fromstr_from_deserialize!(MyEnum);
17/// # }
18/// ```
19///
20/// This automatically implements [`FromStr`](std::str::FromStr) which will
21/// invoke the [`from_str`](crate::from_str) method from this crate.
22///
23/// Additionally this macro supports a second argument which can be the
24/// error type to use.  In that case `From<serde_plain::Error>` needs
25/// to be implemented for that error.
26///
27/// A third form with a conversion function as second argument is supported.
28/// The closure needs to be in the form `|err| -> ErrType { ... }`:
29///
30/// ```rust
31/// # #[macro_use] extern crate serde_derive;
32/// use serde::Deserialize;
33/// use serde_plain::derive_fromstr_from_deserialize;
34/// # fn main() {
35///
36/// #[derive(Deserialize, Debug)]
37/// pub enum MyEnum {
38///     VariantA,
39///     VariantB,
40/// }
41///
42/// #[derive(Debug)]
43/// pub struct MyError(String);
44///
45/// derive_fromstr_from_deserialize!(MyEnum, |err| -> MyError { MyError(err.to_string()) });
46/// # }
47/// ```
48macro_rules! derive_fromstr_from_deserialize {
49    ($type:ty) => {
50        impl ::std::str::FromStr for $type {
51            type Err = $crate::Error;
52            fn from_str(s: &str) -> ::std::result::Result<$type, Self::Err> {
53                $crate::from_str(s)
54            }
55        }
56    };
57    ($type:ty, |$var:ident| -> $err_type:ty { $err_conv:expr }) => {
58        impl ::std::str::FromStr for $type {
59            type Err = $err_type;
60            fn from_str(s: &str) -> ::std::result::Result<$type, Self::Err> {
61                $crate::from_str(s).map_err(|$var| ($err_conv))
62            }
63        }
64    };
65    ($type:ty, $err_type:ty) => {
66        impl ::std::str::FromStr for $type {
67            type Err = $err_type;
68            fn from_str(s: &str) -> ::std::result::Result<$type, Self::Err> {
69                $crate::from_str(s).map_err(|e| e.into())
70            }
71        }
72    };
73}
74
75/// Legacy alias for [`derive_fromstr_from_deserialize`].
76#[deprecated(note = "legacy alias for derive_fromstr_from_deserialize")]
77#[doc(hidden)]
78#[macro_export]
79macro_rules! forward_from_str_to_serde {
80    ($($tt:tt)*) => { $crate::derive_fromstr_from_deserialize!($($tt)*); }
81}
82
83#[macro_export]
84/// Implements [`Display`](std::fmt::Display) for a type that forwards to [`Serialize`](serde::Serialize).
85///
86/// ```rust
87/// # #[macro_use] extern crate serde_derive;
88/// use serde::Deserialize;
89/// use serde_plain::derive_display_from_serialize;
90/// # fn main() {
91///
92/// #[derive(Serialize, Debug)]
93/// pub enum MyEnum {
94///     VariantA,
95///     VariantB,
96/// }
97///
98/// derive_display_from_serialize!(MyEnum);
99/// # }
100/// ```
101///
102/// This automatically implements [`Display`](std::fmt::Display) which will
103/// invoke the [`to_string`](crate::to_string) method from this crate. In case
104/// that fails the method will panic.
105macro_rules! derive_display_from_serialize {
106    ($type:ident $(:: $type_extra:ident)* < $($lt:lifetime),+ >) => {
107        impl<$($lt,)*> ::std::fmt::Display for $type$(:: $type_extra)*<$($lt,)*> {
108            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
109                write!(f, "{}", $crate::to_string(self).unwrap())
110            }
111        }
112    };
113    ($type:ty) => {
114        impl ::std::fmt::Display for $type {
115            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
116                write!(f, "{}", $crate::to_string(self).unwrap())
117            }
118        }
119    };
120}
121
122/// Legacy alias for [`derive_fromstr_from_serialize`].
123#[deprecated(note = "legacy alias for derive_display_from_serialize")]
124#[doc(hidden)]
125#[macro_export]
126macro_rules! forward_display_to_serde {
127    ($($tt:tt)*) => { $crate::derive_display_from_serialize!($($tt)*); }
128}
129
130/// Derives [`Deserialize`](serde::Serialize) for a type that implements [`FromStr`](std::str::FromStr).
131///
132/// ```rust
133/// use std::str::FromStr;
134/// use std::num::ParseIntError;
135/// use serde_plain::derive_deserialize_from_fromstr;
136/// # fn main() {
137///
138/// pub struct MyStruct(u32);
139///
140/// impl FromStr for MyStruct {
141///     type Err = ParseIntError;
142///     fn from_str(value: &str) -> Result<MyStruct, Self::Err> {
143///         Ok(MyStruct(value.parse()?))
144///     }
145/// }
146///
147/// derive_deserialize_from_fromstr!(MyStruct, "valid positive number");
148/// # }
149/// ```
150///
151/// This automatically implements [`Serialize`](serde::Serialize) which will
152/// invoke the [`from_str`](crate::from_str) function on the target type
153/// internally. First argument is the name of the type, the second is a message
154/// for the expectation error (human readable type effectively).
155#[macro_export]
156macro_rules! derive_deserialize_from_fromstr {
157    ($type:ty, $expectation:expr) => {
158        impl<'de> ::serde::de::Deserialize<'de> for $type {
159            fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
160            where
161                D: ::serde::de::Deserializer<'de>,
162            {
163                struct V;
164
165                impl<'de> ::serde::de::Visitor<'de> for V {
166                    type Value = $type;
167
168                    fn expecting(
169                        &self,
170                        formatter: &mut ::std::fmt::Formatter,
171                    ) -> ::std::fmt::Result {
172                        formatter.write_str($expectation)
173                    }
174
175                    fn visit_str<E>(self, value: &str) -> ::std::result::Result<$type, E>
176                    where
177                        E: ::serde::de::Error,
178                    {
179                        value.parse().map_err(|_| {
180                            ::serde::de::Error::invalid_value(
181                                ::serde::de::Unexpected::Str(value),
182                                &self,
183                            )
184                        })
185                    }
186                }
187
188                deserializer.deserialize_str(V)
189            }
190        }
191    };
192}
193
194/// Legacy alias for [`derive_fromstr_from_deserialize`].
195#[deprecated(note = "legacy alias for derive_deserialize_from_fromstr")]
196#[doc(hidden)]
197#[macro_export]
198macro_rules! derive_deserialize_from_str {
199    ($($tt:tt)*) => { $crate::derive_deserialize_from_fromstr!($($tt)*); }
200}
201
202/// Derives [`Serialize`](serde::Serialize) a type that implements [`Display`](std::fmt::Display).
203///
204/// ```rust
205/// use std::fmt;
206/// use serde_plain::derive_serialize_from_display;
207/// # fn main() {
208///
209/// pub struct MyStruct(u32);
210///
211/// impl fmt::Display for MyStruct {
212///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213///         write!(f, "{}", self.0)
214///     }
215/// }
216///
217/// derive_serialize_from_display!(MyStruct);
218/// # }
219/// ```
220///
221/// This automatically implements [`Serialize`](serde::Serialize) which will
222/// invoke the [`to_string`](crate::to_string) method on the target.
223#[macro_export]
224macro_rules! derive_serialize_from_display {
225    ($type:ident $(:: $type_extra:ident)* < $($lt:lifetime),+ >) => {
226        impl<$($lt,)*> ::serde::ser::Serialize for $type$(:: $type_extra)*<$($lt,)*> {
227            fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
228            where
229                S: ::serde::ser::Serializer,
230            {
231                serializer.serialize_str(&self.to_string())
232            }
233        }
234    };
235    ($type:ty) => {
236        impl ::serde::ser::Serialize for $type {
237            fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
238            where
239                S: ::serde::ser::Serializer,
240            {
241                serializer.serialize_str(&self.to_string())
242            }
243        }
244    };
245}
246
247#[test]
248fn test_derive_display_from_serialize_lifetimes() {
249    use serde_derive::Serialize;
250
251    #[derive(Serialize)]
252    struct MyType<'a>(&'a str);
253
254    mod inner {
255        use serde_derive::Serialize;
256
257        #[derive(Serialize)]
258        pub struct MyType<'a>(pub &'a str);
259    }
260
261    derive_display_from_serialize!(MyType<'a>);
262    derive_display_from_serialize!(inner::MyType<'a>);
263
264    assert_eq!(MyType("x").to_string(), "x");
265    assert_eq!(inner::MyType("x").to_string(), "x");
266}
267
268#[test]
269fn test_derive_serialize_from_display_lifetimes() {
270    use serde_derive::Deserialize;
271
272    #[derive(Deserialize)]
273    struct MyType<'a>(&'a str);
274
275    impl<'a> std::fmt::Display for MyType<'a> {
276        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277            write!(f, "{}", self.0)
278        }
279    }
280
281    mod inner {
282        use serde_derive::Deserialize;
283
284        #[derive(Deserialize)]
285        pub struct MyType<'a>(pub &'a str);
286
287        impl<'a> std::fmt::Display for MyType<'a> {
288            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289                write!(f, "{}", self.0)
290            }
291        }
292    }
293
294    derive_serialize_from_display!(MyType<'a>);
295    derive_serialize_from_display!(inner::MyType<'a>);
296
297    assert_eq!(crate::to_string(&MyType("x")).unwrap(), "x");
298    assert_eq!(crate::to_string(&inner::MyType("x")).unwrap(), "x");
299}