async_graphql/dynamic/
value_accessor.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
use std::borrow::Cow;

use indexmap::IndexMap;
use serde::de::DeserializeOwned;

use crate::{Error, Name, Result, Upload, Value};

/// A value accessor
pub struct ValueAccessor<'a>(&'a Value);

impl<'a> ValueAccessor<'a> {
    /// Returns `true` if the value is null, otherwise returns `false`
    #[inline]
    pub fn is_null(&self) -> bool {
        matches!(self.0, Value::Null)
    }

    /// Returns the boolean
    pub fn boolean(&self) -> Result<bool> {
        match self.0 {
            Value::Boolean(b) => Ok(*b),
            _ => Err(Error::new("internal: not a boolean")),
        }
    }

    /// Returns the enum name
    pub fn enum_name(&self) -> Result<&str> {
        match self.0 {
            Value::Enum(s) => Ok(s),
            Value::String(s) => Ok(s.as_str()),
            _ => Err(Error::new("internal: not an enum name")),
        }
    }

    /// Returns the number as `i64`
    pub fn i64(&self) -> Result<i64> {
        if let Value::Number(number) = self.0 {
            if let Some(value) = number.as_i64() {
                return Ok(value);
            }
        }
        Err(Error::new("internal: not an signed integer"))
    }

    /// Returns the number as `u64`
    pub fn u64(&self) -> Result<u64> {
        if let Value::Number(number) = self.0 {
            if let Some(value) = number.as_u64() {
                return Ok(value);
            }
        }
        Err(Error::new("internal: not an unsigned integer"))
    }

    /// Returns the number as `f32`
    pub fn f32(&self) -> Result<f32> {
        if let Value::Number(number) = self.0 {
            if let Some(value) = number.as_f64() {
                return Ok(value as f32);
            }
        }
        Err(Error::new("internal: not a float"))
    }

    /// Returns the number as `f64`
    pub fn f64(&self) -> Result<f64> {
        if let Value::Number(number) = self.0 {
            if let Some(value) = number.as_f64() {
                return Ok(value);
            }
        }
        Err(Error::new("internal: not a float"))
    }

    /// Returns the string value
    pub fn string(&self) -> Result<&'a str> {
        if let Value::String(value) = self.0 {
            Ok(value)
        } else {
            Err(Error::new("internal: not a string"))
        }
    }

    /// Returns the object accessor
    pub fn object(&self) -> Result<ObjectAccessor<'a>> {
        if let Value::Object(obj) = self.0 {
            Ok(ObjectAccessor(Cow::Borrowed(obj)))
        } else {
            Err(Error::new("internal: not an object"))
        }
    }

    /// Returns the list accessor
    pub fn list(&self) -> Result<ListAccessor<'a>> {
        if let Value::List(list) = self.0 {
            Ok(ListAccessor(list))
        } else {
            Err(Error::new("internal: not a list"))
        }
    }

    /// Deserialize the value to `T`
    pub fn deserialize<T: DeserializeOwned>(&self) -> Result<T> {
        T::deserialize(self.0.clone()).map_err(|err| format!("internal: {}", err).into())
    }

    /// Returns a reference to the underlying `Value`
    #[inline]
    pub fn as_value(&self) -> &'a Value {
        self.0
    }

    /// Returns a upload object
    pub fn upload(&self) -> Result<Upload> {
        <Upload as crate::InputType>::parse(Some(self.0.clone()))
            .map_err(|_| Error::new("internal: not a upload"))
    }
}

/// A object accessor
pub struct ObjectAccessor<'a>(pub(crate) Cow<'a, IndexMap<Name, Value>>);

impl<'a> ObjectAccessor<'a> {
    /// Return a reference to the value stored for `key`, if it is present,
    /// else `None`.
    #[inline]
    pub fn get(&self, name: &str) -> Option<ValueAccessor<'_>> {
        self.0.get(name).map(ValueAccessor)
    }

    /// Like [`ObjectAccessor::get`], returns `Err` if the index does not exist
    #[inline]
    pub fn try_get(&self, name: &str) -> Result<ValueAccessor<'_>> {
        self.0
            .get(name)
            .map(ValueAccessor)
            .ok_or_else(|| Error::new(format!("internal: key \"{}\" not found", name)))
    }

    /// Return an iterator over the key-value pairs of the object, in their
    /// order
    #[inline]
    pub fn iter(&self) -> impl Iterator<Item = (&Name, ValueAccessor<'_>)> + '_ {
        self.0
            .iter()
            .map(|(name, value)| (name, ValueAccessor(value)))
    }

    /// Return an iterator over the keys of the object, in their order
    #[inline]
    pub fn keys(&self) -> impl Iterator<Item = &Name> + '_ {
        self.0.keys()
    }

    /// Return an iterator over the values of the object, in their order
    #[inline]
    pub fn values(&self) -> impl Iterator<Item = ValueAccessor<'_>> + '_ {
        self.0.values().map(ValueAccessor)
    }

    /// Returns the number of elements in the object
    #[inline]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns `true` if the object has no members
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a reference to the underlying IndexMap
    #[inline]
    pub fn as_index_map(&'a self) -> &'a IndexMap<Name, Value> {
        &self.0
    }
}

/// A list accessor
pub struct ListAccessor<'a>(pub(crate) &'a [Value]);

impl<'a> ListAccessor<'a> {
    /// Returns the number of elements in the list
    #[inline]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns `true` if the list has a length of 0
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Returns an iterator over the list
    #[inline]
    pub fn iter(&self) -> impl Iterator<Item = ValueAccessor<'_>> + '_ {
        self.0.iter().map(ValueAccessor)
    }

    /// Returns a reference to an element depending on the index
    #[inline]
    pub fn get(&self, idx: usize) -> Option<ValueAccessor<'_>> {
        self.0.get(idx).map(ValueAccessor)
    }

    /// Like [`ListAccessor::get`], returns `Err` if the index does not exist
    #[inline]
    pub fn try_get(&self, idx: usize) -> Result<ValueAccessor<'_>> {
        self.get(idx)
            .ok_or_else(|| Error::new(format!("internal: index \"{}\" not found", idx)))
    }

    /// Returns a new ListAccessor that represents a slice of the original
    #[inline]
    pub fn as_slice(&self, start: usize, end: usize) -> Result<ListAccessor<'a>> {
        if start <= end && end <= self.len() {
            Ok(ListAccessor(&self.0[start..end]))
        } else {
            Err(Error::new("internal: invalid slice indices"))
        }
    }

    /// Returns a reference to the underlying `&[Value]`
    #[inline]
    pub fn as_values_slice(&self) -> &'a [Value] {
        self.0
    }
}