juniper_puff/integrations/
serde.rs

1use std::{fmt, marker::PhantomData};
2
3use indexmap::IndexMap;
4use serde::{
5    de::{self, Deserializer, IntoDeserializer as _},
6    ser::{SerializeMap as _, Serializer},
7    serde_if_integer128, Deserialize, Serialize,
8};
9
10use crate::{
11    ast::InputValue,
12    executor::ExecutionError,
13    parser::{ParseError, SourcePosition, Spanning},
14    validation::RuleError,
15    DefaultScalarValue, GraphQLError, Object, Value,
16};
17
18impl<T: Serialize> Serialize for ExecutionError<T> {
19    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
20        let mut map = ser.serialize_map(Some(4))?;
21
22        map.serialize_key("message")?;
23        map.serialize_value(self.error().message())?;
24
25        let locations = vec![self.location()];
26        map.serialize_key("locations")?;
27        map.serialize_value(&locations)?;
28
29        map.serialize_key("path")?;
30        map.serialize_value(self.path())?;
31
32        if !self.error().extensions().is_null() {
33            map.serialize_key("extensions")?;
34            map.serialize_value(self.error().extensions())?;
35        }
36
37        map.end()
38    }
39}
40
41impl Serialize for GraphQLError {
42    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
43        #[derive(Serialize)]
44        struct Helper {
45            message: &'static str,
46        }
47
48        match self {
49            Self::ParseError(e) => [e].serialize(ser),
50            Self::ValidationError(es) => es.serialize(ser),
51            Self::NoOperationProvided => [Helper {
52                message: "Must provide an operation",
53            }]
54            .serialize(ser),
55            Self::MultipleOperationsProvided => [Helper {
56                message: "Must provide operation name \
57                          if query contains multiple operations",
58            }]
59            .serialize(ser),
60            Self::UnknownOperationName => [Helper {
61                message: "Unknown operation",
62            }]
63            .serialize(ser),
64            Self::IsSubscription => [Helper {
65                message: "Expected query, got subscription",
66            }]
67            .serialize(ser),
68            Self::NotSubscription => [Helper {
69                message: "Expected subscription, got query",
70            }]
71            .serialize(ser),
72        }
73    }
74}
75
76impl<'de, S: Deserialize<'de>> Deserialize<'de> for InputValue<S> {
77    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
78        struct Visitor<S: ?Sized>(PhantomData<S>);
79
80        impl<'de, S: Deserialize<'de>> de::Visitor<'de> for Visitor<S> {
81            type Value = InputValue<S>;
82
83            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84                f.write_str("a valid input value")
85            }
86
87            fn visit_bool<E: de::Error>(self, b: bool) -> Result<Self::Value, E> {
88                S::deserialize(b.into_deserializer()).map(InputValue::Scalar)
89            }
90
91            fn visit_i8<E: de::Error>(self, n: i8) -> Result<Self::Value, E> {
92                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
93            }
94
95            fn visit_i16<E: de::Error>(self, n: i16) -> Result<Self::Value, E> {
96                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
97            }
98
99            fn visit_i32<E: de::Error>(self, n: i32) -> Result<Self::Value, E> {
100                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
101            }
102
103            fn visit_i64<E: de::Error>(self, n: i64) -> Result<Self::Value, E> {
104                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
105            }
106
107            serde_if_integer128! {
108                fn visit_i128<E: de::Error>(self, n: i128) ->  Result<Self::Value, E> {
109                    S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
110                }
111            }
112
113            fn visit_u8<E: de::Error>(self, n: u8) -> Result<Self::Value, E> {
114                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
115            }
116
117            fn visit_u16<E: de::Error>(self, n: u16) -> Result<Self::Value, E> {
118                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
119            }
120
121            fn visit_u32<E: de::Error>(self, n: u32) -> Result<Self::Value, E> {
122                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
123            }
124
125            fn visit_u64<E: de::Error>(self, n: u64) -> Result<Self::Value, E> {
126                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
127            }
128
129            serde_if_integer128! {
130                fn visit_u128<E: de::Error>(self, n: u128) ->  Result<Self::Value, E> {
131                    S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
132                }
133            }
134
135            fn visit_f32<E: de::Error>(self, n: f32) -> Result<Self::Value, E> {
136                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
137            }
138
139            fn visit_f64<E: de::Error>(self, n: f64) -> Result<Self::Value, E> {
140                S::deserialize(n.into_deserializer()).map(InputValue::Scalar)
141            }
142
143            fn visit_char<E: de::Error>(self, c: char) -> Result<Self::Value, E> {
144                S::deserialize(c.into_deserializer()).map(InputValue::Scalar)
145            }
146
147            fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
148                S::deserialize(s.into_deserializer()).map(InputValue::Scalar)
149            }
150
151            fn visit_string<E: de::Error>(self, s: String) -> Result<Self::Value, E> {
152                S::deserialize(s.into_deserializer()).map(InputValue::Scalar)
153            }
154
155            fn visit_bytes<E: de::Error>(self, b: &[u8]) -> Result<Self::Value, E> {
156                S::deserialize(b.into_deserializer()).map(InputValue::Scalar)
157            }
158
159            fn visit_byte_buf<E: de::Error>(self, b: Vec<u8>) -> Result<Self::Value, E> {
160                S::deserialize(b.into_deserializer()).map(InputValue::Scalar)
161            }
162
163            fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
164                Ok(InputValue::Null)
165            }
166
167            fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
168                Ok(InputValue::Null)
169            }
170
171            fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
172            where
173                V: de::SeqAccess<'de>,
174            {
175                let mut vals = Vec::new();
176                while let Some(v) = visitor.next_element()? {
177                    vals.push(v);
178                }
179                Ok(InputValue::list(vals))
180            }
181
182            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
183            where
184                V: de::MapAccess<'de>,
185            {
186                let mut obj = IndexMap::<String, InputValue<S>>::with_capacity(
187                    visitor.size_hint().unwrap_or(0),
188                );
189                while let Some((key, val)) = visitor.next_entry()? {
190                    obj.insert(key, val);
191                }
192                Ok(InputValue::object(obj))
193            }
194        }
195
196        de.deserialize_any(Visitor(PhantomData))
197    }
198}
199
200impl<T: Serialize> Serialize for InputValue<T> {
201    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
202        match self {
203            Self::Null | Self::Variable(_) => ser.serialize_unit(),
204            Self::Scalar(s) => s.serialize(ser),
205            Self::Enum(e) => ser.serialize_str(e),
206            Self::List(l) => l.iter().map(|x| &x.item).collect::<Vec<_>>().serialize(ser),
207            Self::Object(o) => o
208                .iter()
209                .map(|(k, v)| (k.item.as_str(), &v.item))
210                .collect::<IndexMap<_, _>>()
211                .serialize(ser),
212        }
213    }
214}
215
216impl Serialize for RuleError {
217    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
218        let mut map = ser.serialize_map(Some(2))?;
219
220        map.serialize_key("message")?;
221        map.serialize_value(self.message())?;
222
223        map.serialize_key("locations")?;
224        map.serialize_value(self.locations())?;
225
226        map.end()
227    }
228}
229
230impl Serialize for SourcePosition {
231    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
232        let mut map = ser.serialize_map(Some(2))?;
233
234        let line = self.line() + 1;
235        map.serialize_key("line")?;
236        map.serialize_value(&line)?;
237
238        let column = self.column() + 1;
239        map.serialize_key("column")?;
240        map.serialize_value(&column)?;
241
242        map.end()
243    }
244}
245
246impl Serialize for Spanning<ParseError> {
247    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
248        let mut map = ser.serialize_map(Some(2))?;
249
250        let msg = self.item.to_string();
251        map.serialize_key("message")?;
252        map.serialize_value(&msg)?;
253
254        let mut loc = IndexMap::new();
255        loc.insert("line".to_owned(), self.start.line() + 1);
256        loc.insert("column".to_owned(), self.start.column() + 1);
257
258        let locations = vec![loc];
259        map.serialize_key("locations")?;
260        map.serialize_value(&locations)?;
261
262        map.end()
263    }
264}
265
266impl<T: Serialize> Serialize for Object<T> {
267    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
268        let mut map = ser.serialize_map(Some(self.field_count()))?;
269        for (f, v) in self.iter() {
270            map.serialize_key(f)?;
271            map.serialize_value(v)?;
272        }
273        map.end()
274    }
275}
276
277impl<T: Serialize> Serialize for Value<T> {
278    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
279        match self {
280            Self::Null => ser.serialize_unit(),
281            Self::Scalar(s) => s.serialize(ser),
282            Self::List(l) => l.serialize(ser),
283            Self::Object(o) => o.serialize(ser),
284        }
285    }
286}
287
288impl<'de> Deserialize<'de> for DefaultScalarValue {
289    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
290        struct Visitor;
291
292        impl<'de> de::Visitor<'de> for Visitor {
293            type Value = DefaultScalarValue;
294
295            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
296                f.write_str("a valid input value")
297            }
298
299            fn visit_bool<E: de::Error>(self, b: bool) -> Result<Self::Value, E> {
300                Ok(DefaultScalarValue::Boolean(b))
301            }
302
303            fn visit_i64<E: de::Error>(self, n: i64) -> Result<Self::Value, E> {
304                if n >= i64::from(i32::MIN) && n <= i64::from(i32::MAX) {
305                    Ok(DefaultScalarValue::Int(n.try_into().unwrap()))
306                } else {
307                    // Browser's `JSON.stringify()` serializes all numbers
308                    // having no fractional part as integers (no decimal point),
309                    // so we must parse large integers as floating point,
310                    // otherwise we would error on transferring large floating
311                    // point numbers.
312                    // TODO: Use `FloatToInt` conversion once stabilized:
313                    //       https://github.com/rust-lang/rust/issues/67057
314                    Ok(DefaultScalarValue::Float(n as f64))
315                }
316            }
317
318            fn visit_u64<E: de::Error>(self, n: u64) -> Result<Self::Value, E> {
319                if n <= u64::try_from(i32::MAX).unwrap() {
320                    self.visit_i64(n.try_into().unwrap())
321                } else {
322                    // Browser's `JSON.stringify()` serializes all numbers
323                    // having no fractional part as integers (no decimal point),
324                    // so we must parse large integers as floating point,
325                    // otherwise we would error on transferring large floating
326                    // point numbers.
327                    // TODO: Use `FloatToInt` conversion once stabilized:
328                    //       https://github.com/rust-lang/rust/issues/67057
329                    Ok(DefaultScalarValue::Float(n as f64))
330                }
331            }
332
333            fn visit_f64<E: de::Error>(self, f: f64) -> Result<Self::Value, E> {
334                Ok(DefaultScalarValue::Float(f))
335            }
336
337            fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
338                self.visit_string(s.into())
339            }
340
341            fn visit_string<E: de::Error>(self, s: String) -> Result<Self::Value, E> {
342                Ok(DefaultScalarValue::String(s))
343            }
344        }
345
346        de.deserialize_any(Visitor)
347    }
348}
349
350#[cfg(test)]
351mod tests {
352    use serde_json::{from_str, to_string};
353
354    use crate::{
355        ast::InputValue,
356        graphql_input_value,
357        value::{DefaultScalarValue, Object},
358        FieldError, Value,
359    };
360
361    use super::{ExecutionError, GraphQLError};
362
363    #[test]
364    fn int() {
365        assert_eq!(
366            from_str::<InputValue>("1235").unwrap(),
367            graphql_input_value!(1235),
368        );
369    }
370
371    #[test]
372    fn float() {
373        assert_eq!(
374            from_str::<InputValue>("2.0").unwrap(),
375            graphql_input_value!(2.0),
376        );
377        // large value without a decimal part is also float
378        assert_eq!(
379            from_str::<InputValue>("123567890123").unwrap(),
380            graphql_input_value!(123_567_890_123.0),
381        );
382    }
383
384    #[test]
385    fn errors() {
386        assert_eq!(
387            to_string(&GraphQLError::UnknownOperationName).unwrap(),
388            r#"[{"message":"Unknown operation"}]"#,
389        );
390    }
391
392    #[test]
393    fn error_extensions() {
394        let mut obj: Object<DefaultScalarValue> = Object::with_capacity(1);
395        obj.add_field("foo", Value::scalar("bar"));
396        assert_eq!(
397            to_string(&ExecutionError::at_origin(FieldError::new(
398                "foo error",
399                Value::Object(obj),
400            )))
401            .unwrap(),
402            r#"{"message":"foo error","locations":[{"line":1,"column":1}],"path":[],"extensions":{"foo":"bar"}}"#,
403        );
404    }
405}