cynic_parser/values/
value.rs

1use crate::{common::IdRange, AstLookup, Span};
2
3use super::{
4    const_value::ConstValue,
5    enums::EnumValue,
6    ids::{FieldId, StringId},
7    iter::{Iter, ValueStoreReader},
8    lists::List,
9    objects::Object,
10    scalars::{BooleanValue, FloatValue, IntValue, NullValue, StringValue},
11    variables::VariableValue,
12    Cursor, ObjectField, ValueId,
13};
14
15#[derive(Debug, Clone, Copy)]
16pub enum Value<'a> {
17    Variable(VariableValue<'a>),
18    Int(IntValue<'a>),
19    Float(FloatValue<'a>),
20    String(StringValue<'a>),
21    Boolean(BooleanValue<'a>),
22    Null(NullValue<'a>),
23    Enum(EnumValue<'a>),
24    List(List<'a>),
25    Object(Object<'a>),
26}
27
28impl<'a> Value<'a> {
29    pub fn span(&self) -> Span {
30        match self {
31            Value::Variable(inner) => inner.span(),
32            Value::Int(inner) => inner.span(),
33            Value::Float(inner) => inner.span(),
34            Value::String(inner) => inner.span(),
35            Value::Boolean(inner) => inner.span(),
36            Value::Null(inner) => inner.span(),
37            Value::Enum(inner) => inner.span(),
38            Value::List(inner) => inner.span(),
39            Value::Object(inner) => inner.span(),
40        }
41    }
42
43    /// Returns an iterator over all the variables that appear somewhere in this Value.
44    ///
45    /// Note that this is not deduplicated - if a variable appears more than once in
46    /// the value it'll appear more than once in this iterator.
47    pub fn variables_used(&self) -> impl Iterator<Item = &'a str> + '_ {
48        VariableIterator {
49            value_stack: vec![*self],
50        }
51    }
52}
53
54impl<'a> Value<'a> {
55    pub fn is_variable(&self) -> bool {
56        matches!(self, Value::Variable(_))
57    }
58
59    pub fn as_variable(&self) -> Option<&'a str> {
60        match self {
61            Self::Variable(inner) => Some(inner.name()),
62            _ => None,
63        }
64    }
65
66    pub fn is_int(&self) -> bool {
67        matches!(self, Value::Int(_))
68    }
69
70    pub fn as_i32(&self) -> Option<i32> {
71        match self {
72            Self::Int(inner) => Some(inner.as_i32()),
73            _ => None,
74        }
75    }
76
77    pub fn is_float(&self) -> bool {
78        matches!(self, Value::Float(_))
79    }
80
81    pub fn as_f64(&self) -> Option<f64> {
82        match self {
83            Self::Float(inner) => Some(inner.value()),
84            _ => None,
85        }
86    }
87
88    pub fn is_string(&self) -> bool {
89        matches!(self, Value::String(_))
90    }
91
92    pub fn as_str(&self) -> Option<&'a str> {
93        match self {
94            Self::String(inner) => Some(inner.value()),
95            _ => None,
96        }
97    }
98
99    pub fn is_boolean(&self) -> bool {
100        matches!(self, Value::Boolean(_))
101    }
102
103    pub fn as_bool(&self) -> Option<bool> {
104        match self {
105            Value::Boolean(boolean_value) => Some(boolean_value.value()),
106            _ => None,
107        }
108    }
109
110    pub fn is_null(&self) -> bool {
111        matches!(self, Value::Null(_))
112    }
113
114    pub fn as_null(&self) -> Option<()> {
115        match self {
116            Value::Null(_) => Some(()),
117            _ => None,
118        }
119    }
120
121    pub fn is_enum(&self) -> bool {
122        matches!(self, Value::Enum(_))
123    }
124
125    pub fn as_enum_value(&self) -> Option<&'a str> {
126        match self {
127            Value::Enum(value) => Some(value.name()),
128            _ => None,
129        }
130    }
131
132    pub fn is_list(&self) -> bool {
133        matches!(self, Value::List(_))
134    }
135
136    pub fn as_list(&self) -> Option<List<'a>> {
137        match self {
138            Self::List(inner) => Some(*inner),
139            _ => None,
140        }
141    }
142
143    pub fn as_items(&self) -> Option<Iter<'a, Value<'a>>> {
144        match self {
145            Self::List(inner) => Some(inner.items()),
146            _ => None,
147        }
148    }
149
150    pub fn is_object(&self) -> bool {
151        matches!(self, Value::Object(_))
152    }
153
154    pub fn as_object(&self) -> Option<Object<'a>> {
155        match self {
156            Self::Object(inner) => Some(*inner),
157            _ => None,
158        }
159    }
160
161    pub fn as_fields(&self) -> Option<Iter<'a, ObjectField<'a>>> {
162        match self {
163            Self::Object(inner) => Some(inner.fields()),
164            _ => None,
165        }
166    }
167}
168
169impl PartialEq for Value<'_> {
170    fn eq(&self, other: &Self) -> bool {
171        match (self, other) {
172            (Value::Int(a), Value::Int(b)) => a == b,
173            (Value::Variable(a), Value::Variable(b)) => a == b,
174            (Value::Float(a), Value::Float(b)) => a == b,
175            (Value::String(a), Value::String(b)) => a == b,
176            (Value::Boolean(a), Value::Boolean(b)) => a == b,
177            (Value::Null(_), Value::Null(_)) => true,
178            (Value::Enum(a), Value::Enum(b)) => a == b,
179            (Value::List(a), Value::List(b)) => a == b,
180            (Value::Object(a), Value::Object(b)) => a == b,
181            _ => false,
182        }
183    }
184}
185
186impl<'a> ValueStoreReader<'a> for Value<'a> {
187    type Id = ValueId;
188}
189
190impl super::ValueStoreId for ValueId {
191    type Reader<'a> = Value<'a>;
192
193    fn read(self, store: &super::ValueStore) -> Self::Reader<'_> {
194        let cursor = Cursor { id: self, store };
195
196        match store.lookup(self).kind {
197            ValueKind::Variable(_) => Value::Variable(VariableValue(cursor)),
198            ValueKind::Int(_) => Value::Int(IntValue(cursor)),
199            ValueKind::Float(_) => Value::Float(FloatValue(cursor)),
200            ValueKind::String(_) => Value::String(StringValue(cursor)),
201            ValueKind::Boolean(_) => Value::Boolean(BooleanValue(cursor)),
202            ValueKind::Null => Value::Null(NullValue(cursor)),
203            ValueKind::Enum(_) => Value::Enum(EnumValue(cursor)),
204            ValueKind::List(_) => Value::List(List(cursor)),
205            ValueKind::Object(_) => Value::Object(Object(cursor)),
206        }
207    }
208}
209
210pub struct ValueRecord {
211    pub span: Span,
212    pub kind: ValueKind,
213}
214
215pub enum ValueKind {
216    Variable(StringId),
217    Int(i64),
218    Float(f64),
219    String(StringId),
220    Boolean(bool),
221    Null,
222    Enum(StringId),
223    List(IdRange<ValueId>),
224    Object(IdRange<FieldId>),
225}
226
227impl ValueKind {
228    pub fn as_variable(&self) -> Option<StringId> {
229        match self {
230            ValueKind::Variable(string_id) => Some(*string_id),
231            _ => None,
232        }
233    }
234
235    pub fn as_int(&self) -> Option<i64> {
236        match self {
237            ValueKind::Int(int) => Some(*int),
238            _ => None,
239        }
240    }
241
242    pub fn as_float(&self) -> Option<f64> {
243        match self {
244            ValueKind::Float(inner) => Some(*inner),
245            _ => None,
246        }
247    }
248
249    pub fn as_string(&self) -> Option<StringId> {
250        match self {
251            ValueKind::String(inner) => Some(*inner),
252            _ => None,
253        }
254    }
255
256    pub fn as_boolean(&self) -> Option<bool> {
257        match self {
258            ValueKind::Boolean(inner) => Some(*inner),
259            _ => None,
260        }
261    }
262
263    pub fn as_null(&self) -> Option<()> {
264        match self {
265            ValueKind::Null => Some(()),
266            _ => None,
267        }
268    }
269
270    pub fn as_enum_value(&self) -> Option<StringId> {
271        match self {
272            ValueKind::Enum(inner) => Some(*inner),
273            _ => None,
274        }
275    }
276
277    pub fn as_list(&self) -> Option<IdRange<ValueId>> {
278        match self {
279            ValueKind::List(inner) => Some(*inner),
280            _ => None,
281        }
282    }
283
284    pub fn as_object(&self) -> Option<IdRange<FieldId>> {
285        match self {
286            ValueKind::Object(inner) => Some(*inner),
287            _ => None,
288        }
289    }
290}
291
292pub struct VariableIterator<'a> {
293    value_stack: Vec<Value<'a>>,
294}
295
296impl<'a> Iterator for VariableIterator<'a> {
297    type Item = &'a str;
298
299    fn next(&mut self) -> Option<Self::Item> {
300        while let Some(value) = self.value_stack.pop() {
301            match value {
302                Value::Object(fields) => self
303                    .value_stack
304                    .extend(fields.fields().map(|field| field.value())),
305                Value::List(values) => self.value_stack.extend(values.items()),
306                Value::Variable(variable) => return Some(variable.name()),
307                _ => {}
308            }
309        }
310        None
311    }
312}
313
314impl<'a> From<ConstValue<'a>> for Value<'a> {
315    fn from(value: ConstValue<'a>) -> Self {
316        match value {
317            ConstValue::Int(inner) => Value::Int(inner),
318            ConstValue::Float(inner) => Value::Float(inner),
319            ConstValue::String(inner) => Value::String(inner),
320            ConstValue::Boolean(inner) => Value::Boolean(inner),
321            ConstValue::Null(inner) => Value::Null(inner),
322            ConstValue::Enum(inner) => Value::Enum(inner),
323            ConstValue::List(inner) => Value::List(inner.into()),
324            ConstValue::Object(inner) => Value::Object(inner.into()),
325        }
326    }
327}
328
329#[cfg(test)]
330mod tests {
331    use super::ValueRecord;
332
333    #[test]
334    fn test_size_of_record() {
335        assert_eq!(std::mem::size_of::<ValueRecord>(), 32);
336    }
337}