1extern crate alloc;
16use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime};
17use core::fmt::{self, Debug, Display};
18use drasi_query_ast::ast::Expression as AstExpression;
19use duration::Duration;
20use float::Float;
21use index::Index;
22use integer::Integer;
23use serde_json::Value;
24use std::{
25 collections::BTreeMap,
26 hash::{Hash, Hasher},
27 sync::Arc,
28};
29use zoned_datetime::ZonedDateTime;
30use zoned_time::ZonedTime;
31
32use crate::models::{Element, ElementMetadata, ElementReference};
33
34#[allow(clippy::derived_hash_with_manual_eq)]
35#[derive(Clone, Hash, Eq, Default)]
36pub enum VariableValue {
37 #[default]
38 Null,
39 Bool(bool),
40 Float(Float),
41 Integer(Integer),
42 String(String),
43 List(Vec<VariableValue>),
44 Object(BTreeMap<String, VariableValue>), Date(NaiveDate), LocalTime(NaiveTime),
48 ZonedTime(ZonedTime),
49 LocalDateTime(NaiveDateTime), ZonedDateTime(ZonedDateTime),
51 Duration(Duration),
52 Expression(AstExpression),
53 ListRange(ListRange),
54 Element(Arc<Element>),
55 ElementMetadata(ElementMetadata),
56 ElementReference(ElementReference),
57 Awaiting,
58}
59
60impl From<VariableValue> for Value {
61 fn from(val: VariableValue) -> Self {
62 match val {
63 VariableValue::Null => Value::Null,
64 VariableValue::Bool(b) => Value::Bool(b),
65 VariableValue::Float(f) => Value::Number(f.into()),
66 VariableValue::Integer(i) => Value::Number(i.into()),
67 VariableValue::String(s) => Value::String(s),
68 VariableValue::List(l) => Value::Array(l.into_iter().map(|x| x.into()).collect()),
69 VariableValue::Object(o) => {
70 Value::Object(o.into_iter().map(|(k, v)| (k, v.into())).collect())
71 }
72 VariableValue::Date(d) => Value::String(d.to_string()),
73 VariableValue::LocalTime(t) => Value::String(t.to_string()),
74 VariableValue::ZonedTime(t) => Value::String(t.to_string()),
75 VariableValue::LocalDateTime(t) => Value::String(t.to_string()),
76 VariableValue::ZonedDateTime(t) => Value::String(t.to_string()),
77 VariableValue::Duration(d) => Value::String(d.to_string()),
78 VariableValue::Expression(e) => Value::String(format!("{:?}", e)),
79 VariableValue::ListRange(r) => Value::String(r.to_string()),
80 VariableValue::Element(e) => e.as_ref().into(),
81 VariableValue::ElementMetadata(m) => Value::String(m.to_string()),
82 VariableValue::ElementReference(r) => Value::String(r.to_string()),
83 VariableValue::Awaiting => Value::String("Awaiting".to_string()),
84 }
85 }
86}
87
88#[derive(Clone, Debug, Hash, PartialEq, Eq)]
89pub struct ListRange {
90 pub start: RangeBound,
91 pub end: RangeBound,
92}
93
94impl Display for ListRange {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 write!(f, "{}..{}", self.start, self.end)
97 }
98}
99
100#[derive(Clone, Debug, Hash, PartialEq, Eq)]
101pub enum RangeBound {
102 Index(i64),
103 Unbounded,
104}
105
106impl Display for RangeBound {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 match self {
109 RangeBound::Index(i) => write!(f, "{}", i),
110 RangeBound::Unbounded => write!(f, "..."),
111 }
112 }
113}
114
115impl VariableValue {
116 pub fn get<I: Index>(&self, index: I) -> Option<&VariableValue> {
117 index.index_into(self)
118 }
119
120 pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut VariableValue> {
121 index.index_into_mut(self)
122 }
123
124 pub fn as_object(&self) -> Option<&BTreeMap<String, VariableValue>> {
125 match self {
126 VariableValue::Object(map) => Some(map),
127 _ => None,
128 }
129 }
130
131 pub fn as_object_mut(&mut self) -> Option<&mut BTreeMap<String, VariableValue>> {
132 match self {
133 VariableValue::Object(map) => Some(map),
134 _ => None,
135 }
136 }
137
138 pub fn is_object(&self) -> bool {
139 self.as_object().is_some()
140 }
141
142 pub fn as_array(&self) -> Option<&Vec<VariableValue>> {
143 match self {
144 VariableValue::List(list) => Some(list),
145 _ => None,
146 }
147 }
148
149 pub fn as_array_mut(&mut self) -> Option<&mut Vec<VariableValue>> {
150 match self {
151 VariableValue::List(list) => Some(list),
152 _ => None,
153 }
154 }
155
156 pub fn is_array(&self) -> bool {
157 self.as_array().is_some()
158 }
159
160 pub fn as_str(&self) -> Option<&str> {
161 match self {
162 VariableValue::String(s) => Some(s),
163 _ => None,
164 }
165 }
166
167 pub fn is_string(&self) -> bool {
168 self.as_str().is_some()
169 }
170
171 pub fn is_number(&self) -> bool {
172 matches!(*self, VariableValue::Integer(_) | VariableValue::Float(_))
173 }
174
175 pub fn is_i64(&self) -> bool {
176 match self {
177 VariableValue::Integer(n) => n.is_i64(),
178 _ => false,
179 }
180 }
181
182 pub fn is_f64(&self) -> bool {
183 match self {
184 VariableValue::Float(n) => n.is_f64(),
185 _ => false,
186 }
187 }
188
189 pub fn is_u64(&self) -> bool {
190 match self {
191 VariableValue::Integer(n) => n.is_u64(),
192 _ => false,
193 }
194 }
195
196 pub fn as_i64(&self) -> Option<i64> {
197 match self {
198 VariableValue::Integer(n) => n.as_i64(),
199 _ => None,
200 }
201 }
202
203 pub fn as_f64(&self) -> Option<f64> {
204 match self {
205 VariableValue::Float(n) => n.as_f64(),
206 VariableValue::Integer(n) => n.as_i64().map(|n| n as f64),
207 _ => None,
208 }
209 }
210
211 pub fn as_u64(&self) -> Option<u64> {
212 match self {
213 VariableValue::Integer(n) => n.as_u64(),
214 _ => None,
215 }
216 }
217
218 pub fn as_bool(&self) -> Option<bool> {
219 match *self {
220 VariableValue::Bool(b) => Some(b),
221 _ => None,
222 }
223 }
224
225 pub fn is_boolean(&self) -> bool {
226 self.as_bool().is_some()
227 }
228
229 pub fn as_null(&self) -> Option<()> {
230 match *self {
231 VariableValue::Null => Some(()),
232 _ => None,
233 }
234 }
235
236 pub fn is_null(&self) -> bool {
237 self.as_null().is_some()
238 }
239
240 pub fn as_date(&self) -> Option<NaiveDate> {
241 match *self {
242 VariableValue::Date(d) => Some(d),
243 _ => None,
244 }
245 }
246
247 pub fn is_date(&self) -> bool {
248 self.as_date().is_some()
249 }
250
251 pub fn as_local_time(&self) -> Option<NaiveTime> {
252 match *self {
253 VariableValue::LocalTime(t) => Some(t),
254 _ => None,
255 }
256 }
257
258 pub fn is_local_time(&self) -> bool {
259 self.as_local_time().is_some()
260 }
261
262 pub fn as_time(&self) -> Option<ZonedTime> {
263 match self {
264 VariableValue::ZonedTime(t) => Some(*t),
265 _ => None,
266 }
267 }
268
269 pub fn is_time(&self) -> bool {
270 self.as_time().is_some()
271 }
272
273 pub fn as_local_date_time(&self) -> Option<NaiveDateTime> {
274 match *self {
275 VariableValue::LocalDateTime(t) => Some(t),
276 _ => None,
277 }
278 }
279
280 pub fn is_local_date_time(&self) -> bool {
281 self.as_local_date_time().is_some()
282 }
283
284 pub fn as_zoned_date_time(&self) -> Option<ZonedDateTime> {
285 match self {
286 VariableValue::ZonedDateTime(t) => Some(t.clone()),
287 _ => None,
288 }
289 }
290
291 pub fn get_date_property(&self, property: String) -> Option<String> {
292 if self.is_date() {
293 match property.as_str() {
294 "year" => Some(match self.as_date() {
295 Some(date) => date.year().to_string(),
296 None => return None,
297 }),
298 "month" => Some(match self.as_date() {
299 Some(date) => date.month().to_string(),
300 None => return None,
301 }),
302 "day" => Some(match self.as_date() {
303 Some(date) => date.day().to_string(),
304 None => return None,
305 }),
306 _ => None,
307 }
308 } else {
309 None
310 }
311 }
312
313 pub fn is_zoned_date_time(&self) -> bool {
314 self.as_zoned_date_time().is_some()
315 }
316
317 pub fn as_duration(&self) -> Option<Duration> {
318 match self {
319 VariableValue::Duration(d) => Some(d.clone()),
320 _ => None,
321 }
322 }
323
324 pub fn is_duration(&self) -> bool {
325 self.as_duration().is_some()
326 }
327
328 pub fn as_expression(&self) -> Option<AstExpression> {
329 match self {
330 VariableValue::Expression(e) => Some(e.clone()),
331 _ => None,
332 }
333 }
334
335 pub fn is_expression(&self) -> bool {
336 self.as_expression().is_some()
337 }
338
339 pub fn as_list_range(&self) -> Option<ListRange> {
340 match self {
341 VariableValue::ListRange(r) => Some(r.clone()),
342 _ => None,
343 }
344 }
345
346 pub fn is_list_range(&self) -> bool {
347 self.as_list_range().is_some()
348 }
349
350 pub fn pointer(&self, pointer: &str) -> Option<&VariableValue> {
351 if pointer.is_empty() {
352 return Some(self);
353 }
354 if !pointer.starts_with('/') {
355 return None;
356 }
357 pointer
358 .split('/')
359 .skip(1)
360 .map(|x| x.replace("~1", "/").replace("~0", "~"))
361 .try_fold(self, |target, token| match target {
362 VariableValue::Object(map) => map.get(&token),
363 VariableValue::List(list) => parse_index(&token).and_then(|x| list.get(x)),
364 _ => None,
365 })
366 }
367
368 pub fn hash_for_groupby<H: Hasher>(&self, state: &mut H) {
369 match self {
370 VariableValue::Element(element) => element.get_reference().hash(state),
371 _ => self.hash(state),
372 }
373 }
374}
375
376fn parse_index(s: &str) -> Option<usize> {
377 if s.starts_with('+') || (s.starts_with('0') && s.len() != 1) {
378 return None;
379 }
380 s.parse().ok()
381}
382
383impl Debug for VariableValue {
384 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
385 match self {
386 VariableValue::Null => formatter.write_str("Null"),
387 VariableValue::Bool(boolean) => write!(formatter, "Bool({})", boolean),
388 VariableValue::Integer(integer) => write!(formatter, "Integer({})", integer),
389 VariableValue::Float(float) => write!(formatter, "Float({})", float),
390 VariableValue::String(string) => write!(formatter, "String({:?})", string),
391 VariableValue::List(vec) => {
392 let _ = formatter.write_str("List ");
393 Debug::fmt(vec, formatter)
394 }
395 VariableValue::Object(map) => {
396 let _ = formatter.write_str("Object ");
397 Debug::fmt(map, formatter)
398 }
399 VariableValue::Date(date) => write!(formatter, "Date({})", date),
400 VariableValue::LocalTime(time) => write!(formatter, "LocalTime({})", time),
401 VariableValue::ZonedTime(time) => write!(formatter, "Time({})", time),
402 VariableValue::LocalDateTime(time) => write!(formatter, "LocalDateTime({})", time),
403 VariableValue::ZonedDateTime(time) => write!(formatter, "ZonedDateTime({})", time),
404 VariableValue::Duration(duration) => write!(formatter, "Duration({})", duration),
405 VariableValue::Expression(expression) => {
406 write!(formatter, "Expression({:?})", expression)
407 }
408 VariableValue::ListRange(range) => write!(formatter, "ListRange({:?})", range),
409 VariableValue::Element(element) => write!(formatter, "Element({:?})", element),
410 VariableValue::ElementMetadata(metadata) => {
411 write!(formatter, "ElementMetadata({:?})", metadata)
412 }
413 VariableValue::ElementReference(reference) => {
414 write!(formatter, "ElementReference({:?})", reference)
415 }
416 VariableValue::Awaiting => write!(formatter, "Awaiting"),
417 }
418 }
419}
420
421impl Display for VariableValue {
422 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
423 match &self {
424 VariableValue::Null => write!(f, "null"),
425 VariableValue::Bool(b) => write!(f, "{}", b),
426 VariableValue::Integer(i) => write!(f, "{}", i),
427 VariableValue::Float(fl) => write!(f, "{}", fl),
428 VariableValue::String(s) => write!(f, "{}", s),
429 VariableValue::List(l) => {
430 let mut first = true;
431 write!(f, "[")?;
432 for item in l {
433 if first {
434 first = false;
435 } else {
436 write!(f, ", ")?;
437 }
438 write!(f, "{}", item)?;
439 }
440 write!(f, "]")
441 }
442 VariableValue::Object(o) => {
443 let mut first = true;
444 write!(f, "{{")?;
445 for (key, value) in o {
446 if first {
447 first = false;
448 } else {
449 write!(f, ", ")?;
450 }
451 write!(f, "{}: {}", key, value)?;
452 }
453 write!(f, "}}")
454 }
455 VariableValue::Date(d) => write!(f, "{}", d),
456 VariableValue::LocalTime(t) => write!(f, "{}", t),
457 VariableValue::ZonedTime(t) => write!(f, "{}", t),
458 VariableValue::LocalDateTime(t) => write!(f, "{}", t),
459 VariableValue::ZonedDateTime(t) => write!(f, "{}", t),
460 VariableValue::Duration(d) => write!(f, "{}", d),
461 VariableValue::Expression(e) => write!(f, "{:?}", e),
462 VariableValue::ListRange(r) => write!(f, "{}", r),
463 VariableValue::Element(e) => write!(f, "{:?}", e),
464 VariableValue::ElementMetadata(m) => write!(f, "{}", m),
465 VariableValue::ElementReference(r) => write!(f, "{}", r),
466 VariableValue::Awaiting => write!(f, "Awaiting"),
467 }
468 }
469}
470
471pub mod de;
472pub mod duration;
473pub mod float;
474mod from;
475mod index;
476pub mod integer;
477mod partial_eq;
478pub mod ser;
479#[cfg(test)]
480mod tests;
481pub mod zoned_datetime;
482pub mod zoned_time;