json_decode/
decoders.rs

1use super::{DecodeError, Decoder};
2use std::convert::{TryFrom, TryInto};
3use std::iter::FromIterator;
4use std::marker::PhantomData;
5
6pub type BoxDecoder<'a, T> = Box<dyn Decoder<'a, T> + 'a + Send + Sync>;
7
8pub fn field<'a, T>(field_name: &str, decoder: BoxDecoder<'a, T>) -> BoxDecoder<'a, T>
9where
10    T: 'a,
11{
12    Box::new(FieldDecoder {
13        field_name: field_name.to_string(),
14        inner_decoder: decoder,
15    })
16}
17
18pub struct FieldDecoder<'a, DecodesTo> {
19    field_name: String,
20    inner_decoder: BoxDecoder<'a, DecodesTo>,
21}
22
23impl<'a, DecodesTo> Decoder<'a, DecodesTo> for FieldDecoder<'a, DecodesTo> {
24    fn decode(&self, value: &serde_json::Value) -> Result<DecodesTo, DecodeError> {
25        match value {
26            serde_json::Value::Object(map) => map
27                .get(&self.field_name)
28                .ok_or_else(|| {
29                    DecodeError::MissingField(self.field_name.clone(), value.to_string())
30                })
31                .and_then(|inner_value| (*self.inner_decoder).decode(inner_value)),
32            _ => Err(DecodeError::IncorrectType(
33                "Object".to_string(),
34                value.to_string(),
35            )),
36        }
37    }
38}
39
40pub fn string() -> BoxDecoder<'static, String> {
41    Box::new(StringDecoder {})
42}
43
44pub struct StringDecoder {}
45
46impl<'a> Decoder<'a, String> for StringDecoder {
47    fn decode(&self, value: &serde_json::Value) -> Result<String, DecodeError> {
48        match value {
49            serde_json::Value::String(s) => Ok(s.clone()),
50            _ => Err(DecodeError::IncorrectType(
51                "String".to_string(),
52                value.to_string(),
53            )),
54        }
55    }
56}
57
58pub fn integer<I: TryFrom<i64>>() -> BoxDecoder<'static, I>
59where
60    I: 'static + Send + Sync,
61{
62    Box::new(IntDecoder {
63        phantom: PhantomData,
64    })
65}
66
67pub struct IntDecoder<I: TryFrom<i64>> {
68    phantom: PhantomData<I>,
69}
70
71impl<'a, I> Decoder<'a, I> for IntDecoder<I>
72where
73    I: TryFrom<i64>,
74{
75    fn decode(&self, value: &serde_json::Value) -> Result<I, DecodeError> {
76        match value {
77            serde_json::Value::Number(n) => {
78                let int64 = n
79                    .as_i64()
80                    .ok_or_else(|| DecodeError::InvalidInteger(value.to_string()))?;
81
82                Ok(int64.try_into().map_err(|_| {
83                    DecodeError::IntegerOverflow(value.to_string(), std::any::type_name::<I>())
84                })?)
85            }
86            _ => Err(DecodeError::IncorrectType(
87                "Number".to_string(),
88                value.to_string(),
89            )),
90        }
91    }
92}
93
94pub fn unsigned_integer<'a, I: TryFrom<u64>>() -> Box<dyn Decoder<'a, I> + 'a>
95where
96    I: 'a,
97{
98    Box::new(UIntDecoder {
99        phantom: PhantomData,
100    })
101}
102
103pub struct UIntDecoder<I: TryFrom<u64>> {
104    phantom: PhantomData<I>,
105}
106
107impl<'a, I> Decoder<'a, I> for UIntDecoder<I>
108where
109    I: TryFrom<u64>,
110{
111    fn decode(&self, value: &serde_json::Value) -> Result<I, DecodeError> {
112        match value {
113            serde_json::Value::Number(n) => {
114                let uint64 = n
115                    .as_u64()
116                    .ok_or_else(|| DecodeError::InvalidInteger(value.to_string()))?;
117
118                Ok(uint64.try_into().map_err(|_| {
119                    DecodeError::IntegerOverflow(value.to_string(), std::any::type_name::<I>())
120                })?)
121            }
122            _ => Err(DecodeError::IncorrectType(
123                "Number".to_string(),
124                value.to_string(),
125            )),
126        }
127    }
128}
129
130pub fn float<F: From<f64>>() -> BoxDecoder<'static, F>
131where
132    F: 'static + Send + Sync,
133{
134    Box::new(FloatDecoder {
135        phantom: PhantomData,
136    })
137}
138
139pub struct FloatDecoder<I: From<f64>> {
140    phantom: PhantomData<I>,
141}
142
143// TODO: Probably don't need from - just force f64 etc.
144impl<'a, I> Decoder<'a, I> for FloatDecoder<I>
145where
146    I: From<f64>,
147{
148    fn decode(&self, value: &serde_json::Value) -> Result<I, DecodeError> {
149        match value {
150            serde_json::Value::Number(n) => n
151                .as_f64()
152                .map(Into::into)
153                .ok_or_else(|| DecodeError::InvalidInteger(value.to_string())),
154            _ => Err(DecodeError::IncorrectType(
155                "Number".to_string(),
156                value.to_string(),
157            )),
158        }
159    }
160}
161
162pub fn boolean() -> BoxDecoder<'static, bool> {
163    Box::new(BooleanDecoder {})
164}
165
166pub struct BooleanDecoder {}
167
168impl<'a> Decoder<'a, bool> for BooleanDecoder {
169    fn decode(&self, value: &serde_json::Value) -> Result<bool, DecodeError> {
170        match value {
171            serde_json::Value::Bool(b) => Ok(*b),
172            _ => Err(DecodeError::IncorrectType(
173                "Boolean".to_string(),
174                value.to_string(),
175            )),
176        }
177    }
178}
179
180pub fn option<'a, DecodesTo>(
181    decoder: BoxDecoder<'a, DecodesTo>,
182) -> BoxDecoder<'a, Option<DecodesTo>>
183where
184    DecodesTo: 'a + Send + Sync,
185{
186    Box::new(OptionDecoder {
187        inner_decoder: decoder,
188    })
189}
190
191pub struct OptionDecoder<'a, DecodesTo> {
192    inner_decoder: BoxDecoder<'a, DecodesTo>,
193}
194
195impl<'a, DecodesTo> Decoder<'a, Option<DecodesTo>> for OptionDecoder<'a, DecodesTo>
196where
197    DecodesTo: 'a,
198{
199    fn decode(&self, value: &serde_json::Value) -> Result<Option<DecodesTo>, DecodeError> {
200        match value {
201            serde_json::Value::Null => Ok(None),
202            _ => self.inner_decoder.decode(value).map(Some),
203        }
204    }
205}
206
207// TODO: Difficulties using this due to type inference problems
208// look to re-work the interface somehow
209pub fn list<'a, Item, Collection>(decoder: BoxDecoder<'a, Item>) -> BoxDecoder<'a, Collection>
210where
211    Collection: FromIterator<Item> + 'a + Send + Sync,
212    Item: 'a,
213{
214    Box::new(ListDecoder {
215        inner_decoder: decoder,
216        phantom: PhantomData,
217    })
218}
219
220pub struct ListDecoder<'a, Item, DecodesTo: FromIterator<Item>> {
221    phantom: PhantomData<DecodesTo>,
222    inner_decoder: BoxDecoder<'a, Item>,
223}
224
225impl<'a, Item, DecodesTo> Decoder<'a, DecodesTo> for ListDecoder<'a, Item, DecodesTo>
226where
227    DecodesTo: FromIterator<Item>,
228{
229    fn decode(&self, value: &serde_json::Value) -> Result<DecodesTo, DecodeError> {
230        match value {
231            serde_json::Value::Array(vec) => vec
232                .iter()
233                .map(|item| (*self.inner_decoder).decode(item))
234                .collect(),
235            _ => Err(DecodeError::IncorrectType(
236                "Array".to_string(),
237                value.to_string(),
238            )),
239        }
240    }
241}
242
243// TODO: Do we need the lifetimes here
244pub fn map<'a, F, T1, NewDecodesTo>(func: F, d1: BoxDecoder<'a, T1>) -> BoxDecoder<'a, NewDecodesTo>
245where
246    F: (Fn(T1) -> NewDecodesTo) + 'a + Send + Sync,
247    NewDecodesTo: 'a,
248    T1: 'a,
249{
250    Box::new(DecoderFn1 {
251        func: Box::new(func),
252        decoder: d1,
253    })
254}
255
256pub struct DecoderFn1<'a, DecodesTo, Argument1> {
257    func: Box<dyn Fn(Argument1) -> DecodesTo + 'a + Send + Sync>,
258    decoder: BoxDecoder<'a, Argument1>,
259}
260
261impl<'a, DecodesTo, Argument1> Decoder<'a, DecodesTo> for DecoderFn1<'a, DecodesTo, Argument1> {
262    fn decode(&self, value: &serde_json::Value) -> Result<DecodesTo, DecodeError> {
263        let arg0 = self.decoder.decode(value)?;
264        Ok((*self.func)(arg0))
265    }
266}
267
268pub fn serde<T>() -> BoxDecoder<'static, T>
269where
270    for<'de> T: serde::Deserialize<'de> + 'static + Send + Sync,
271{
272    Box::new(SerdeDecoder {
273        phantom: PhantomData,
274    })
275}
276
277pub struct SerdeDecoder<T> {
278    phantom: PhantomData<T>,
279}
280
281impl<'a, DecodesTo> Decoder<'a, DecodesTo> for SerdeDecoder<DecodesTo>
282where
283    for<'de> DecodesTo: serde::Deserialize<'de>,
284{
285    fn decode(&self, value: &serde_json::Value) -> Result<DecodesTo, DecodeError> {
286        // TODO: Figure out if we can get rid of this clone somehow?
287        serde_json::from_value(value.clone()).map_err(|e| DecodeError::SerdeError(e.to_string()))
288    }
289}
290
291pub fn json() -> BoxDecoder<'static, serde_json::Value> {
292    Box::new(JsonDecoder {})
293}
294
295pub struct JsonDecoder {}
296
297impl<'a> Decoder<'a, serde_json::Value> for JsonDecoder {
298    fn decode(&self, value: &serde_json::Value) -> Result<serde_json::Value, DecodeError> {
299        // TODO: Figure out if we can get rid of this clone somehow?
300        Ok(value.clone())
301    }
302}
303
304pub fn succeed<'a, V>(value: V) -> BoxDecoder<'a, V>
305where
306    V: Clone + Send + Sync + 'a,
307{
308    Box::new(SucceedDecoder { value })
309}
310
311pub struct SucceedDecoder<V> {
312    value: V,
313}
314
315impl<'a, V> Decoder<'a, V> for SucceedDecoder<V>
316where
317    V: Clone + Send + Sync + 'a,
318{
319    fn decode(&self, _value: &serde_json::Value) -> Result<V, DecodeError> {
320        // Be nice to figure out a way to avoid this clone...
321        Ok(self.value.clone())
322    }
323}
324
325pub fn fail<V>(error: impl Into<String>) -> BoxDecoder<'static, V> {
326    // TODO: Might be nice to get this using a std::Error but it was
327    // surprisingly tricky.  For now just using a String instead.
328    Box::new(FailDecoder {
329        error: error.into(),
330    })
331}
332
333pub struct FailDecoder {
334    error: String,
335}
336
337impl<'a, V> Decoder<'a, V> for FailDecoder {
338    fn decode(&self, _value: &serde_json::Value) -> Result<V, DecodeError> {
339        // Be nice to figure out a way to avoid this clone...
340        Err(DecodeError::Other(self.error.clone()))
341    }
342}
343
344pub fn and_then<'a, F, T, NewDecodesTo>(
345    func: F,
346    d: BoxDecoder<'a, T>,
347) -> BoxDecoder<'a, NewDecodesTo>
348where
349    F: (Fn(T) -> BoxDecoder<'a, NewDecodesTo>) + 'a + Send + Sync,
350    NewDecodesTo: 'a,
351    T: 'a,
352{
353    Box::new(DecoderAndThen {
354        func: Box::new(func),
355        decoder: d,
356    })
357}
358
359pub struct DecoderAndThen<'a, DecodesTo, Argument> {
360    func: Box<dyn Fn(Argument) -> BoxDecoder<'a, DecodesTo> + 'a + Send + Sync>,
361    decoder: BoxDecoder<'a, Argument>,
362}
363
364impl<'a, DecodesTo, Argument> Decoder<'a, DecodesTo> for DecoderAndThen<'a, DecodesTo, Argument> {
365    fn decode(&self, value: &serde_json::Value) -> Result<DecodesTo, DecodeError> {
366        let func_param = self.decoder.decode(value)?;
367        let inner_decoder = (*self.func)(func_param);
368        let res = inner_decoder.decode(value)?;
369        Ok(res)
370    }
371}