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 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}