apollo_encoder/
value.rs

1use std::fmt;
2
3/// The Value type represents available values you could give as an input.
4///
5/// *Value*:
6///     Variable | IntValue | FloatValue | StringValue | BooleanValue |
7///     NullValue | EnumValue | ListValue | ObjectValue
8///
9/// Detailed documentation can be found in [GraphQL spec](https://spec.graphql.org/October2021/#Value).
10#[derive(Debug, PartialEq, Clone)]
11pub enum Value {
12    /// Name of a variable example: `varName`
13    Variable(String),
14    /// Int value example: `7`
15    Int(i32),
16    /// Float value example: `25.4`
17    Float(f64),
18    /// String value example: `"My string"`
19    String(String),
20    /// Boolean value example: `false`
21    Boolean(bool),
22    /// Null value example: `null`
23    Null,
24    /// Enum value example: `"VARIANT_EXAMPLE"`
25    Enum(String),
26    /// List value example: `[1, 2, 3]`
27    List(Vec<Value>),
28    /// Object value example: `{ first: 1, second: 2 }`
29    Object(Vec<(String, Value)>),
30}
31
32impl fmt::Display for Value {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match self {
35            Self::Variable(v) => write!(f, "${v}"),
36            Self::Int(i) => write!(f, "{i}"),
37            Self::Float(fl) => write!(f, "{fl}"),
38            Self::String(s) => {
39                if s.contains('"') | s.contains('\n') | s.contains('\r') {
40                    write!(f, r#""""{s}""""#)
41                } else {
42                    write!(f, r#""{s}""#)
43                }
44            }
45            Self::Boolean(b) => write!(f, "{b}"),
46            Self::Null => write!(f, "null"),
47            Self::Enum(val) => write!(f, "{val}"),
48            Self::List(list) => write!(
49                f,
50                "[{}]",
51                list.iter()
52                    .map(|elt| format!("{elt}"))
53                    .collect::<Vec<String>>()
54                    .join(", ")
55            ),
56            Self::Object(obj) => write!(
57                f,
58                "{{ {} }}",
59                obj.iter()
60                    .map(|(k, v)| format!("{}: {v}", String::from(k)))
61                    .collect::<Vec<String>>()
62                    .join(", ")
63            ),
64        }
65    }
66}
67
68macro_rules! to_number_value {
69    ($ty: path, $inner_type: path, $value_variant: ident) => {
70        impl From<$ty> for Value {
71            fn from(val: $ty) -> Self {
72                Self::$value_variant(val as $inner_type)
73            }
74        }
75    };
76    ($({$ty: path, $inner_type: path, $value_variant: ident}),+) => {
77        $(
78            to_number_value!($ty, $inner_type, $value_variant);
79        )+
80    };
81}
82
83// Numbers
84to_number_value!(
85    {i64, i32, Int},
86    {i32, i32, Int},
87    {i16, i32, Int},
88    {i8, i32, Int},
89    {isize, i32, Int},
90    {u64, i32, Int},
91    {u32, i32, Int},
92    {u16, i32, Int},
93    {u8, i32, Int},
94    {usize, i32, Int},
95    {f64, f64, Float},
96    {f32, f64, Float}
97);
98
99impl From<String> for Value {
100    fn from(val: String) -> Self {
101        Self::String(val)
102    }
103}
104
105impl From<&str> for Value {
106    fn from(val: &str) -> Self {
107        Self::String(val.to_string())
108    }
109}
110
111impl From<bool> for Value {
112    fn from(val: bool) -> Self {
113        Self::Boolean(val)
114    }
115}