cynic_parser_deser/
deserialize.rs

1use std::collections::HashMap;
2
3use crate::{value::ValueType, ConstDeserializer, DeserValue, Error};
4
5// ValueDeserialize vs DeserializeValue
6pub trait ValueDeserialize<'a>: Sized {
7    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error>;
8
9    /// Provides a default in the case where a field of this type is missing
10    fn default_when_missing() -> Option<Self> {
11        None
12    }
13}
14
15pub trait ValueDeserializeOwned: for<'a> ValueDeserialize<'a> {}
16impl<T> ValueDeserializeOwned for T where T: for<'a> ValueDeserialize<'a> {}
17
18impl<'a> ValueDeserialize<'a> for String {
19    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
20        match input {
21            DeserValue::String(string_value) => Ok(string_value.as_str().to_string()),
22            other => Err(Error::unexpected_type(ValueType::String, other)),
23        }
24    }
25}
26
27impl<'a> ValueDeserialize<'a> for &'a str {
28    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
29        match input {
30            DeserValue::String(string_value) => Ok(string_value.as_str()),
31            other => Err(Error::unexpected_type(ValueType::String, other)),
32        }
33    }
34}
35
36impl<'a> ValueDeserialize<'a> for i32 {
37    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
38        match input {
39            DeserValue::Int(inner) => Ok(inner.as_i32()),
40            other => Err(Error::unexpected_type(ValueType::Int, other)),
41        }
42    }
43}
44
45impl<'a> ValueDeserialize<'a> for i64 {
46    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
47        match input {
48            DeserValue::Int(inner) => Ok(inner.as_i64()),
49            other => Err(Error::unexpected_type(ValueType::Int, other)),
50        }
51    }
52}
53
54impl<'a> ValueDeserialize<'a> for u32 {
55    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
56        let value = i64::deserialize(input)?;
57
58        if value < 0 {
59            return Err(Error::custom(
60                format!("integer was less than zero: {value}"),
61                input.span(),
62            ));
63        }
64
65        value
66            .try_into()
67            .map_err(|_| Error::custom(format!("integer was too large: {value}"), input.span()))
68    }
69}
70
71impl<'a> ValueDeserialize<'a> for u64 {
72    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
73        let value = i64::deserialize(input)?;
74
75        if value < 0 {
76            return Err(Error::custom(
77                format!("integer was less than zero: {value}"),
78                input.span(),
79            ));
80        }
81
82        value
83            .try_into()
84            .map_err(|_| Error::custom(format!("integer was too large: {value}"), input.span()))
85    }
86}
87
88impl<'a> ValueDeserialize<'a> for usize {
89    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
90        let value = i64::deserialize(input)?;
91
92        if value < 0 {
93            return Err(Error::custom(
94                format!("integer was less than zero: {value}"),
95                input.span(),
96            ));
97        }
98
99        value
100            .try_into()
101            .map_err(|_| Error::custom(format!("integer was too large: {value}"), input.span()))
102    }
103}
104
105impl<'a> ValueDeserialize<'a> for f64 {
106    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
107        match input {
108            DeserValue::Float(inner) => Ok(inner.as_f64()),
109            other => Err(Error::unexpected_type(ValueType::Float, other)),
110        }
111    }
112}
113
114impl<'a> ValueDeserialize<'a> for bool {
115    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
116        match input {
117            DeserValue::Boolean(inner) => Ok(inner.as_bool()),
118            other => Err(Error::unexpected_type(ValueType::Boolean, other)),
119        }
120    }
121}
122
123impl<'a> ValueDeserialize<'a> for () {
124    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
125        match input {
126            DeserValue::Null(_) => Ok(()),
127            other => Err(Error::unexpected_type(ValueType::Null, other)),
128        }
129    }
130}
131
132impl<'a, T> ValueDeserialize<'a> for Option<T>
133where
134    T: ValueDeserialize<'a>,
135{
136    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
137        match input {
138            DeserValue::Null(_) => Ok(None),
139            other => T::deserialize(other).map(Some),
140        }
141    }
142
143    fn default_when_missing() -> Option<Self> {
144        Some(None)
145    }
146}
147
148impl<'a, T> ValueDeserialize<'a> for Vec<T>
149where
150    T: ValueDeserialize<'a>,
151{
152    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
153        match input {
154            DeserValue::List(list) => list.items().map(T::deserialize).collect(),
155            other => {
156                if !other.is_null() {
157                    // List coercion
158                    //
159                    // I am not 100% sure this is right but lets see...
160                    if let Ok(inner) = T::deserialize(other) {
161                        return Ok(vec![inner]);
162                    }
163                }
164                Err(Error::unexpected_type(ValueType::List, other))
165            }
166        }
167    }
168}
169
170impl<'a, T> ValueDeserialize<'a> for HashMap<String, T>
171where
172    T: ValueDeserialize<'a>,
173{
174    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
175        match input {
176            DeserValue::Object(object) => Ok(object
177                .fields()
178                .map(|field| Ok((field.name().to_string(), field.value().deserialize()?)))
179                .collect::<Result<HashMap<_, _>, _>>()?),
180            other => Err(Error::unexpected_type(ValueType::Object, other)),
181        }
182    }
183}
184
185impl<'a, T> ValueDeserialize<'a> for HashMap<&'a str, T>
186where
187    T: ValueDeserialize<'a>,
188{
189    fn deserialize(input: DeserValue<'a>) -> Result<Self, Error> {
190        match input {
191            DeserValue::Object(object) => Ok(object
192                .fields()
193                .map(|field| Ok((field.name(), field.value().deserialize()?)))
194                .collect::<Result<HashMap<_, _>, _>>()?),
195            other => Err(Error::unexpected_type(ValueType::Object, other)),
196        }
197    }
198}