serde_vars/source/
mod.rs

1//! Dynamic variable expansion.
2
3use std::borrow::Cow;
4
5use serde::de;
6
7mod file;
8mod string;
9mod tuple;
10mod utils;
11
12pub use self::file::*;
13pub use self::string::*;
14
15/// A [`Source`] expands a variable string into a concrete value.
16///
17/// A source may choose to not expand a value and indicate that by either returning `None` or
18/// [`Expansion::Original`].
19pub trait Source {
20    /// Expands a variable string to a boolean.
21    fn expand_bool<E>(&mut self, v: &str) -> Result<Option<bool>, E>
22    where
23        E: de::Error;
24
25    /// Expands a variable string to an `i8`.
26    fn expand_i8<E>(&mut self, v: &str) -> Result<Option<i8>, E>
27    where
28        E: de::Error;
29
30    /// Expands a variable string to an `i16`.
31    fn expand_i16<E>(&mut self, v: &str) -> Result<Option<i16>, E>
32    where
33        E: de::Error;
34
35    /// Expands a variable string to an `i32`.
36    fn expand_i32<E>(&mut self, v: &str) -> Result<Option<i32>, E>
37    where
38        E: de::Error;
39
40    /// Expands a variable string to an `i64`.
41    fn expand_i64<E>(&mut self, v: &str) -> Result<Option<i64>, E>
42    where
43        E: de::Error;
44
45    /// Expands a variable string to an `u8`.
46    fn expand_u8<E>(&mut self, v: &str) -> Result<Option<u8>, E>
47    where
48        E: de::Error;
49
50    /// Expands a variable string to an `u16`.
51    fn expand_u16<E>(&mut self, v: &str) -> Result<Option<u16>, E>
52    where
53        E: de::Error;
54
55    /// Expands a variable string to an `u32`.
56    fn expand_u32<E>(&mut self, v: &str) -> Result<Option<u32>, E>
57    where
58        E: de::Error;
59
60    /// Expands a variable string to an `u64`.
61    fn expand_u64<E>(&mut self, v: &str) -> Result<Option<u64>, E>
62    where
63        E: de::Error;
64
65    /// Expands a variable string to a `f32`.
66    fn expand_f32<E>(&mut self, v: &str) -> Result<Option<f32>, E>
67    where
68        E: de::Error;
69
70    /// Expands a variable string to a `f64`.
71    fn expand_f64<E>(&mut self, v: &str) -> Result<Option<f64>, E>
72    where
73        E: de::Error;
74
75    /// Expands a variable string to string.
76    fn expand_str<'a, E>(&mut self, v: Cow<'a, str>) -> Result<Expansion<Cow<'a, str>>, E>
77    where
78        E: de::Error;
79
80    /// Expands bytes into other bytes.
81    ///
82    /// Implementations which can expand strings, should also expand byte sequences
83    /// which are valid utf-8.
84    fn expand_bytes<'a, E>(&mut self, v: Cow<'a, [u8]>) -> Result<Expansion<Cow<'a, [u8]>>, E>
85    where
86        E: de::Error;
87
88    /// Expands a variable string to [`Any`].
89    ///
90    /// Required for self-describing deserialization, where the resulting type
91    /// depends on the type deserialized.
92    ///
93    /// For strings this needs the same behaviour as [`Source::expand_str`].
94    fn expand_any<'a, E>(&mut self, v: Cow<'a, str>) -> Result<Expansion<Any<'a>, Cow<'a, str>>, E>
95    where
96        E: de::Error;
97}
98
99/// Value returned by certain methods of [`Source`].
100///
101/// The type is used to indicate whether an expansion took place, and in case it did not, give back
102/// the original value.
103pub enum Expansion<T, S = T> {
104    /// The source expanded the value into a new value.
105    Expanded(T),
106    /// The source returned the original value and did not expand it.
107    Original(S),
108}
109
110impl<T> Expansion<T> {
111    pub(crate) fn map<S, F>(self, f: F) -> Expansion<S>
112    where
113        F: FnOnce(T) -> S,
114    {
115        match self {
116            Expansion::Expanded(v) => Expansion::Expanded(f(v)),
117            Expansion::Original(v) => Expansion::Original(f(v)),
118        }
119    }
120
121    pub(crate) fn collapse(self) -> T {
122        match self {
123            Expansion::Expanded(v) => v,
124            Expansion::Original(v) => v,
125        }
126    }
127}
128
129impl<'a> Expansion<Any<'a>, Cow<'a, str>> {
130    pub(crate) fn visit<'de, V, E>(self, visitor: V) -> Result<V::Value, E>
131    where
132        V: de::Visitor<'de>,
133        E: de::Error,
134    {
135        match self {
136            Expansion::Expanded(expanded) => expanded.visit(visitor),
137            Expansion::Original(Cow::Owned(v)) => visitor.visit_string(v),
138            Expansion::Original(Cow::Borrowed(v)) => visitor.visit_str(v),
139        }
140    }
141
142    pub(crate) fn visit_borrowed<V, E>(self, visitor: V) -> Result<V::Value, E>
143    where
144        V: de::Visitor<'a>,
145        E: de::Error,
146    {
147        match self {
148            Expansion::Expanded(expanded) => expanded.visit_borrowed(visitor),
149            Expansion::Original(Cow::Owned(v)) => visitor.visit_string(v),
150            Expansion::Original(Cow::Borrowed(v)) => visitor.visit_borrowed_str(v),
151        }
152    }
153}
154
155/// Type returned by [`Source::expand_any`].
156///
157/// Represents any primitive type that can be parsed by a [`Source`].
158pub enum Any<'a> {
159    Bool(bool),
160    I8(i8),
161    I16(i16),
162    I32(i32),
163    I64(i64),
164    U8(u8),
165    U16(u16),
166    U32(u32),
167    U64(u64),
168    F32(f32),
169    F64(f64),
170    Str(Cow<'a, str>),
171    Bytes(Cow<'a, [u8]>),
172}
173
174impl<'a> Any<'a> {
175    /// Turns this [`Self`] into a [`de::Unexpected`] for error handling.
176    pub fn unexpected(&self) -> de::Unexpected<'_> {
177        match self {
178            Any::Bool(v) => de::Unexpected::Bool(*v),
179            Any::I8(v) => de::Unexpected::Signed(i64::from(*v)),
180            Any::I16(v) => de::Unexpected::Signed(i64::from(*v)),
181            Any::I32(v) => de::Unexpected::Signed(i64::from(*v)),
182            Any::I64(v) => de::Unexpected::Signed(*v),
183            Any::U8(v) => de::Unexpected::Unsigned(u64::from(*v)),
184            Any::U16(v) => de::Unexpected::Unsigned(u64::from(*v)),
185            Any::U32(v) => de::Unexpected::Unsigned(u64::from(*v)),
186            Any::U64(v) => de::Unexpected::Unsigned(*v),
187            Any::F32(v) => de::Unexpected::Float(f64::from(*v)),
188            Any::F64(v) => de::Unexpected::Float(*v),
189            Any::Str(v) => de::Unexpected::Str(v),
190            Any::Bytes(v) => de::Unexpected::Bytes(v),
191        }
192    }
193
194    pub(crate) fn visit_borrowed<V, E>(self, visitor: V) -> Result<V::Value, E>
195    where
196        V: de::Visitor<'a>,
197        E: de::Error,
198    {
199        match self {
200            Any::Str(Cow::Borrowed(v)) => visitor.visit_borrowed_str(v),
201            Any::Bytes(Cow::Borrowed(v)) => visitor.visit_borrowed_bytes(v),
202            other => other.visit(visitor),
203        }
204    }
205
206    pub(crate) fn visit<'de, V, E>(self, visitor: V) -> Result<V::Value, E>
207    where
208        V: de::Visitor<'de>,
209        E: de::Error,
210    {
211        match self {
212            Any::Bool(v) => visitor.visit_bool(v),
213            Any::I8(v) => visitor.visit_i8(v),
214            Any::I16(v) => visitor.visit_i16(v),
215            Any::I32(v) => visitor.visit_i32(v),
216            Any::I64(v) => visitor.visit_i64(v),
217            Any::U8(v) => visitor.visit_u8(v),
218            Any::U16(v) => visitor.visit_u16(v),
219            Any::U32(v) => visitor.visit_u32(v),
220            Any::U64(v) => visitor.visit_u64(v),
221            Any::F32(v) => visitor.visit_f32(v),
222            Any::F64(v) => visitor.visit_f64(v),
223            Any::Str(Cow::Owned(v)) => visitor.visit_string(v),
224            Any::Str(Cow::Borrowed(v)) => visitor.visit_str(v),
225            Any::Bytes(Cow::Owned(v)) => visitor.visit_byte_buf(v),
226            Any::Bytes(Cow::Borrowed(v)) => visitor.visit_bytes(v),
227        }
228    }
229}