1use std::{
2 collections::HashMap,
3 fmt::{self, Display, Formatter},
4 hash::{self, Hash},
5 ops::{Index, IndexMut},
6 slice::SliceIndex,
7 sync::LazyLock,
8};
9
10use chrono::{DateTime, TimeDelta, Utc};
11use num_bigint::BigInt;
12
13use crate::stringify::{StringifyOptions, str_key, stringify};
14
15#[derive(Debug, Clone)]
75pub enum Value {
76 Bool(bool),
78 Int(i64),
80 Uint(u64),
82 BigInt(BigInt),
84 Float(f64),
86 Str(String),
88 Inst(DateTime<Utc>),
90 Dur(TimeDelta),
92 UUID([u8; 16]),
94 Arr(Vec<Value>),
96 Map(Box<HashMap<Key, Value>>),
98 UnitVar(String),
100}
101
102#[derive(Debug, Clone, Hash, Eq)]
114pub enum Key {
115 Bool(bool),
117 Int(i64),
119 Uint(u64),
121 BigInt(BigInt),
123 Str(String),
125 Inst(DateTime<Utc>),
127 Dur(TimeDelta),
129 UUID([u8; 16]),
131}
132
133impl Default for Value {
134 fn default() -> Self {
135 Value::Uint(0)
136 }
137}
138impl Default for Key {
139 fn default() -> Self {
140 Key::Uint(0)
141 }
142}
143
144pub static ENUM_VARIANT_KEY: LazyLock<Key> =
145 LazyLock::new(|| Key::Str("$enum_variant".to_string()));
146pub static HAS_META_KEY: LazyLock<Key> = LazyLock::new(|| Key::Str("$has_meta".to_string()));
147pub static INNER_KEY: LazyLock<Key> = LazyLock::new(|| Key::Str("$value".to_string()));
148impl Key {
149 pub fn enum_variant_key() -> &'static Key {
151 &ENUM_VARIANT_KEY
152 }
153 pub fn has_meta_key() -> &'static Key {
155 &HAS_META_KEY
156 }
157 pub fn inner_key() -> &'static Key {
159 &INNER_KEY
160 }
161}
162
163macro_rules! is_impl {
164 ($enum:ident, $(($ty:ident, $met:ident)),+) => {
165 $(pub fn $met(&self) -> bool {
166 match self {
167 $enum::$ty(_) => true,
168 _ => false,
169 }
170 })+
171 };
172}
173
174impl Value {
176 is_impl!(Value, (Bool, is_bool), (Uint, is_uint), (Int, is_int), (Str, is_str));
177 is_impl!(Value, (BigInt, is_bigint), (Float, is_float), (Inst, is_inst), (Dur, is_dur));
178 is_impl!(Value, (UUID, is_uuid), (Arr, is_array), (Map, is_map), (UnitVar, is_unit_variant));
179
180 pub fn is_enum(&self) -> bool {
182 match self {
183 Value::UnitVar(_) => true,
184 Value::Map(map) => map.contains_key(&ENUM_VARIANT_KEY),
185 _ => false,
186 }
187 }
188 pub fn has_meta(&self) -> bool {
190 match self {
191 Value::Map(map) => map.contains_key(&HAS_META_KEY),
192 _ => false,
193 }
194 }
195}
196
197impl Key {
199 is_impl!(Key, (Bool, is_bool), (Uint, is_uint), (Int, is_int), (Str, is_str));
200 is_impl!(Key, (BigInt, is_bigint), (Inst, is_inst), (Dur, is_dur), (UUID, is_uuid));
201}
202
203impl Value {
204 pub fn into_key(self) -> Option<Key> {
206 self.try_into().ok()
207 }
208 pub fn enum_variant(&self) -> Option<&str> {
210 match self {
211 Value::UnitVar(str) => Some(str),
212 Value::Map(map) => map.get(&ENUM_VARIANT_KEY)?.as_str(),
213 _ => None,
214 }
215 }
216 pub fn inner(&self) -> &Value {
218 match &self {
219 Value::Map(map) if map.contains_key(&HAS_META_KEY) => &map[&INNER_KEY],
220 _ => &self,
221 }
222 }
223 pub fn inner_mut(&mut self) -> &mut Value {
225 if let Value::Map(map) = self {
226 if map.contains_key(&HAS_META_KEY) {
227 return map.get_mut(&INNER_KEY).unwrap();
228 }
229 panic!("actualy this doesnt work since of dark magic, if you can fix it, please do")
230 }
231 self
232 }
233 pub fn into_inner(self) -> Value {
235 match self {
236 Value::Map(mut map) if map.contains_key(&HAS_META_KEY) => {
237 map.remove(&INNER_KEY).unwrap()
238 }
239 _ => self,
240 }
241 }
242}
243
244impl TryFrom<Value> for Key {
245 type Error = ();
246 fn try_from(value: Value) -> Result<Self, Self::Error> {
247 match value {
248 Value::Bool(b) => Ok(Key::Bool(b)),
249 Value::Int(i) => Ok(Key::Int(i)),
250 Value::Uint(i) => Ok(Key::Uint(i)),
251 Value::BigInt(i) => Ok(Key::BigInt(i)),
252 Value::Str(s) => Ok(Key::Str(s)),
253 Value::Inst(i) => Ok(Key::Inst(i)),
254 Value::Dur(d) => Ok(Key::Dur(d)),
255 Value::UUID(u) => Ok(Key::UUID(u)),
256 _ => Err(()),
257 }
258 }
259}
260impl From<Key> for Value {
261 fn from(key: Key) -> Self {
262 match key {
263 Key::Bool(b) => Value::Bool(b),
264 Key::Int(i) => Value::Int(i),
265 Key::Uint(i) => Value::Uint(i),
266 Key::BigInt(i) => Value::BigInt(i),
267 Key::Str(s) => Value::Str(s),
268 Key::Inst(i) => Value::Inst(i),
269 Key::Dur(d) => Value::Dur(d),
270 Key::UUID(u) => Value::UUID(u),
271 }
272 }
273}
274
275macro_rules! from_impl {
276 ($enum:ident, $(($ty:ty, $var:ident)),+) => {
277 $(impl From<$ty> for $enum {
278 fn from(v: $ty) -> Self {
279 $enum::$var(v)
280 }
281 })+
282 };
283 ($enum:ident, $var:ident, $as:ident, [$($ty:ident),+]) => {
284 $(impl From<$ty> for $enum {
285 fn from(v: $ty) -> Self {
286 $enum::$var(v as $as)
287 }
288 })+
289 };
290}
291
292from_impl!(Value, (bool, Bool), (i64, Int), (u64, Uint), (f64, Float));
293from_impl!(Value, (String, Str), (DateTime<Utc>, Inst), (TimeDelta, Dur));
294from_impl!(Value, ([u8; 16], UUID), (BigInt, BigInt));
295
296from_impl!(Value, Uint, u64, [u8, u16, u32, usize]);
297from_impl!(Value, Int, i64, [i8, i16, i32, isize]);
298from_impl!(Value, Float, f64, [f32]);
299
300from_impl!(Key, (bool, Bool), (i64, Int), (u64, Uint), (String, Str), (BigInt, BigInt));
301from_impl!(Key, (DateTime<Utc>, Inst), (TimeDelta, Dur), ([u8; 16], UUID));
302
303from_impl!(Key, Uint, u64, [u8, u16, u32, usize]);
304from_impl!(Key, Int, i64, [i8, i16, i32, isize]);
305
306impl From<&str> for Value {
307 fn from(s: &str) -> Self {
308 Value::Str(s.to_string())
309 }
310}
311impl From<&str> for Key {
312 fn from(s: &str) -> Self {
313 Key::Str(s.to_string())
314 }
315}
316
317impl<T: Into<Value>> From<Vec<T>> for Value {
318 fn from(v: Vec<T>) -> Self {
319 Value::Arr(v.into_iter().map(|v| v.into()).collect())
320 }
321}
322impl<K: Into<Key>, V: Into<Value>> From<HashMap<K, V>> for Value {
323 fn from(m: HashMap<K, V>) -> Self {
324 Value::Map(Box::new(m.into_iter().map(|(k, v)| (k.into(), v.into())).collect()))
325 }
326}
327
328impl Value {
329 pub fn map_from<K: Into<Key>, V: Into<Value>, I: IntoIterator<Item = (K, V)>>(
330 iter: I,
331 ) -> Value {
332 Value::Map(Box::new(iter.into_iter().map(|(k, v)| (k.into(), v.into())).collect()))
333 }
334}
335
336macro_rules! try_into_impl {
337 ($enum:ident, $(($ty:ty, $var:ident)),+) => {
338 $(impl TryInto<$ty> for $enum {
339 type Error = ();
340 fn try_into(self) -> Result<$ty, Self::Error> {
341 match self {
342 $enum::$var(v) => Ok(v as $ty),
343 _ => Err(()),
344 }
345 }
346 })+
347 };
348}
349macro_rules! try_into_int_impl {
350 ($enum:ident, [$($ty:ty),+]) => {
351 $(impl TryInto<$ty> for $enum {
352 type Error = ();
353 fn try_into(self) -> Result<$ty, Self::Error> {
354 match self {
355 $enum::Int(v) => Ok(v.try_into().map_err(|_| ())?),
356 $enum::Uint(v) => Ok(v.try_into().map_err(|_| ())?),
357 _ => Err(()),
358 }
359 }
360 })+
361 };
362}
363try_into_impl!(Value, (bool, Bool), (u64, Uint), (i64, Int), (f64, Float), (f32, Float));
364try_into_impl!(Value, (String, Str), (DateTime<Utc>, Inst), (TimeDelta, Dur));
365try_into_impl!(Value, ([u8; 16], UUID), (BigInt, BigInt));
366
367try_into_int_impl!(Value, [u8, u16, u32, usize, i8, i16, i32, isize]);
368
369try_into_impl!(Key, (bool, Bool), (u64, Uint), (i64, Int), (String, Str), (BigInt, BigInt));
370try_into_impl!(Key, (DateTime<Utc>, Inst), (TimeDelta, Dur), ([u8; 16], UUID));
371try_into_int_impl!(Key, [u8, u16, u32, usize, i8, i16, i32, isize]);
372
373impl<T> TryInto<Vec<T>> for Value
374where
375 Value: TryInto<T>,
376{
377 type Error = ();
378 fn try_into(self) -> Result<Vec<T>, Self::Error> {
379 match self {
380 Value::Arr(v) => {
381 let mut vec = Vec::<T>::with_capacity(v.len());
382 for item in v {
383 vec.push(item.try_into().map_err(|_| ())?);
384 }
385 Ok(vec)
386 }
387 _ => Err(()),
388 }
389 }
390}
391impl<K, V> TryInto<HashMap<K, V>> for Value
392where
393 Key: TryInto<K>,
394 Value: TryInto<V>,
395 K: Eq + hash::Hash,
396{
397 type Error = ();
398 fn try_into(self) -> Result<HashMap<K, V>, Self::Error> {
399 match self {
400 Value::Map(m) => {
401 let mut map = HashMap::<K, V>::with_capacity(m.len());
402 for (k, v) in *m {
403 map.insert(k.try_into().map_err(|_| ())?, v.try_into().map_err(|_| ())?);
404 }
405 Ok(map)
406 }
407 _ => Err(()),
408 }
409 }
410}
411
412impl Value {
413 pub fn cast<T>(self) -> Option<T>
415 where
416 Value: TryInto<T>,
417 {
418 TryInto::try_into(self).ok()
419 }
420}
421impl Key {
422 pub fn cast<T>(self) -> Option<T>
424 where
425 Key: TryInto<T>,
426 {
427 TryInto::try_into(self).ok()
428 }
429}
430
431macro_rules! as_impl {
432 ($enum:ident, $(($ty:ty, $met:ident, $var:ident)),+) => {
433 $(pub fn $met(&self) -> Option<$ty> {
434 match self {
435 $enum::$var(v) => Some(*v),
436 _ => None,
437 }
438 })+
439 };
440}
441macro_rules! as_ref_impl {
442 ($enum:ident, $(($ty:ty, $met:ident, $var:ident)),+) => {
443 $(pub fn $met(&self) -> Option<&$ty> {
444 match self {
445 $enum::$var(v) => Some(v),
446 _ => None,
447 }
448 })+
449 };
450}
451macro_rules! as_mut_impl {
452 ($enum:ident, $(($ty:ty, $met:ident, $var:ident)),+) => {
453 $(pub fn $met(&mut self) -> Option<&mut $ty> {
454 match self {
455 $enum::$var(v) => Some(v),
456 _ => None,
457 }
458 })+
459 };
460}
461
462impl Value {
466 as_impl!(Value, (bool, as_bool, Bool), (i64, as_int, Int), (u64, as_uint, Uint));
467 as_impl!(Value, (f64, as_float, Float), ([u8; 16], as_uuid, UUID));
468 as_impl!(Value, (TimeDelta, as_dur, Dur), (DateTime<Utc>, as_inst, Inst));
469 as_ref_impl!(Value, (str, as_str, Str), ([Value], as_slice, Arr));
470 as_ref_impl!(Value, (BigInt, as_bigint, BigInt), (HashMap<Key, Value>, as_map, Map));
471 as_mut_impl!(Value, (Vec<Value>, as_vec_mut, Arr), (HashMap<Key, Value>, as_map_mut, Map));
472}
473
474impl Key {
476 as_impl!(Key, (bool, as_bool, Bool), (i64, as_int, Int), ([u8; 16], as_uuid, UUID));
477 as_impl!(Key, (TimeDelta, as_dur, Dur), (DateTime<Utc>, as_inst, Inst), (u64, as_uint, Uint));
478 as_ref_impl!(Key, (str, as_str, Str), (BigInt, as_bigint, BigInt));
479}
480
481impl PartialEq<Value> for Value {
482 fn eq(&self, other: &Value) -> bool {
483 match (self, other) {
484 (Value::Bool(a), Value::Bool(b)) => *a == *b,
485 (Value::Int(a), Value::Int(b)) => *a == *b,
486 (Value::Uint(a), Value::Uint(b)) => *a == *b,
487 (Value::Int(a), Value::Uint(b)) => *a == *b as _,
488 (Value::Uint(a), Value::Int(b)) => *a == *b as _,
489 (Value::BigInt(a), Value::BigInt(b)) => a == b,
490 (Value::Float(a), Value::Float(b)) => *a == *b,
491 (Value::Str(a), Value::Str(b)) => a == b,
492 (Value::Inst(a), Value::Inst(b)) => a == b,
493 (Value::Dur(a), Value::Dur(b)) => a == b,
494 (Value::UUID(a), Value::UUID(b)) => a == b,
495 (Value::Arr(a), Value::Arr(b)) => a == b,
496 (Value::Map(a), Value::Map(b)) => a == b,
497 (Value::UnitVar(a), Value::UnitVar(b)) => a == b,
498 _ => false,
499 }
500 }
501}
502impl PartialEq<Key> for Key {
503 fn eq(&self, other: &Key) -> bool {
504 match (self, other) {
505 (Key::Bool(a), Key::Bool(b)) => *a == *b,
506 (Key::Int(a), Key::Int(b)) => *a == *b,
507 (Key::Uint(a), Key::Uint(b)) => *a == *b,
508 (Key::Int(a), Key::Uint(b)) => *a == *b as _,
509 (Key::Uint(a), Key::Int(b)) => *a == *b as _,
510 (Key::BigInt(a), Key::BigInt(b)) => a == b,
511 (Key::Str(a), Key::Str(b)) => a == b,
512 (Key::Inst(a), Key::Inst(b)) => a == b,
513 (Key::Dur(a), Key::Dur(b)) => a == b,
514 (Key::UUID(a), Key::UUID(b)) => a == b,
515 _ => false,
516 }
517 }
518}
519
520impl PartialEq<Key> for Value {
521 fn eq(&self, other: &Key) -> bool {
522 match (self, other) {
523 (Value::Bool(a), Key::Bool(b)) => a == b,
524 (Value::Int(a), Key::Int(b)) => a == b,
525 (Value::Uint(a), Key::Uint(b)) => a == b,
526 (Value::BigInt(a), Key::BigInt(b)) => a == b,
527 (Value::Str(a), Key::Str(b)) => a == b,
528 (Value::Inst(a), Key::Inst(b)) => a == b,
529 (Value::Dur(a), Key::Dur(b)) => a == b,
530 (Value::UUID(a), Key::UUID(b)) => a == b,
531 _ => false,
532 }
533 }
534}
535
536macro_rules! eq_impl {
537 ($enum:ident, $(($ty:ty, $var:ident)),+) => {
538 $(impl PartialEq<$ty> for $enum {
539 fn eq(&self, other: &$ty) -> bool {
540 match self {
541 $enum::$var(v) => v == other,
542 _ => false,
543 }
544 }
545 })+
546 };
547}
548macro_rules! eq_int_impl {
549 ($enum:ident, [$($ty:ty),+]) => {
550 $(impl PartialEq<$ty> for $enum {
551 fn eq(&self, other: &$ty) -> bool {
552 match self {
553 $enum::Uint(v) => *v as $ty == *other,
554 $enum::Int(v) => *v as $ty == *other,
555 _ => false,
556 }
557 }
558 }
559 impl PartialEq<$ty> for &$enum {
560 fn eq(&self, other: &$ty) -> bool {
561 match self {
562 $enum::Uint(v) => *v as $ty == *other,
563 $enum::Int(v) => *v as $ty == *other,
564 _ => false,
565 }
566 }
567 })+
568 };
569}
570
571eq_impl!(Value, (bool, Bool), (DateTime<Utc>, Inst), (TimeDelta, Dur), (f64, Float));
572eq_impl!(Value, (&str, Str), (String, Str), ([u8; 16], UUID), (BigInt, BigInt));
573
574eq_int_impl!(Value, [u8, u16, u32, u64, usize]);
575eq_int_impl!(Value, [i8, i16, i32, i64, isize]);
576
577eq_impl!(Key, (bool, Bool), (DateTime<Utc>, Inst), (TimeDelta, Dur), (String, Str), (&str, Str));
578eq_impl!(Key, (BigInt, BigInt), ([u8; 16], UUID));
579
580eq_int_impl!(Key, [u8, u16, u32, u64, usize]);
581eq_int_impl!(Key, [i8, i16, i32, i64, isize]);
582
583impl<T> PartialEq<Vec<T>> for Value
584where
585 Value: PartialEq<T>,
586{
587 fn eq(&self, other: &Vec<T>) -> bool {
588 match self {
589 Value::Arr(a) => a == other,
590 _ => false,
591 }
592 }
593}
594
595impl<I: SliceIndex<[Value]>> Index<I> for Value {
596 type Output = <I as SliceIndex<[Value]>>::Output;
597 fn index(&self, index: I) -> &Self::Output {
598 match self {
599 Value::Arr(a) => &a[index],
600 _ => panic!(),
601 }
602 }
603}
604impl<I: SliceIndex<[Value]>> IndexMut<I> for Value {
605 fn index_mut(&mut self, index: I) -> &mut Self::Output {
606 match self {
607 Value::Arr(a) => &mut a[index],
608 _ => panic!(),
609 }
610 }
611}
612impl Index<&Key> for Value {
613 type Output = Value;
614 fn index(&self, index: &Key) -> &Self::Output {
615 match self {
616 Value::Map(m) => m.get(index).unwrap(),
617 _ => panic!(),
618 }
619 }
620}
621impl IndexMut<&Key> for Value {
622 fn index_mut(&mut self, index: &Key) -> &mut Self::Output {
623 match self {
624 Value::Map(m) => match m.contains_key(index) {
625 true => m.get_mut(index).unwrap(),
626 false => m.entry(index.clone()).or_insert(Value::default()),
627 },
628 _ => panic!(),
629 }
630 }
631}
632impl Value {
633 pub fn index_arr<I: SliceIndex<[Value]>>(
635 &self, index: I,
636 ) -> Option<&<I as SliceIndex<[Value]>>::Output> {
637 match self {
638 Value::Arr(a) => a.get(index),
639 _ => None,
640 }
641 }
642 pub fn index_arr_mut<I: SliceIndex<[Value]>>(
644 &mut self, index: I,
645 ) -> Option<&mut <I as SliceIndex<[Value]>>::Output> {
646 match self {
647 Value::Arr(a) => a.get_mut(index),
648 _ => None,
649 }
650 }
651 pub fn index_map(&self, key: &Key) -> Option<&Value> {
653 match self {
654 Value::Map(m) => m.get(key),
655 _ => None,
656 }
657 }
658 pub fn index_map_mut(&mut self, key: &Key) -> Option<&mut Value> {
660 match self {
661 Value::Map(m) => m.get_mut(key),
662 _ => None,
663 }
664 }
665}
666
667impl Display for Value {
668 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
669 if f.alternate() {
670 stringify(self, &StringifyOptions { ident: "\t", ..Default::default() }).fmt(f)
671 } else {
672 stringify(self, &StringifyOptions::default()).fmt(f)
673 }
674 }
675}
676
677impl Display for Key {
678 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
679 str_key(self).fmt(f)
680 }
681}