serde_constant/
lib.rs

1//! This crate provides a type that can represent a single-const serde value. For example, asserting that a particular bool is always true.
2//! You can use this for disambiguation in `serde(untagged)` structures, or just for validation.
3//!
4//! # Examples
5//!
6//! ```rust
7//! # use serde::Deserialize;
8//! # use serde_json::json;
9//! use serde_constant::ConstBool;
10//! #[derive(Deserialize)]
11//! struct Foo {
12//!     bar: String,
13//!     baz: ConstBool<true>,
14//! }
15//!
16//! assert!(serde_json::from_value::<Foo>(json!({ "bar": "quux", "baz": true })).is_ok());
17//! assert!(serde_json::from_value::<Foo>(json!({ "bar": "quux", "baz": false })).is_err());
18//! ```
19//!
20//! ```
21//! # use serde::Deserialize;
22//! # use serde_json::{json, from_value};
23//! # use std::error::Error;
24//! use serde_constant::ConstI64;
25//! // int tags? No problem!
26//! #[derive(Deserialize)]
27//! #[serde(untagged)]
28//! enum Foo {
29//!     Bar {
30//!         tag: ConstI64<1>,
31//!     },
32//!     Baz {
33//!         tag: ConstI64<2>,
34//!         x: Option<String>,
35//!     },
36//! }
37//! # fn main() -> Result<(), Box<dyn Error>> {
38//! assert!(matches!(
39//!     serde_json::from_value(json!({ "tag": 2, "x": null }))?,
40//!     // would have been Bar if `tag` were just `i64`
41//!     Foo::Baz { x: None, .. },
42//! ));
43//! # Ok(()) }
44//! ```
45#![no_std]
46#![allow(clippy::unnecessary_cast)]
47#![warn(missing_docs)]
48use core::fmt;
49use serde::{
50    de::{self, Unexpected, Visitor},
51    Deserialize, Deserializer, Serialize, Serializer,
52};
53
54/// A const `bool`.
55///
56/// Deserialization fails if the value is not `V`.
57#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
58pub struct ConstBool<const V: bool>;
59
60impl<const V: bool> Serialize for ConstBool<V> {
61    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
62    where
63        S: Serializer,
64    {
65        serializer.serialize_bool(V)
66    }
67}
68
69impl<'de, const V: bool> Deserialize<'de> for ConstBool<V> {
70    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
71    where
72        D: Deserializer<'de>,
73    {
74        deserializer.deserialize_bool(ConstBoolVisitor::<V>)
75    }
76}
77
78struct ConstBoolVisitor<const V: bool>;
79
80impl<'de, const V: bool> Visitor<'de> for ConstBoolVisitor<V> {
81    type Value = ConstBool<V>;
82    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
83        write!(formatter, "{V}")
84    }
85    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
86    where
87        E: de::Error,
88    {
89        if v == V {
90            Ok(ConstBool::<V>)
91        } else {
92            Err(E::invalid_value(Unexpected::Bool(v), &self))
93        }
94    }
95}
96
97macro_rules! declare_int {
98    ($($type:ty => $struct:ident $visitor:ident $ser_func:ident $deser_func:ident),* $(,)?) => {
99        $(
100            #[doc = concat!("A const `", stringify!($type), "`.")]
101            ///
102            /// Deserialization fails if the value is not `V`.
103            #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
104            pub struct $struct<const V: $type>;
105
106            impl<const V: $type> Serialize for $struct<V> {
107                fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108                where
109                    S: Serializer,
110                {
111                    serializer.$ser_func(V)
112                }
113            }
114
115            impl<'de, const V: $type> Deserialize<'de> for $struct<V> {
116                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
117                where
118                    D: Deserializer<'de>,
119                {
120                    deserializer.$deser_func($visitor::<V>)
121                }
122            }
123
124            struct $visitor<const V: $type>;
125
126            impl<'de, const V: $type> Visitor<'de> for $visitor<V> {
127                type Value = $struct<V>;
128                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
129                    write!(formatter, "{V}")
130                }
131                fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
132                where
133                    E: de::Error,
134                {
135                    self.visit_i128(v as i128)
136                }
137                fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
138                where
139                    E: de::Error,
140                {
141                    self.visit_i128(v as i128)
142                }
143                fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
144                where
145                    E: de::Error,
146                {
147                    self.visit_i128(v as i128)
148                }
149                fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
150                where
151                    E: de::Error,
152                {
153                    self.visit_i128(v as i128)
154                }
155                fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
156                where
157                    E: de::Error,
158                {
159                    if v == V as i128 {
160                        Ok($struct::<V>)
161                    } else {
162                        Err(E::invalid_value(Unexpected::Signed(V as i64), &self))
163                    }
164                }
165                fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
166                where
167                    E: de::Error,
168                {
169                    self.visit_i128(v as i128)
170                }
171                fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
172                where
173                    E: de::Error,
174                {
175                    self.visit_i128(v as i128)
176                }
177                fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
178                where
179                    E: de::Error,
180                {
181                    self.visit_i128(v as i128)
182                }
183                fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
184                where
185                    E: de::Error,
186                {
187                    self.visit_i128(v as i128)
188                }
189                fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
190                where
191                    E: de::Error,
192                {
193                    self.visit_i128(
194                        i128::try_from(v)
195                            .map_err(|_| E::invalid_value(Unexpected::Unsigned(v as u64), &Self))?,
196                    )
197                }
198            }
199        )*
200    };
201}
202
203declare_int!(
204    i8 => ConstI8 ConstI8Visitor serialize_i8 deserialize_i8,
205    i16 => ConstI16 ConstI16Visitor serialize_i16 deserialize_i16,
206    i32 => ConstI32 ConstI32Visitor serialize_i32 deserialize_i32,
207    i64 => ConstI64 ConstI64Visitor serialize_i64 deserialize_i64,
208    i128 => ConstI128 ConstI128Visitor serialize_i128 deserialize_i128,
209);
210
211macro_rules! declare_uint {
212    ($($type:ty => $struct:ident $visitor:ident $ser_func:ident $deser_func:ident),* $(,)?) => {
213        $(
214            #[doc = concat!("A const `", stringify!($type), "`.")]
215            ///
216            ///  Deserialization fails if the value is not `V`.
217            #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
218            pub struct $struct<const V: $type>;
219
220            impl<const V: $type> Serialize for $struct<V> {
221                fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
222                where
223                    S: Serializer,
224                {
225                    serializer.$ser_func(V)
226                }
227            }
228
229            impl<'de, const V: $type> Deserialize<'de> for $struct<V> {
230                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
231                where
232                    D: Deserializer<'de>,
233                {
234                    deserializer.$deser_func($visitor::<V>)
235                }
236            }
237
238            struct $visitor<const V: $type>;
239
240            impl<'de, const V: $type> Visitor<'de> for $visitor<V> {
241                type Value = $struct<V>;
242                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
243                    write!(formatter, "{V}")
244                }
245                fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
246                where
247                    E: de::Error,
248                {
249                    self.visit_i128(v as i128)
250                }
251                fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
252                where
253                    E: de::Error,
254                {
255                    self.visit_i128(v as i128)
256                }
257                fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
258                where
259                    E: de::Error,
260                {
261                    self.visit_i128(v as i128)
262                }
263                fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
264                where
265                    E: de::Error,
266                {
267                    self.visit_i128(v as i128)
268                }
269                fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
270                where
271                    E: de::Error,
272                {
273                    if v < 0 {
274                        Err(E::invalid_value(Unexpected::Signed(v as i64), &self))
275                    } else {
276                        self.visit_u128(v as u128)
277                    }
278                }
279                fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
280                where
281                    E: de::Error,
282                {
283                    self.visit_u128(v as u128)
284                }
285                fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
286                where
287                    E: de::Error,
288                {
289                    self.visit_u128(v as u128)
290                }
291                fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
292                where
293                    E: de::Error,
294                {
295                    self.visit_u128(v as u128)
296                }
297                fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
298                where
299                    E: de::Error,
300                {
301                    self.visit_u128(v as u128)
302                }
303                fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
304                where
305                    E: de::Error,
306                {
307                    if v == V as u128 {
308                        Ok($struct::<V>)
309                    } else {
310                        Err(E::invalid_value(Unexpected::Unsigned(v as u64), &self))
311                    }
312                }
313            }
314        )*
315    };
316}
317
318declare_uint!(
319    u8 => ConstU8 ConstU8Visitor serialize_u8 deserialize_u8,
320    u16 => ConstU16 ConstU16Visitor serialize_u16 deserialize_u16,
321    u32 => ConstU32 ConstU32Visitor serialize_u32 deserialize_u32,
322    u64 => ConstU64 ConstU64Visitor serialize_u64 deserialize_u64,
323    u128 => ConstU128 ConstU128Visitor serialize_u128 deserialize_u128,
324);
325
326/// A const `char`.
327///
328/// Deserialization fails if the value is not `V`.
329#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
330pub struct ConstChar<const V: char>;
331
332impl<const V: char> Serialize for ConstChar<V> {
333    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
334    where
335        S: Serializer,
336    {
337        serializer.serialize_char(V)
338    }
339}
340
341impl<'de, const V: char> Deserialize<'de> for ConstChar<V> {
342    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
343    where
344        D: Deserializer<'de>,
345    {
346        deserializer.deserialize_char(ConstCharVisitor::<V>)
347    }
348}
349
350struct ConstCharVisitor<const V: char>;
351
352impl<'de, const V: char> Visitor<'de> for ConstCharVisitor<V> {
353    type Value = ConstChar<V>;
354    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
355        write!(formatter, "'{V}'")
356    }
357    fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
358    where
359        E: de::Error,
360    {
361        if v == V {
362            Ok(ConstChar::<V>)
363        } else {
364            Err(E::invalid_value(Unexpected::Char(v), &self))
365        }
366    }
367    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
368    where
369        E: de::Error,
370    {
371        let mut chs = v.chars();
372        let ch = chs.next().ok_or_else(|| E::invalid_length(0, &self))?;
373        if chs.next().is_some() {
374            Err(E::invalid_length(2, &self))
375        } else {
376            self.visit_char(ch)
377        }
378    }
379}