helix_db/protocol/
value.rs

1use crate::{helix_engine::types::GraphError, helixc::generator::utils::GenRef};
2use chrono::Utc;
3use serde::{
4    Deserializer, Serializer,
5    de::{DeserializeSeed, VariantAccess, Visitor},
6};
7use serde_json::Value as JsonValue;
8use sonic_rs::{Deserialize, Serialize};
9use std::{
10    cmp::Ordering,
11    collections::HashMap,
12    fmt::{self, Display},
13};
14use crate::utils::id::ID;
15
16
17/// A flexible value type that can represent various property values in nodes and edges.
18/// Handles both JSON and binary serialisation formats via custom implementaions of the Serialize and Deserialize traits.
19#[derive(Clone, PartialEq, Debug)]
20pub enum Value {
21    String(String),
22    F32(f32),
23    F64(f64),
24    I8(i8),
25    I16(i16),
26    I32(i32),
27    I64(i64),
28    U8(u8),
29    U16(u16),
30    U32(u32),
31    U64(u64),
32    U128(u128),
33    Boolean(bool),
34    Array(Vec<Value>),
35    Object(HashMap<String, Value>),
36    Empty,
37}
38
39impl Value {
40    pub fn to_string(&self) -> String {
41        match self {
42            Value::String(s) => s.to_string(),
43            Value::F32(f) => f.to_string(),
44            Value::F64(f) => f.to_string(),
45            Value::I8(i) => i.to_string(),
46            Value::I16(i) => i.to_string(),
47            Value::I32(i) => i.to_string(),
48            Value::I64(i) => i.to_string(),
49            Value::U8(u) => u.to_string(),
50            Value::U16(u) => u.to_string(),
51            Value::U32(u) => u.to_string(),
52            Value::U64(u) => u.to_string(),
53            Value::U128(u) => u.to_string(),
54            Value::Boolean(b) => b.to_string(),
55            Value::Array(arr) => arr
56                .iter()
57                .map(|v| v.to_string())
58                .collect::<Vec<String>>()
59                .join(" "),
60            Value::Object(obj) => obj
61                .iter()
62                .map(|(k, v)| format!("{} {}", k, v.to_string()))
63                .collect::<Vec<String>>()
64                .join(" "),
65            _ => panic!("Not primitive"),
66        }
67    }
68
69    pub fn as_str(&self) -> &str {
70        match self {
71            Value::String(s) => s.as_str(),
72            _ => panic!("Not a string"),
73        }
74    }
75
76    #[inline]
77    #[allow(unused_variables)] // default is not used but needed for function signature
78    pub fn map_value_or(
79        self,
80        default: bool,
81        f: impl Fn(&Value) -> bool,
82    ) -> Result<bool, GraphError> {
83        Ok(f(&self))
84    }
85}
86impl Display for Value {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        match self {
89            Value::String(_) => write!(f, "String"),
90            Value::F32(_) => write!(f, "F32"),
91            Value::F64(_) => write!(f, "F64"),
92            Value::I8(_) => write!(f, "I8"),
93            Value::I16(_) => write!(f, "I16"),
94            Value::I32(_) => write!(f, "I32"),
95            Value::I64(_) => write!(f, "I64"),
96            Value::U8(_) => write!(f, "U8"),
97            Value::U16(_) => write!(f, "U16"),
98            Value::U32(_) => write!(f, "U32"),
99            Value::U64(_) => write!(f, "U64"),
100            Value::U128(_) => write!(f, "U128"),
101            Value::Boolean(_) => write!(f, "Boolean"),
102            Value::Array(_) => write!(f, "Array"),
103            Value::Object(_) => write!(f, "Object"),
104            Value::Empty => write!(f, "Empty"),
105        }
106    }
107}
108impl Ord for Value {
109    fn cmp(&self, other: &Self) -> Ordering {
110        match (self, other) {
111            (Value::String(s), Value::String(o)) => s.cmp(o),
112            (Value::F32(s), Value::F32(o)) => match s.partial_cmp(o) {
113                Some(o) => o,
114                None => Ordering::Equal,
115            },
116            (Value::F64(s), Value::F64(o)) => match s.partial_cmp(o) {
117                Some(o) => o,
118                None => Ordering::Equal,
119            },
120            (Value::I8(s), Value::I8(o)) => s.cmp(o),
121            (Value::I16(s), Value::I16(o)) => s.cmp(o),
122            (Value::I32(s), Value::I32(o)) => s.cmp(o),
123            (Value::I64(s), Value::I64(o)) => s.cmp(o),
124            (Value::U8(s), Value::U8(o)) => s.cmp(o),
125            (Value::U16(s), Value::U16(o)) => s.cmp(o),
126            (Value::U32(s), Value::U32(o)) => s.cmp(o),
127            (Value::U64(s), Value::U64(o)) => s.cmp(o),
128            (Value::U128(s), Value::U128(o)) => s.cmp(o),
129            (Value::Boolean(s), Value::Boolean(o)) => s.cmp(o),
130            (Value::Array(s), Value::Array(o)) => s.cmp(o),
131            (Value::Empty, Value::Empty) => Ordering::Equal,
132            (Value::Empty, _) => Ordering::Less,
133            (_, Value::Empty) => Ordering::Greater,
134            (_, _) => Ordering::Equal,
135        }
136    }
137}
138
139impl PartialOrd for Value {
140    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
141        Some(self.cmp(other))
142    }
143}
144
145impl Eq for Value {}
146
147impl PartialEq<i32> for Value {
148    fn eq(&self, other: &i32) -> bool {
149        match self {
150            Value::I32(i) => i == other,
151            _ => false,
152        }
153    }
154}
155impl PartialEq<i64> for Value {
156    fn eq(&self, other: &i64) -> bool {
157        match self {
158            Value::I64(i) => i == other,
159            _ => false,
160        }
161    }
162}
163
164impl PartialEq<f64> for Value {
165    fn eq(&self, other: &f64) -> bool {
166        match self {
167            Value::F64(f) => f == other,
168            _ => false,
169        }
170    }
171}
172
173impl PartialEq<String> for Value {
174    fn eq(&self, other: &String) -> bool {
175        match self {
176            Value::String(s) => s == other,
177            _ => false,
178        }
179    }
180}
181
182impl PartialEq<bool> for Value {
183    fn eq(&self, other: &bool) -> bool {
184        match self {
185            Value::Boolean(b) => b == other,
186            _ => false,
187        }
188    }
189}
190
191impl PartialEq<f32> for Value {
192    fn eq(&self, other: &f32) -> bool {
193        match self {
194            Value::F32(f) => f == other,
195            _ => false,
196        }
197    }
198}
199
200impl PartialEq<&str> for Value {
201    fn eq(&self, other: &&str) -> bool {
202        match self {
203            Value::String(s) => s == other,
204            _ => false,
205        }
206    }
207}
208
209impl PartialOrd<i64> for Value {
210    fn partial_cmp(&self, other: &i64) -> Option<Ordering> {
211        match self {
212            Value::I64(i) => i.partial_cmp(other),
213            _ => None,
214        }
215    }
216}
217
218impl PartialOrd<i32> for Value {
219    fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
220        match self {
221            Value::I32(i) => i.partial_cmp(other),
222            _ => None,
223        }
224    }
225}
226impl PartialOrd<f64> for Value {
227    fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
228        match self {
229            Value::F64(f) => f.partial_cmp(other),
230            _ => None,
231        }
232    }
233}
234
235/// Custom serialisation implementation for Value that removes enum variant names in JSON
236/// whilst preserving them for binary formats like bincode.
237impl Serialize for Value {
238    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
239    where
240        S: Serializer,
241    {
242        if serializer.is_human_readable() {
243            match self {
244                Value::String(s) => s.serialize(serializer),
245                Value::F32(f) => f.serialize(serializer),
246                Value::F64(f) => f.serialize(serializer),
247                Value::I8(i) => i.serialize(serializer),
248                Value::I16(i) => i.serialize(serializer),
249                Value::I32(i) => i.serialize(serializer),
250                Value::I64(i) => i.serialize(serializer),
251                Value::U8(i) => i.serialize(serializer),
252                Value::U16(i) => i.serialize(serializer),
253                Value::U32(i) => i.serialize(serializer),
254                Value::U64(i) => i.serialize(serializer),
255                Value::U128(i) => i.serialize(serializer),
256                Value::Boolean(b) => b.serialize(serializer),
257                Value::Array(arr) => {
258                    use serde::ser::SerializeSeq;
259                    let mut seq = serializer.serialize_seq(Some(arr.len()))?;
260                    for value in arr {
261                        seq.serialize_element(&value)?;
262                    }
263                    seq.end()
264                }
265                Value::Object(obj) => {
266                    use serde::ser::SerializeMap;
267                    let mut map = serializer.serialize_map(Some(obj.len()))?;
268                    for (k, v) in obj {
269                        map.serialize_entry(k, v)?;
270                    }
271                    map.end()
272                }
273                Value::Empty => serializer.serialize_none(),
274            }
275        } else {
276            match self {
277                Value::String(s) => serializer.serialize_newtype_variant("Value", 0, "String", s),
278                Value::F32(f) => serializer.serialize_newtype_variant("Value", 1, "F32", f),
279                Value::F64(f) => serializer.serialize_newtype_variant("Value", 2, "F64", f),
280                Value::I8(i) => serializer.serialize_newtype_variant("Value", 3, "I8", i),
281                Value::I16(i) => serializer.serialize_newtype_variant("Value", 4, "I16", i),
282                Value::I32(i) => serializer.serialize_newtype_variant("Value", 5, "I32", i),
283                Value::I64(i) => serializer.serialize_newtype_variant("Value", 6, "I64", i),
284                Value::U8(i) => serializer.serialize_newtype_variant("Value", 7, "U8", i),
285                Value::U16(i) => serializer.serialize_newtype_variant("Value", 8, "U16", i),
286                Value::U32(i) => serializer.serialize_newtype_variant("Value", 9, "U32", i),
287                Value::U64(i) => serializer.serialize_newtype_variant("Value", 10, "U64", i),
288                Value::U128(i) => serializer.serialize_newtype_variant("Value", 11, "U128", i),
289                Value::Boolean(b) => {
290                    serializer.serialize_newtype_variant("Value", 12, "Boolean", b)
291                }
292                Value::Array(a) => serializer.serialize_newtype_variant("Value", 13, "Array", a),
293                Value::Object(obj) => {
294                    serializer.serialize_newtype_variant("Value", 14, "Object", obj)
295                }
296                Value::Empty => serializer.serialize_unit_variant("Value", 15, "Empty"),
297            }
298        }
299    }
300}
301
302/// Custom deserialisation implementation for Value that handles both JSON and binary formats.
303/// For JSON, parses raw values directly.
304/// For binary formats like bincode, reconstructs the full enum structure.
305impl<'de> Deserialize<'de> for Value {
306    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
307    where
308        D: Deserializer<'de>,
309    {
310        /// Visitor implementation that handles conversion of raw values into Value enum variants.
311        /// Supports both direct value parsing for JSON and enum variant parsing for binary formats.
312        struct ValueVisitor;
313
314        impl<'de> Visitor<'de> for ValueVisitor {
315            type Value = Value;
316
317            #[inline]
318            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
319                formatter.write_str("a string, number, boolean, array, null, or Value enum")
320            }
321
322            #[inline]
323            fn visit_str<E>(self, value: &str) -> Result<Value, E>
324            where
325                E: serde::de::Error,
326            {
327                Ok(Value::String(value.to_owned()))
328            }
329
330            #[inline]
331            fn visit_string<E>(self, value: String) -> Result<Value, E>
332            where
333                E: serde::de::Error,
334            {
335                Ok(Value::String(value))
336            }
337
338            #[inline]
339            fn visit_f32<E>(self, value: f32) -> Result<Value, E>
340            where
341                E: serde::de::Error,
342            {
343                Ok(Value::F32(value))
344            }
345
346            #[inline]
347            fn visit_f64<E>(self, value: f64) -> Result<Value, E>
348            where
349                E: serde::de::Error,
350            {
351                Ok(Value::F64(value))
352            }
353
354            #[inline]
355            fn visit_i8<E>(self, value: i8) -> Result<Value, E>
356            where
357                E: serde::de::Error,
358            {
359                Ok(Value::I8(value))
360            }
361
362            #[inline]
363            fn visit_i16<E>(self, value: i16) -> Result<Value, E>
364            where
365                E: serde::de::Error,
366            {
367                Ok(Value::I16(value))
368            }
369
370            #[inline]
371            fn visit_i32<E>(self, value: i32) -> Result<Value, E>
372            where
373                E: serde::de::Error,
374            {
375                Ok(Value::I32(value))
376            }
377
378            #[inline]
379            fn visit_i64<E>(self, value: i64) -> Result<Value, E>
380            where
381                E: serde::de::Error,
382            {
383                Ok(Value::I64(value))
384            }
385
386            #[inline]
387            fn visit_u8<E>(self, value: u8) -> Result<Value, E>
388            where
389                E: serde::de::Error,
390            {
391                Ok(Value::U8(value))
392            }
393
394            #[inline]
395            fn visit_u16<E>(self, value: u16) -> Result<Value, E>
396            where
397                E: serde::de::Error,
398            {
399                Ok(Value::U16(value))
400            }
401
402            #[inline]
403            fn visit_u32<E>(self, value: u32) -> Result<Value, E>
404            where
405                E: serde::de::Error,
406            {
407                Ok(Value::U32(value))
408            }
409
410            #[inline]
411            fn visit_u64<E>(self, value: u64) -> Result<Value, E>
412            where
413                E: serde::de::Error,
414            {
415                Ok(Value::U64(value))
416            }
417
418            #[inline]
419            fn visit_u128<E>(self, value: u128) -> Result<Value, E>
420            where
421                E: serde::de::Error,
422            {
423                Ok(Value::U128(value))
424            }
425
426            #[inline]
427            fn visit_bool<E>(self, value: bool) -> Result<Value, E>
428            where
429                E: serde::de::Error,
430            {
431                Ok(Value::Boolean(value))
432            }
433
434            #[inline]
435            fn visit_none<E>(self) -> Result<Value, E>
436            where
437                E: serde::de::Error,
438            {
439                Ok(Value::Empty)
440            }
441
442            /// Handles array values by recursively deserialising each element
443            fn visit_seq<A>(self, mut seq: A) -> Result<Value, A::Error>
444            where
445                A: serde::de::SeqAccess<'de>,
446            {
447                let mut values = Vec::new();
448                while let Some(value) = seq.next_element()? {
449                    values.push(value);
450                }
451                Ok(Value::Array(values))
452            }
453
454            /// Handles binary format deserialisation using numeric indices to identify variants
455            /// Maps indices 0-5 to corresponding Value enum variants
456            fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
457            where
458                A: serde::de::EnumAccess<'de>,
459            {
460                let (variant_idx, variant_data) = data.variant_seed(VariantIdxDeserializer)?;
461                match variant_idx {
462                    0 => Ok(Value::String(variant_data.newtype_variant()?)),
463                    1 => Ok(Value::F32(variant_data.newtype_variant()?)),
464                    2 => Ok(Value::F64(variant_data.newtype_variant()?)),
465                    3 => Ok(Value::I8(variant_data.newtype_variant()?)),
466                    4 => Ok(Value::I16(variant_data.newtype_variant()?)),
467                    5 => Ok(Value::I32(variant_data.newtype_variant()?)),
468                    6 => Ok(Value::I64(variant_data.newtype_variant()?)),
469                    7 => Ok(Value::U8(variant_data.newtype_variant()?)),
470                    8 => Ok(Value::U16(variant_data.newtype_variant()?)),
471                    9 => Ok(Value::U32(variant_data.newtype_variant()?)),
472                    10 => Ok(Value::U64(variant_data.newtype_variant()?)),
473                    11 => Ok(Value::U128(variant_data.newtype_variant()?)),
474                    12 => Ok(Value::Boolean(variant_data.newtype_variant()?)),
475                    13 => Ok(Value::Array(variant_data.newtype_variant()?)),
476                    14 => Ok(Value::Object(variant_data.newtype_variant()?)),
477                    15 => {
478                        variant_data.unit_variant()?;
479                        Ok(Value::Empty)
480                    }
481                    _ => Err(serde::de::Error::invalid_value(
482                        serde::de::Unexpected::Unsigned(variant_idx as u64),
483                        &"variant index 0 through 5",
484                    )),
485                }
486            }
487        }
488
489        /// Helper deserialiser for handling numeric variant indices in binary format
490        struct VariantIdxDeserializer;
491
492        impl<'de> DeserializeSeed<'de> for VariantIdxDeserializer {
493            type Value = u32;
494            #[inline]
495            fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
496            where
497                D: Deserializer<'de>,
498            {
499                deserializer.deserialize_u32(self)
500            }
501        }
502
503        impl<'de> Visitor<'de> for VariantIdxDeserializer {
504            type Value = u32;
505
506            #[inline]
507            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
508                formatter.write_str("variant index")
509            }
510
511            #[inline]
512            fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
513            where
514                E: serde::de::Error,
515            {
516                Ok(v)
517            }
518        }
519        // Choose deserialisation strategy based on format
520        if deserializer.is_human_readable() {
521            // For JSON, accept any value type
522            deserializer.deserialize_any(ValueVisitor)
523        } else {
524            // For binary, use enum variant indices
525            deserializer.deserialize_enum(
526                "Value",
527                &[
528                    "String", "F32", "F64", "I8", "I16", "I32", "I64", "U8", "U16", "U32", "U64",
529                    "U128", "Boolean", "Array", "Object", "Empty",
530                ],
531                ValueVisitor,
532            )
533        }
534    }
535}
536
537/// Module for custom serialisation of property hashmaps
538/// Ensures consistent handling of Value enum serialisation within property maps
539pub mod properties_format {
540    use super::*;
541
542    #[inline]
543    pub fn serialize<S>(
544        properties: &Option<HashMap<String, Value>>,
545        serializer: S,
546    ) -> Result<S::Ok, S::Error>
547    where
548        S: Serializer,
549    {
550        match properties {
551            Some(properties) => {
552                use serde::ser::SerializeMap;
553                let mut map = serializer.serialize_map(Some(properties.len()))?;
554                for (k, v) in properties {
555                    map.serialize_entry(k, v)?;
556                }
557                map.end()
558            }
559            None => serializer.serialize_none(),
560        }
561    }
562
563    #[inline]
564    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<HashMap<String, Value>>, D::Error>
565    where
566        D: Deserializer<'de>,
567    {
568        match Option::<HashMap<String, Value>>::deserialize(deserializer) {
569            Ok(properties) => Ok(properties),
570            Err(e) => Err(e),
571        }
572    }
573}
574
575impl From<&str> for Value {
576    #[inline]
577    fn from(s: &str) -> Self {
578        Value::String(s.trim_matches('"').to_string())
579    }
580}
581
582impl From<String> for Value {
583    #[inline]
584    fn from(s: String) -> Self {
585        Value::String(s.trim_matches('"').to_string())
586    }
587}
588impl From<bool> for Value {
589    #[inline]
590    fn from(b: bool) -> Self {
591        Value::Boolean(b)
592    }
593}
594
595impl From<f32> for Value {
596    #[inline]
597    fn from(f: f32) -> Self {
598        Value::F32(f)
599    }
600}
601
602impl From<f64> for Value {
603    #[inline]
604    fn from(f: f64) -> Self {
605        Value::F64(f)
606    }
607}
608
609impl From<i8> for Value {
610    #[inline]
611    fn from(i: i8) -> Self {
612        Value::I8(i)
613    }
614}
615
616impl From<i16> for Value {
617    #[inline]
618    fn from(i: i16) -> Self {
619        Value::I16(i)
620    }
621}
622
623impl From<i32> for Value {
624    #[inline]
625    fn from(i: i32) -> Self {
626        Value::I32(i)
627    }
628}
629
630impl From<i64> for Value {
631    #[inline]
632    fn from(i: i64) -> Self {
633        Value::I64(i)
634    }
635}
636
637impl From<u8> for Value {
638    #[inline]
639    fn from(i: u8) -> Self {
640        Value::U8(i)
641    }
642}
643
644impl From<u16> for Value {
645    #[inline]
646    fn from(i: u16) -> Self {
647        Value::U16(i)
648    }
649}
650
651impl From<u32> for Value {
652    #[inline]
653    fn from(i: u32) -> Self {
654        Value::U32(i)
655    }
656}
657
658impl From<u64> for Value {
659    #[inline]
660    fn from(i: u64) -> Self {
661        Value::U64(i)
662    }
663}
664
665impl From<u128> for Value {
666    #[inline]
667    fn from(i: u128) -> Self {
668        Value::U128(i)
669    }
670}
671
672impl From<Vec<Value>> for Value {
673    #[inline]
674    fn from(v: Vec<Value>) -> Self {
675        Value::Array(v)
676    }
677}
678
679impl From<Vec<bool>> for Value {
680    #[inline(always)]
681    fn from(v: Vec<bool>) -> Self {
682        Value::Array(v.into_iter().map(|v| v.into()).collect())
683    }
684}
685
686impl From<Vec<String>> for Value {
687    #[inline(always)]
688    fn from(v: Vec<String>) -> Self {
689        Value::Array(v.into_iter().map(|v| v.into()).collect())
690    }
691}
692
693impl From<Vec<i64>> for Value {
694    #[inline(always)]
695    fn from(v: Vec<i64>) -> Self {
696        Value::Array(v.into_iter().map(|v| v.into()).collect())
697    }
698}
699
700impl From<Vec<i32>> for Value {
701    #[inline(always)]
702    fn from(v: Vec<i32>) -> Self {
703        Value::Array(v.into_iter().map(|v| v.into()).collect())
704    }
705}
706
707impl From<Vec<i16>> for Value {
708    #[inline(always)]
709    fn from(v: Vec<i16>) -> Self {
710        Value::Array(v.into_iter().map(|v| v.into()).collect())
711    }
712}
713
714impl From<Vec<i8>> for Value {
715    #[inline(always)]
716    fn from(v: Vec<i8>) -> Self {
717        Value::Array(v.into_iter().map(|v| v.into()).collect())
718    }
719}
720
721impl From<Vec<u128>> for Value {
722    #[inline(always)]
723    fn from(v: Vec<u128>) -> Self {
724        Value::Array(v.into_iter().map(|v| v.into()).collect())
725    }
726}
727
728impl From<Vec<u64>> for Value {
729    #[inline(always)]
730    fn from(v: Vec<u64>) -> Self {
731        Value::Array(v.into_iter().map(|v| v.into()).collect())
732    }
733}
734
735impl From<Vec<u32>> for Value {
736    #[inline(always)]
737    fn from(v: Vec<u32>) -> Self {
738        Value::Array(v.into_iter().map(|v| v.into()).collect())
739    }
740}
741
742impl From<Vec<u16>> for Value {
743    #[inline(always)]
744    fn from(v: Vec<u16>) -> Self {
745        Value::Array(v.into_iter().map(|v| v.into()).collect())
746    }
747}
748
749impl From<Vec<u8>> for Value {
750    #[inline(always)]
751    fn from(v: Vec<u8>) -> Self {
752        Value::Array(v.into_iter().map(|v| v.into()).collect())
753    }
754}
755
756impl From<Vec<f64>> for Value {
757    #[inline(always)]
758    fn from(v: Vec<f64>) -> Self {
759        Value::Array(v.into_iter().map(|v| v.into()).collect())
760    }
761}
762
763impl From<Vec<f32>> for Value {
764    #[inline(always)]
765    fn from(v: Vec<f32>) -> Self {
766        Value::Array(v.into_iter().map(|v| v.into()).collect())
767    }
768}
769
770impl From<usize> for Value {
771    #[inline]
772    fn from(v: usize) -> Self {
773        if cfg!(target_pointer_width = "64") {
774            Value::U64(v as u64)
775        } else {
776            Value::U128(v as u128)
777        }
778    }
779}
780
781impl From<Value> for String {
782    #[inline]
783    fn from(v: Value) -> Self {
784        match v {
785            Value::String(s) => s,
786            _ => panic!("Value is not a string"),
787        }
788    }
789}
790impl From<JsonValue> for Value {
791    #[inline]
792    fn from(v: JsonValue) -> Self {
793        match v {
794            JsonValue::String(s) => Value::String(s),
795            JsonValue::Number(n) => {
796                if n.is_u64() {
797                    Value::U64(n.as_u64().unwrap() as u64)
798                } else if n.is_i64() {
799                    Value::I64(n.as_i64().unwrap())
800                } else {
801                    Value::F64(n.as_f64().unwrap())
802                }
803            }
804            JsonValue::Bool(b) => Value::Boolean(b),
805            JsonValue::Array(a) => Value::Array(a.into_iter().map(|v| v.into()).collect()),
806            JsonValue::Object(o) => {
807                Value::Object(o.into_iter().map(|(k, v)| (k, v.into())).collect())
808            }
809            JsonValue::Null => Value::Empty,
810        }
811    }
812}
813
814impl From<ID> for Value {
815    #[inline]
816    fn from(id: ID) -> Self {
817        Value::String(id.to_string())
818    }
819}
820
821impl<'a, K> From<&'a K> for Value
822where
823    K: Into<Value> + Serialize + Clone,
824{
825    #[inline]
826    fn from(k: &'a K) -> Self {
827        Value::from(k.clone().into())
828    }
829}
830
831impl From<chrono::DateTime<Utc>> for Value {
832    #[inline]
833    fn from(dt: chrono::DateTime<Utc>) -> Self {
834        Value::String(dt.to_rfc3339())
835    }
836}
837
838pub trait Encodings {
839    fn decode_properties(bytes: &[u8]) -> Result<HashMap<String, Value>, GraphError>;
840    fn encode_properties(&self) -> Result<Vec<u8>, GraphError>;
841}
842
843impl Encodings for HashMap<String, Value> {
844    fn decode_properties(bytes: &[u8]) -> Result<HashMap<String, Value>, GraphError> {
845        match bincode::deserialize(bytes) {
846            Ok(properties) => Ok(properties),
847            Err(e) => Err(GraphError::ConversionError(format!(
848                "Error deserializing properties: {}",
849                e
850            ))),
851        }
852    }
853
854    fn encode_properties(&self) -> Result<Vec<u8>, GraphError> {
855        match bincode::serialize(self) {
856            Ok(bytes) => Ok(bytes),
857            Err(e) => Err(GraphError::ConversionError(format!(
858                "Error serializing properties: {}",
859                e
860            ))),
861        }
862    }
863}
864
865impl From<Value> for GenRef<String> {
866    fn from(v: Value) -> Self {
867        match v {
868            Value::String(s) => GenRef::Literal(s),
869            Value::I8(i) => GenRef::Std(format!("{}", i)),
870            Value::I16(i) => GenRef::Std(format!("{}", i)),
871            Value::I32(i) => GenRef::Std(format!("{}", i)),
872            Value::I64(i) => GenRef::Std(format!("{}", i)),
873            Value::F32(f) => GenRef::Std(format!("{:?}", f)), // {:?} forces decimal point
874            Value::F64(f) => GenRef::Std(format!("{:?}", f)),
875            Value::Boolean(b) => GenRef::Std(format!("{}", b)),
876            Value::U8(u) => GenRef::Std(format!("{}", u)),
877            Value::U16(u) => GenRef::Std(format!("{}", u)),
878            Value::U32(u) => GenRef::Std(format!("{}", u)),
879            Value::U64(u) => GenRef::Std(format!("{}", u)),
880            Value::U128(u) => GenRef::Std(format!("{}", u)),
881            Value::Array(_a) => unimplemented!(),
882            Value::Object(_o) => unimplemented!(),
883            Value::Empty => GenRef::Literal("".to_string()),
884        }
885    }
886}