serde_file_value/
de.rs

1use std::{fmt, fs, io, path::Path};
2
3use serde::de;
4
5/// A deserializer which automatically reads referenced files.
6///
7/// Files should be referenced like `${file:/path/to/file}`.
8pub struct Deserializer<'a, D, L> {
9    de: D,
10    listener: &'a mut L,
11}
12
13impl<'a, D, L> Deserializer<'a, D, L>
14where
15    L: FnMut(&Path, &io::Result<Vec<u8>>),
16{
17    /// Creates a new deserializer.
18    ///
19    /// The listener will be called on every referenced file read along with the result of the read.
20    pub fn new(de: D, listener: &'a mut L) -> Self {
21        Deserializer { de, listener }
22    }
23}
24
25macro_rules! forward_deserialize {
26    ($name:ident) => {forward_deserialize!($name, );};
27    ($name:ident, $($arg:tt => $ty:ty),*) => {
28        fn $name<V>(self, $($arg: $ty,)* visitor: V) -> Result<V::Value, D::Error>
29            where V: de::Visitor<'de>
30        {
31            let visitor = Visitor {
32                visitor,
33                listener: self.listener,
34            };
35            self.de.$name($($arg,)* visitor)
36        }
37    }
38}
39
40impl<'a, 'de, D, L> de::Deserializer<'de> for Deserializer<'a, D, L>
41where
42    D: de::Deserializer<'de>,
43    L: FnMut(&Path, &io::Result<Vec<u8>>),
44{
45    type Error = D::Error;
46
47    forward_deserialize!(deserialize_any);
48    forward_deserialize!(deserialize_bool);
49    forward_deserialize!(deserialize_u8);
50    forward_deserialize!(deserialize_u16);
51    forward_deserialize!(deserialize_u32);
52    forward_deserialize!(deserialize_u64);
53    forward_deserialize!(deserialize_i8);
54    forward_deserialize!(deserialize_i16);
55    forward_deserialize!(deserialize_i32);
56    forward_deserialize!(deserialize_i64);
57    forward_deserialize!(deserialize_f32);
58    forward_deserialize!(deserialize_f64);
59    forward_deserialize!(deserialize_char);
60    forward_deserialize!(deserialize_str);
61    forward_deserialize!(deserialize_string);
62    forward_deserialize!(deserialize_unit);
63    forward_deserialize!(deserialize_option);
64    forward_deserialize!(deserialize_seq);
65    forward_deserialize!(deserialize_bytes);
66    forward_deserialize!(deserialize_byte_buf);
67    forward_deserialize!(deserialize_map);
68    forward_deserialize!(deserialize_unit_struct, name => &'static str);
69    forward_deserialize!(deserialize_newtype_struct, name => &'static str);
70    forward_deserialize!(deserialize_tuple_struct, name => &'static str, len => usize);
71    forward_deserialize!(deserialize_struct,
72                         name => &'static str,
73                         fields => &'static [&'static str]);
74    forward_deserialize!(deserialize_identifier);
75    forward_deserialize!(deserialize_tuple, len => usize);
76    forward_deserialize!(deserialize_enum,
77                         name => &'static str,
78                         variants => &'static [&'static str]);
79    forward_deserialize!(deserialize_ignored_any);
80}
81
82struct Visitor<'a, V, L> {
83    visitor: V,
84    listener: &'a mut L,
85}
86
87macro_rules! forward_visit {
88    ($name:ident, $ty:ty) => {
89        fn $name<E>(self, v: $ty) -> Result<V::Value, E>
90        where
91            E: de::Error,
92        {
93            self.visitor.$name(v)
94        }
95    };
96}
97
98impl<V, L> Visitor<'_, V, L>
99where
100    L: FnMut(&Path, &io::Result<Vec<u8>>),
101{
102    fn expand_str<E>(&mut self, s: &str) -> Result<Option<String>, E>
103    where
104        E: de::Error,
105    {
106        match s.strip_prefix("${file:").and_then(|s| s.strip_suffix('}')) {
107            Some(path) => {
108                let value = fs::read(path);
109                (self.listener)(path.as_ref(), &value);
110                match value {
111                    Ok(contents) => {
112                        let contents = String::from_utf8(contents).map_err(|e| {
113                            E::custom(format_args!("error parsing file {path}: {e}"))
114                        })?;
115                        Ok(Some(contents))
116                    }
117                    Err(e) => Err(E::custom(format_args!("error reading file {path}: {e}"))),
118                }
119            }
120            None => Ok(None),
121        }
122    }
123}
124
125impl<'de, V, L> de::Visitor<'de> for Visitor<'_, V, L>
126where
127    V: de::Visitor<'de>,
128    L: FnMut(&Path, &io::Result<Vec<u8>>),
129{
130    type Value = V::Value;
131
132    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
133        self.visitor.expecting(formatter)
134    }
135
136    forward_visit!(visit_bool, bool);
137    forward_visit!(visit_i8, i8);
138    forward_visit!(visit_i16, i16);
139    forward_visit!(visit_i32, i32);
140    forward_visit!(visit_i64, i64);
141    forward_visit!(visit_u8, u8);
142    forward_visit!(visit_u16, u16);
143    forward_visit!(visit_u32, u32);
144    forward_visit!(visit_u64, u64);
145    forward_visit!(visit_f32, f32);
146    forward_visit!(visit_f64, f64);
147    forward_visit!(visit_char, char);
148    forward_visit!(visit_bytes, &[u8]);
149    forward_visit!(visit_byte_buf, Vec<u8>);
150
151    fn visit_str<E>(mut self, v: &str) -> Result<Self::Value, E>
152    where
153        E: de::Error,
154    {
155        match self.expand_str(v)? {
156            Some(s) => self.visitor.visit_string(s),
157            None => self.visitor.visit_str(v),
158        }
159    }
160
161    fn visit_string<E>(mut self, v: String) -> Result<Self::Value, E>
162    where
163        E: de::Error,
164    {
165        match self.expand_str(&v)? {
166            Some(s) => self.visitor.visit_string(s),
167            None => self.visitor.visit_string(v),
168        }
169    }
170
171    fn visit_borrowed_str<E>(mut self, v: &'de str) -> Result<Self::Value, E>
172    where
173        E: de::Error,
174    {
175        match self.expand_str(v)? {
176            Some(s) => self.visitor.visit_string(s),
177            None => self.visitor.visit_borrowed_str(v),
178        }
179    }
180
181    fn visit_unit<E>(self) -> Result<V::Value, E>
182    where
183        E: de::Error,
184    {
185        self.visitor.visit_unit()
186    }
187
188    fn visit_none<E>(self) -> Result<V::Value, E>
189    where
190        E: de::Error,
191    {
192        self.visitor.visit_none()
193    }
194
195    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
196    where
197        D: de::Deserializer<'de>,
198    {
199        let deserializer = Deserializer {
200            de: deserializer,
201            listener: self.listener,
202        };
203        self.visitor.visit_some(deserializer)
204    }
205
206    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
207    where
208        D: de::Deserializer<'de>,
209    {
210        let deserializer = Deserializer {
211            de: deserializer,
212            listener: self.listener,
213        };
214        self.visitor.visit_newtype_struct(deserializer)
215    }
216
217    fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
218    where
219        A: de::SeqAccess<'de>,
220    {
221        let visitor = Visitor {
222            visitor: seq,
223            listener: self.listener,
224        };
225        self.visitor.visit_seq(visitor)
226    }
227
228    fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
229    where
230        A: de::MapAccess<'de>,
231    {
232        let visitor = Visitor {
233            visitor: map,
234            listener: self.listener,
235        };
236        self.visitor.visit_map(visitor)
237    }
238
239    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
240    where
241        A: de::EnumAccess<'de>,
242    {
243        let visitor = Visitor {
244            visitor: data,
245            listener: self.listener,
246        };
247        self.visitor.visit_enum(visitor)
248    }
249}
250
251impl<'de, V, L> de::SeqAccess<'de> for Visitor<'_, V, L>
252where
253    V: de::SeqAccess<'de>,
254    L: FnMut(&Path, &io::Result<Vec<u8>>),
255{
256    type Error = V::Error;
257
258    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
259    where
260        T: de::DeserializeSeed<'de>,
261    {
262        let seed = DeserializeSeed {
263            seed,
264            listener: self.listener,
265        };
266        self.visitor.next_element_seed(seed)
267    }
268
269    fn size_hint(&self) -> Option<usize> {
270        self.visitor.size_hint()
271    }
272}
273
274impl<'de, V, L> de::MapAccess<'de> for Visitor<'_, V, L>
275where
276    V: de::MapAccess<'de>,
277    L: FnMut(&Path, &io::Result<Vec<u8>>),
278{
279    type Error = V::Error;
280
281    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
282    where
283        K: de::DeserializeSeed<'de>,
284    {
285        let seed = DeserializeSeed {
286            seed,
287            listener: self.listener,
288        };
289        self.visitor.next_key_seed(seed)
290    }
291
292    fn next_value_seed<S>(&mut self, seed: S) -> Result<S::Value, Self::Error>
293    where
294        S: de::DeserializeSeed<'de>,
295    {
296        let seed = DeserializeSeed {
297            seed,
298            listener: self.listener,
299        };
300        self.visitor.next_value_seed(seed)
301    }
302
303    fn size_hint(&self) -> Option<usize> {
304        self.visitor.size_hint()
305    }
306}
307
308impl<'a, 'de, V, L> de::EnumAccess<'de> for Visitor<'a, V, L>
309where
310    V: de::EnumAccess<'de>,
311    L: FnMut(&Path, &io::Result<Vec<u8>>),
312{
313    type Error = V::Error;
314
315    type Variant = Visitor<'a, V::Variant, L>;
316
317    fn variant_seed<S>(self, seed: S) -> Result<(S::Value, Self::Variant), Self::Error>
318    where
319        S: de::DeserializeSeed<'de>,
320    {
321        let seed = DeserializeSeed {
322            seed,
323            listener: self.listener,
324        };
325        match self.visitor.variant_seed(seed) {
326            Ok((value, variant)) => {
327                let variant = Visitor {
328                    visitor: variant,
329                    listener: self.listener,
330                };
331                Ok((value, variant))
332            }
333            Err(e) => Err(e),
334        }
335    }
336}
337
338impl<'de, V, L> de::VariantAccess<'de> for Visitor<'_, V, L>
339where
340    V: de::VariantAccess<'de>,
341    L: FnMut(&Path, &io::Result<Vec<u8>>),
342{
343    type Error = V::Error;
344
345    fn unit_variant(self) -> Result<(), Self::Error> {
346        self.visitor.unit_variant()
347    }
348
349    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
350    where
351        T: de::DeserializeSeed<'de>,
352    {
353        let seed = DeserializeSeed {
354            seed,
355            listener: self.listener,
356        };
357        self.visitor.newtype_variant_seed(seed)
358    }
359
360    fn tuple_variant<V2>(self, len: usize, visitor: V2) -> Result<V2::Value, Self::Error>
361    where
362        V2: de::Visitor<'de>,
363    {
364        let visitor = Visitor {
365            visitor,
366            listener: self.listener,
367        };
368        self.visitor.tuple_variant(len, visitor)
369    }
370
371    fn struct_variant<V2>(
372        self,
373        fields: &'static [&'static str],
374        visitor: V2,
375    ) -> Result<V2::Value, Self::Error>
376    where
377        V2: de::Visitor<'de>,
378    {
379        let visitor = Visitor {
380            visitor,
381            listener: self.listener,
382        };
383        self.visitor.struct_variant(fields, visitor)
384    }
385}
386
387struct DeserializeSeed<'a, S, L> {
388    seed: S,
389    listener: &'a mut L,
390}
391
392impl<'de, S, L> de::DeserializeSeed<'de> for DeserializeSeed<'_, S, L>
393where
394    S: de::DeserializeSeed<'de>,
395    L: FnMut(&Path, &io::Result<Vec<u8>>),
396{
397    type Value = S::Value;
398
399    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
400    where
401        D: de::Deserializer<'de>,
402    {
403        let deserializer = Deserializer {
404            de: deserializer,
405            listener: self.listener,
406        };
407        self.seed.deserialize(deserializer)
408    }
409}