serde_with/
with_suffix.rs

1use crate::prelude::*;
2
3/// Serialize with an added suffix on every field name and deserialize by
4/// trimming away the suffix.
5///
6/// You can set the visibility of the generated module by suffixing the module name with a module visibility.
7/// `with_suffix!(pub(crate) suffix_foo "_foo");` creates a module with `pub(crate)` visibility.
8/// The visibility is optional and by default `pub(self)`, i.e., private visibility is assumed.
9///
10/// **Note:** Use of this macro is incompatible with applying the [`deny_unknown_fields`] attribute
11/// on the container.
12/// While deserializing, it will always warn about unknown fields, even though they are processed
13/// by the `with_suffix` wrapper.
14/// More details can be found in [this issue][issue-with_suffix-deny_unknown_fields].
15///
16/// # Example
17///
18/// [Factorio Prototype tables] like to use suffixes to group related fields. In
19/// simplified form, their JSON representation may resemble the following:
20///
21/// [Factorio Prototype tables]: https://lua-api.factorio.com/2.0.13/types/PipePictures.html
22///
23/// ```json
24/// {
25///   "frames": 4,
26///   "spritesheet": "normal",
27///   "frames_frozen": 1,
28///   "spritesheet_frozen": "frozen",
29///   "frames_visualization": 2,
30///   "spritesheet_visualization": "vis",
31/// }
32/// ```
33///
34/// In Rust, we would ideally like to model this data as a couple of `SpriteData`
35/// structs, rather than repeating the fields of `SpriteData` for each suffix.
36///
37/// ```rust
38/// # #[allow(dead_code)]
39/// struct Graphics {
40///     normal: SpriteData,
41///     frozen: SpriteData,
42///     visualization: SpriteData,
43/// }
44///
45/// # #[allow(dead_code)]
46/// struct SpriteData {
47///     frames: u64,
48///     spritesheet: String,
49/// }
50/// ```
51///
52/// This `with_suffix!` macro produces an adapter that adds a suffix onto field
53/// names during serialization and trims away the suffix during deserialization.
54/// An implementation for the mentioned situation would use `with_suffix!` like this:
55///
56/// ```rust
57/// use serde::{Deserialize, Serialize};
58/// use serde_with::with_suffix;
59///
60/// #[derive(Serialize, Deserialize)]
61/// struct Graphics {
62///     #[serde(flatten)]
63///     normal: SpriteData,
64///     #[serde(flatten, with = "suffix_frozen")]
65///     frozen: SpriteData,
66///     #[serde(flatten, with = "suffix_visualization")]
67///     visualization: SpriteData,
68/// }
69///
70/// #[derive(Serialize, Deserialize)]
71/// struct SpriteData {
72///     frames: u64,
73///     spritesheet: String,
74/// }
75///
76/// with_suffix!(suffix_frozen "_frozen");
77/// // You can also set the visibility of the generated suffix module, the default is private.
78/// with_suffix!(pub suffix_visualization "_visualization");
79/// #
80/// # const EXPECTED: &str = r#"{
81/// #   "frames": 4,
82/// #   "spritesheet": "normal",
83/// #   "frames_frozen": 1,
84/// #   "spritesheet_frozen": "frozen",
85/// #   "frames_visualization": 2,
86/// #   "spritesheet_visualization": "vis"
87/// # }"#;
88///
89/// fn main() {
90///     let g = Graphics {
91///         normal: SpriteData {
92///             frames: 4,
93///             spritesheet: "normal".to_owned(),
94///         },
95///         frozen: SpriteData {
96///             frames: 1,
97///             spritesheet: "frozen".to_owned(),
98///         },
99///         visualization: SpriteData {
100///             frames: 2,
101///             spritesheet: "vis".to_owned(),
102///         },
103///     };
104///
105///     let j = serde_json::to_string_pretty(&g).unwrap();
106///     println!("{}", j);
107/// #
108/// #     assert_eq!(j, EXPECTED);
109/// }
110/// ```
111///
112/// [`deny_unknown_fields`]: https://serde.rs/container-attrs.html#deny_unknown_fields
113/// [issue-with_suffix-deny_unknown_fields]: https://github.com/jonasbb/serde_with/issues/57
114#[macro_export]
115macro_rules! with_suffix {
116    ($module:ident $suffix:expr) => {$crate::with_suffix!(pub(self) $module $suffix);};
117    ($vis:vis $module:ident $suffix:expr) => {
118        $vis mod $module {
119            use $crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
120            use $crate::with_suffix::WithSuffix;
121
122            #[allow(dead_code)]
123            pub fn serialize<T, S>(object: &T, serializer: S) -> $crate::__private__::Result<S::Ok, S::Error>
124            where
125                T: Serialize,
126                S: Serializer,
127            {
128                object.serialize(WithSuffix {
129                    delegate: serializer,
130                    suffix: $suffix,
131                })
132            }
133
134            #[allow(dead_code)]
135            pub fn deserialize<'de, T, D>(deserializer: D) -> $crate::__private__::Result<T, D::Error>
136            where
137                T: Deserialize<'de>,
138                D: Deserializer<'de>,
139            {
140                T::deserialize(WithSuffix {
141                    delegate: deserializer,
142                    suffix: $suffix,
143                })
144            }
145        }
146    };
147}
148
149pub struct WithSuffix<'a, T> {
150    pub delegate: T,
151    pub suffix: &'a str,
152}
153
154impl<T> Serialize for WithSuffix<'_, T>
155where
156    T: Serialize,
157{
158    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
159    where
160        S: Serializer,
161    {
162        self.delegate.serialize(WithSuffix {
163            delegate: serializer,
164            suffix: self.suffix,
165        })
166    }
167}
168
169impl<'a, S> Serializer for WithSuffix<'a, S>
170where
171    S: Serializer,
172{
173    type Ok = S::Ok;
174    type Error = S::Error;
175    type SerializeSeq = Impossible<Self::Ok, Self::Error>;
176    type SerializeTuple = Impossible<Self::Ok, Self::Error>;
177    type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
178    type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
179    type SerializeMap = WithSuffix<'a, S::SerializeMap>;
180    type SerializeStruct = WithSuffix<'a, S::SerializeMap>;
181    type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
182
183    fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
184        Err(SerError::custom("wrong type for with_suffix"))
185    }
186
187    fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
188        Err(SerError::custom("wrong type for with_suffix"))
189    }
190
191    fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
192        Err(SerError::custom("wrong type for with_suffix"))
193    }
194
195    fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
196        Err(SerError::custom("wrong type for with_suffix"))
197    }
198
199    fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
200        Err(SerError::custom("wrong type for with_suffix"))
201    }
202
203    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
204        Err(SerError::custom("wrong type for with_suffix"))
205    }
206
207    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
208        Err(SerError::custom("wrong type for with_suffix"))
209    }
210
211    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
212        Err(SerError::custom("wrong type for with_suffix"))
213    }
214
215    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
216        Err(SerError::custom("wrong type for with_suffix"))
217    }
218
219    fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
220        Err(SerError::custom("wrong type for with_suffix"))
221    }
222
223    fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
224        Err(SerError::custom("wrong type for with_suffix"))
225    }
226
227    fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
228        Err(SerError::custom("wrong type for with_suffix"))
229    }
230
231    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
232        self.delegate
233            .collect_str(&format_args!("{}{}", v, self.suffix))
234    }
235
236    fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
237        Err(SerError::custom("wrong type for with_suffix"))
238    }
239
240    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
241        self.delegate.serialize_none()
242    }
243
244    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
245    where
246        T: ?Sized + Serialize,
247    {
248        self.delegate.serialize_some(&WithSuffix {
249            delegate: value,
250            suffix: self.suffix,
251        })
252    }
253
254    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
255        Err(SerError::custom("wrong type for with_suffix"))
256    }
257
258    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
259        Err(SerError::custom("wrong type for with_suffix"))
260    }
261
262    fn serialize_unit_variant(
263        self,
264        _name: &'static str,
265        _variant_index: u32,
266        variant: &'static str,
267    ) -> Result<Self::Ok, Self::Error> {
268        self.serialize_str(variant)
269    }
270
271    fn serialize_newtype_struct<T>(
272        self,
273        _name: &'static str,
274        _value: &T,
275    ) -> Result<Self::Ok, Self::Error>
276    where
277        T: ?Sized + Serialize,
278    {
279        Err(SerError::custom("wrong type for with_suffix"))
280    }
281
282    fn serialize_newtype_variant<T>(
283        self,
284        _name: &'static str,
285        _variant_index: u32,
286        _variant: &'static str,
287        _value: &T,
288    ) -> Result<Self::Ok, Self::Error>
289    where
290        T: ?Sized + Serialize,
291    {
292        Err(SerError::custom("wrong type for with_suffix"))
293    }
294
295    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
296        Err(SerError::custom("wrong type for with_suffix"))
297    }
298
299    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
300        Err(SerError::custom("wrong type for with_suffix"))
301    }
302
303    fn serialize_tuple_struct(
304        self,
305        _name: &'static str,
306        _len: usize,
307    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
308        Err(SerError::custom("wrong type for with_suffix"))
309    }
310
311    fn serialize_tuple_variant(
312        self,
313        _name: &'static str,
314        _variant_index: u32,
315        _variant: &'static str,
316        _len: usize,
317    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
318        Err(SerError::custom("wrong type for with_suffix"))
319    }
320
321    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
322        Ok(WithSuffix {
323            delegate: self.delegate.serialize_map(len)?,
324            suffix: self.suffix,
325        })
326    }
327
328    fn serialize_struct(
329        self,
330        _name: &'static str,
331        len: usize,
332    ) -> Result<Self::SerializeStruct, Self::Error> {
333        self.serialize_map(Some(len))
334    }
335
336    fn serialize_struct_variant(
337        self,
338        _name: &'static str,
339        _variant_index: u32,
340        _variant: &'static str,
341        _len: usize,
342    ) -> Result<Self::SerializeStructVariant, Self::Error> {
343        Err(SerError::custom("wrong type for with_suffix"))
344    }
345}
346
347impl<S> SerializeMap for WithSuffix<'_, S>
348where
349    S: SerializeMap,
350{
351    type Ok = S::Ok;
352    type Error = S::Error;
353
354    fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
355    where
356        T: ?Sized + Serialize,
357    {
358        self.delegate.serialize_key(&WithSuffix {
359            delegate: key,
360            suffix: self.suffix,
361        })
362    }
363
364    fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
365    where
366        T: ?Sized + Serialize,
367    {
368        self.delegate.serialize_value(value)
369    }
370
371    fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
372    where
373        K: ?Sized + Serialize,
374        V: ?Sized + Serialize,
375    {
376        self.delegate.serialize_entry(
377            &WithSuffix {
378                delegate: key,
379                suffix: self.suffix,
380            },
381            value,
382        )
383    }
384
385    fn end(self) -> Result<Self::Ok, Self::Error> {
386        self.delegate.end()
387    }
388}
389
390impl<S> SerializeStruct for WithSuffix<'_, S>
391where
392    S: SerializeMap,
393{
394    type Ok = S::Ok;
395    type Error = S::Error;
396
397    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
398    where
399        T: ?Sized + Serialize,
400    {
401        let mut suffixed_key = String::with_capacity(key.len() + self.suffix.len());
402        suffixed_key.push_str(key);
403        suffixed_key.push_str(self.suffix);
404        self.delegate.serialize_entry(&suffixed_key, value)
405    }
406
407    fn end(self) -> Result<Self::Ok, Self::Error> {
408        self.delegate.end()
409    }
410}
411
412impl<'de, T> DeserializeSeed<'de> for WithSuffix<'_, T>
413where
414    T: DeserializeSeed<'de>,
415{
416    type Value = T::Value;
417
418    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
419    where
420        D: Deserializer<'de>,
421    {
422        self.delegate.deserialize(WithSuffix {
423            delegate: deserializer,
424            suffix: self.suffix,
425        })
426    }
427}
428
429impl<'de, D> Deserializer<'de> for WithSuffix<'_, D>
430where
431    D: Deserializer<'de>,
432{
433    type Error = D::Error;
434
435    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
436    where
437        V: Visitor<'de>,
438    {
439        self.delegate.deserialize_map(WithSuffix {
440            delegate: visitor,
441            suffix: self.suffix,
442        })
443    }
444
445    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
446    where
447        V: Visitor<'de>,
448    {
449        self.delegate.deserialize_any(WithSuffixOption {
450            first_key: None,
451            delegate: visitor,
452            suffix: self.suffix,
453        })
454    }
455
456    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
457    where
458        V: Visitor<'de>,
459    {
460        self.delegate.deserialize_identifier(WithSuffix {
461            delegate: visitor,
462            suffix: self.suffix,
463        })
464    }
465
466    forward_to_deserialize_any! {
467        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
468        bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct
469        map struct enum ignored_any
470    }
471}
472
473impl<'de, V> Visitor<'de> for WithSuffix<'_, V>
474where
475    V: Visitor<'de>,
476{
477    type Value = V::Value;
478
479    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
480        self.delegate.expecting(formatter)
481    }
482
483    fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
484    where
485        A: MapAccess<'de>,
486    {
487        self.delegate.visit_map(WithSuffix {
488            delegate: map,
489            suffix: self.suffix,
490        })
491    }
492}
493
494impl<'de, A> MapAccess<'de> for WithSuffix<'_, A>
495where
496    A: MapAccess<'de>,
497{
498    type Error = A::Error;
499
500    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
501    where
502        K: DeserializeSeed<'de>,
503    {
504        while let Some(s) = self.delegate.next_key::<String>()? {
505            if let Some(without_suffix) = s.strip_suffix(self.suffix) {
506                return seed
507                    .deserialize(without_suffix.into_deserializer())
508                    .map(Some);
509            }
510            self.delegate.next_value::<IgnoredAny>()?;
511        }
512        Ok(None)
513    }
514
515    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
516    where
517        V: DeserializeSeed<'de>,
518    {
519        self.delegate.next_value_seed(seed)
520    }
521}
522
523pub struct WithSuffixOption<'a, T> {
524    first_key: Option<String>,
525    delegate: T,
526    suffix: &'a str,
527}
528
529impl<'de, V> Visitor<'de> for WithSuffixOption<'_, V>
530where
531    V: Visitor<'de>,
532{
533    type Value = V::Value;
534
535    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
536        self.delegate.expecting(formatter)
537    }
538
539    fn visit_unit<E>(self) -> Result<Self::Value, E>
540    where
541        E: DeError,
542    {
543        self.delegate.visit_none()
544    }
545
546    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
547    where
548        A: MapAccess<'de>,
549    {
550        while let Some(s) = map.next_key::<String>()? {
551            if s.ends_with(self.suffix) {
552                return self.delegate.visit_some(WithSuffixOption {
553                    first_key: Some(s),
554                    delegate: map,
555                    suffix: self.suffix,
556                });
557            }
558            map.next_value::<IgnoredAny>()?;
559        }
560        self.delegate.visit_none()
561    }
562}
563
564impl<'de, A> Deserializer<'de> for WithSuffixOption<'_, A>
565where
566    A: MapAccess<'de>,
567{
568    type Error = A::Error;
569
570    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
571    where
572        V: Visitor<'de>,
573    {
574        visitor.visit_map(self)
575    }
576
577    forward_to_deserialize_any! {
578        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
579        bytes byte_buf option unit unit_struct newtype_struct seq tuple
580        tuple_struct map struct enum identifier ignored_any
581    }
582}
583
584impl<'de, A> MapAccess<'de> for WithSuffixOption<'_, A>
585where
586    A: MapAccess<'de>,
587{
588    type Error = A::Error;
589
590    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
591    where
592        K: DeserializeSeed<'de>,
593    {
594        if let Some(s) = self.first_key.take() {
595            let without_suffix = s[0..s.len() - self.suffix.len()].into_deserializer();
596            return seed.deserialize(without_suffix).map(Some);
597        }
598        while let Some(s) = self.delegate.next_key::<String>()? {
599            if let Some(without_suffix) = s.strip_suffix(self.suffix) {
600                return seed
601                    .deserialize(without_suffix.into_deserializer())
602                    .map(Some);
603            }
604            self.delegate.next_value::<IgnoredAny>()?;
605        }
606        Ok(None)
607    }
608
609    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
610    where
611        V: DeserializeSeed<'de>,
612    {
613        self.delegate.next_value_seed(seed)
614    }
615}