Skip to main content

geode_client/
types.rs

1//! Type system for Geode values.
2
3use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
4use rust_decimal::Decimal;
5use std::collections::HashMap;
6
7use crate::error::{Error, Result};
8
9/// Default maximum JSON nesting depth when decoding values
10pub const DEFAULT_MAX_JSON_DEPTH: usize = 64;
11
12/// Kind of value
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum ValueKind {
15    Null,
16    Int,
17    Bool,
18    String,
19    Decimal,
20    Array,
21    Object,
22    Bytea,
23    Date,
24    Time,
25    TimeTz,
26    Timestamp,
27    TimestampTz,
28    Interval,
29    Json,
30    Jsonb,
31    Xml,
32    Url,
33    Domain,
34    Uuid,
35    Enum,
36    BitString,
37    Range,
38    Node,
39    Edge,
40    Path,
41}
42
43/// A graph node value.
44#[derive(Debug, Clone, PartialEq)]
45pub struct Node {
46    pub id: i64,
47    pub labels: Vec<String>,
48    pub properties: HashMap<String, Value>,
49}
50
51/// A graph edge (relationship) value.
52#[derive(Debug, Clone, PartialEq)]
53pub struct Edge {
54    pub id: i64,
55    pub start_node: i64,
56    pub end_node: i64,
57    pub edge_type: String,
58    pub properties: HashMap<String, Value>,
59}
60
61/// A graph path value (alternating nodes and edges).
62#[derive(Debug, Clone, PartialEq)]
63pub struct Path {
64    pub nodes: Vec<Node>,
65    pub edges: Vec<Edge>,
66}
67
68/// Range type value
69#[derive(Debug, Clone, PartialEq)]
70pub struct Range {
71    pub lower: Option<Box<Value>>,
72    pub upper: Option<Box<Value>>,
73    pub bounds: String,
74}
75
76/// Native representation of Geode values
77#[derive(Debug, Clone, PartialEq)]
78pub struct Value {
79    pub kind: ValueKind,
80    int_value: i64,
81    bool_value: bool,
82    string_value: String,
83    decimal_value: Option<Decimal>,
84    #[allow(dead_code)] // Reserved for future decimal scale support
85    decimal_scale: String,
86    array_value: Vec<Value>,
87    object_value: HashMap<String, Value>,
88    bytes_value: Vec<u8>,
89    date_value: Option<NaiveDate>,
90    #[allow(dead_code)] // Reserved for future time type support
91    time_value: Option<NaiveTime>,
92    timestamp_value: Option<DateTime<Utc>>,
93    range_value: Option<Range>,
94    node_value: Option<Box<Node>>,
95    edge_value: Option<Box<Edge>>,
96    path_value: Option<Box<Path>>,
97}
98
99impl Value {
100    /// Create a NULL value
101    #[inline]
102    pub fn null() -> Self {
103        Self {
104            kind: ValueKind::Null,
105            int_value: 0,
106            bool_value: false,
107            string_value: String::new(),
108            decimal_value: None,
109            decimal_scale: String::new(),
110            array_value: Vec::new(),
111            object_value: HashMap::new(),
112            bytes_value: Vec::new(),
113            date_value: None,
114            time_value: None,
115            timestamp_value: None,
116            range_value: None,
117            node_value: None,
118            edge_value: None,
119            path_value: None,
120        }
121    }
122
123    /// Create an INT value
124    #[inline]
125    pub fn int(value: i64) -> Self {
126        Self {
127            kind: ValueKind::Int,
128            int_value: value,
129            ..Self::null()
130        }
131    }
132
133    /// Create a BOOL value
134    #[inline]
135    pub fn bool(value: bool) -> Self {
136        Self {
137            kind: ValueKind::Bool,
138            bool_value: value,
139            ..Self::null()
140        }
141    }
142
143    /// Create a STRING value
144    #[inline]
145    pub fn string<S: Into<String>>(value: S) -> Self {
146        Self {
147            kind: ValueKind::String,
148            string_value: value.into(),
149            ..Self::null()
150        }
151    }
152
153    /// Create a DECIMAL value
154    #[inline]
155    pub fn decimal(value: Decimal) -> Self {
156        Self {
157            kind: ValueKind::Decimal,
158            decimal_value: Some(value),
159            ..Self::null()
160        }
161    }
162
163    /// Create an ARRAY value
164    #[inline]
165    pub fn array(values: Vec<Value>) -> Self {
166        Self {
167            kind: ValueKind::Array,
168            array_value: values,
169            ..Self::null()
170        }
171    }
172
173    /// Create an OBJECT value
174    #[inline]
175    pub fn object(values: HashMap<String, Value>) -> Self {
176        Self {
177            kind: ValueKind::Object,
178            object_value: values,
179            ..Self::null()
180        }
181    }
182
183    /// Create a NODE value.
184    pub fn node(node: Node) -> Self {
185        Self {
186            kind: ValueKind::Node,
187            node_value: Some(Box::new(node)),
188            ..Self::null()
189        }
190    }
191
192    /// Create an EDGE value.
193    pub fn edge(edge: Edge) -> Self {
194        Self {
195            kind: ValueKind::Edge,
196            edge_value: Some(Box::new(edge)),
197            ..Self::null()
198        }
199    }
200
201    /// Create a PATH value.
202    pub fn path(path: Path) -> Self {
203        Self {
204            kind: ValueKind::Path,
205            path_value: Some(Box::new(path)),
206            ..Self::null()
207        }
208    }
209
210    /// Check if value is NULL
211    #[inline]
212    pub fn is_null(&self) -> bool {
213        self.kind == ValueKind::Null
214    }
215
216    /// Get as integer
217    #[inline]
218    pub fn as_int(&self) -> Result<i64> {
219        if self.kind == ValueKind::Int {
220            Ok(self.int_value)
221        } else {
222            Err(Error::type_error(format!(
223                "Cannot convert {:?} to int",
224                self.kind
225            )))
226        }
227    }
228
229    /// Get as boolean
230    #[inline]
231    pub fn as_bool(&self) -> Result<bool> {
232        if self.kind == ValueKind::Bool {
233            Ok(self.bool_value)
234        } else {
235            Err(Error::type_error(format!(
236                "Cannot convert {:?} to bool",
237                self.kind
238            )))
239        }
240    }
241
242    /// Get as string
243    #[inline]
244    pub fn as_string(&self) -> Result<&str> {
245        match self.kind {
246            ValueKind::String
247            | ValueKind::Xml
248            | ValueKind::Json
249            | ValueKind::Jsonb
250            | ValueKind::Url
251            | ValueKind::Domain
252            | ValueKind::Uuid
253            | ValueKind::Enum
254            | ValueKind::BitString => Ok(&self.string_value),
255            _ => Err(Error::type_error(format!(
256                "Cannot convert {:?} to string",
257                self.kind
258            ))),
259        }
260    }
261
262    /// Get as decimal
263    #[inline]
264    pub fn as_decimal(&self) -> Result<Decimal> {
265        if self.kind == ValueKind::Decimal {
266            self.decimal_value
267                .ok_or_else(|| Error::type_error("Decimal value is None"))
268        } else {
269            Err(Error::type_error(format!(
270                "Cannot convert {:?} to decimal",
271                self.kind
272            )))
273        }
274    }
275
276    /// Get as array
277    #[inline]
278    pub fn as_array(&self) -> Result<&[Value]> {
279        if self.kind == ValueKind::Array {
280            Ok(&self.array_value)
281        } else {
282            Err(Error::type_error(format!(
283                "Cannot convert {:?} to array",
284                self.kind
285            )))
286        }
287    }
288
289    /// Get as object
290    #[inline]
291    pub fn as_object(&self) -> Result<&HashMap<String, Value>> {
292        if self.kind == ValueKind::Object {
293            Ok(&self.object_value)
294        } else {
295            Err(Error::type_error(format!(
296                "Cannot convert {:?} to object",
297                self.kind
298            )))
299        }
300    }
301
302    /// Get as bytes
303    pub fn as_bytes(&self) -> Result<&[u8]> {
304        if self.kind == ValueKind::Bytea {
305            Ok(&self.bytes_value)
306        } else {
307            Err(Error::type_error(format!(
308                "Cannot convert {:?} to bytes",
309                self.kind
310            )))
311        }
312    }
313
314    /// Get as date
315    pub fn as_date(&self) -> Result<NaiveDate> {
316        if self.kind == ValueKind::Date {
317            self.date_value
318                .ok_or_else(|| Error::type_error("Date value is None"))
319        } else {
320            Err(Error::type_error(format!(
321                "Cannot convert {:?} to date",
322                self.kind
323            )))
324        }
325    }
326
327    /// Get as timestamp
328    pub fn as_timestamp(&self) -> Result<DateTime<Utc>> {
329        if self.kind == ValueKind::Timestamp || self.kind == ValueKind::TimestampTz {
330            self.timestamp_value
331                .ok_or_else(|| Error::type_error("Timestamp value is None"))
332        } else {
333            Err(Error::type_error(format!(
334                "Cannot convert {:?} to timestamp",
335                self.kind
336            )))
337        }
338    }
339
340    /// Get as range
341    pub fn as_range(&self) -> Result<&Range> {
342        if self.kind == ValueKind::Range {
343            self.range_value
344                .as_ref()
345                .ok_or_else(|| Error::type_error("Range value is None"))
346        } else {
347            Err(Error::type_error(format!(
348                "Cannot convert {:?} to range",
349                self.kind
350            )))
351        }
352    }
353
354    /// Get as a graph node.
355    pub fn as_node(&self) -> Result<&Node> {
356        if self.kind == ValueKind::Node {
357            self.node_value
358                .as_deref()
359                .ok_or_else(|| Error::type_error("Node value is None"))
360        } else {
361            Err(Error::type_error(format!(
362                "Cannot convert {:?} to node",
363                self.kind
364            )))
365        }
366    }
367
368    /// Get as a graph edge.
369    pub fn as_edge(&self) -> Result<&Edge> {
370        if self.kind == ValueKind::Edge {
371            self.edge_value
372                .as_deref()
373                .ok_or_else(|| Error::type_error("Edge value is None"))
374        } else {
375            Err(Error::type_error(format!(
376                "Cannot convert {:?} to edge",
377                self.kind
378            )))
379        }
380    }
381
382    /// Get as a graph path.
383    pub fn as_path(&self) -> Result<&Path> {
384        if self.kind == ValueKind::Path {
385            self.path_value
386                .as_deref()
387                .ok_or_else(|| Error::type_error("Path value is None"))
388        } else {
389            Err(Error::type_error(format!(
390                "Cannot convert {:?} to path",
391                self.kind
392            )))
393        }
394    }
395
396    /// Convert to serde_json::Value for serialization
397    pub fn to_json(&self) -> serde_json::Value {
398        match self.kind {
399            ValueKind::Null => serde_json::Value::Null,
400            ValueKind::Int => serde_json::Value::Number(self.int_value.into()),
401            ValueKind::Bool => serde_json::Value::Bool(self.bool_value),
402            ValueKind::String
403            | ValueKind::Xml
404            | ValueKind::Json
405            | ValueKind::Jsonb
406            | ValueKind::Url
407            | ValueKind::Domain
408            | ValueKind::Uuid
409            | ValueKind::Enum
410            | ValueKind::BitString => serde_json::Value::String(self.string_value.clone()),
411            ValueKind::Decimal => serde_json::Value::String(
412                self.decimal_value
413                    .map(|d| d.to_string())
414                    .unwrap_or_default(),
415            ),
416            ValueKind::Array => {
417                serde_json::Value::Array(self.array_value.iter().map(|v| v.to_json()).collect())
418            }
419            ValueKind::Object => {
420                let mut map = serde_json::Map::new();
421                for (k, v) in &self.object_value {
422                    map.insert(k.clone(), v.to_json());
423                }
424                serde_json::Value::Object(map)
425            }
426            ValueKind::Bytea => {
427                if self.bytes_value.is_empty() {
428                    serde_json::Value::String(self.string_value.clone())
429                } else {
430                    serde_json::Value::String(format!("\\x{}", hex::encode(&self.bytes_value)))
431                }
432            }
433            ValueKind::Date
434            | ValueKind::Time
435            | ValueKind::TimeTz
436            | ValueKind::Timestamp
437            | ValueKind::TimestampTz
438            | ValueKind::Interval => serde_json::Value::String(self.string_value.clone()),
439            ValueKind::Range => {
440                if let Some(range) = &self.range_value {
441                    let mut map = serde_json::Map::new();
442                    if let Some(lower) = &range.lower {
443                        map.insert("lower".to_string(), lower.to_json());
444                    }
445                    if let Some(upper) = &range.upper {
446                        map.insert("upper".to_string(), upper.to_json());
447                    }
448                    map.insert(
449                        "bounds".to_string(),
450                        serde_json::Value::String(range.bounds.clone()),
451                    );
452                    serde_json::Value::Object(map)
453                } else {
454                    serde_json::Value::Null
455                }
456            }
457            ValueKind::Node => {
458                let mut map = serde_json::Map::new();
459                if let Some(n) = &self.node_value {
460                    map.insert("id".into(), serde_json::Value::Number(n.id.into()));
461                    map.insert(
462                        "labels".into(),
463                        serde_json::Value::Array(
464                            n.labels
465                                .iter()
466                                .cloned()
467                                .map(serde_json::Value::String)
468                                .collect(),
469                        ),
470                    );
471                    let mut props = serde_json::Map::new();
472                    for (k, v) in &n.properties {
473                        props.insert(k.clone(), v.to_json());
474                    }
475                    map.insert("properties".into(), serde_json::Value::Object(props));
476                }
477                serde_json::Value::Object(map)
478            }
479            ValueKind::Edge => {
480                let mut map = serde_json::Map::new();
481                if let Some(e) = &self.edge_value {
482                    map.insert("id".into(), serde_json::Value::Number(e.id.into()));
483                    map.insert(
484                        "start_node".into(),
485                        serde_json::Value::Number(e.start_node.into()),
486                    );
487                    map.insert(
488                        "end_node".into(),
489                        serde_json::Value::Number(e.end_node.into()),
490                    );
491                    map.insert(
492                        "type".into(),
493                        serde_json::Value::String(e.edge_type.clone()),
494                    );
495                    let mut props = serde_json::Map::new();
496                    for (k, v) in &e.properties {
497                        props.insert(k.clone(), v.to_json());
498                    }
499                    map.insert("properties".into(), serde_json::Value::Object(props));
500                }
501                serde_json::Value::Object(map)
502            }
503            ValueKind::Path => {
504                let mut map = serde_json::Map::new();
505                if let Some(p) = &self.path_value {
506                    map.insert(
507                        "nodes".into(),
508                        serde_json::Value::Array(
509                            p.nodes
510                                .iter()
511                                .map(|n| Value::node(n.clone()).to_json())
512                                .collect(),
513                        ),
514                    );
515                    map.insert(
516                        "edges".into(),
517                        serde_json::Value::Array(
518                            p.edges
519                                .iter()
520                                .map(|e| Value::edge(e.clone()).to_json())
521                                .collect(),
522                        ),
523                    );
524                }
525                serde_json::Value::Object(map)
526            }
527        }
528    }
529
530    /// Convert to a proto::Value for protobuf parameter encoding
531    pub fn to_proto_value(&self) -> crate::proto::Value {
532        use crate::proto::{self, value};
533        match self.kind {
534            ValueKind::Null => proto::Value {
535                kind: Some(value::Kind::NullVal(proto::NullValue {})),
536            },
537            ValueKind::Int => proto::Value {
538                kind: Some(value::Kind::IntVal(proto::IntValue {
539                    value: self.int_value,
540                    kind: 0,
541                })),
542            },
543            ValueKind::Bool => proto::Value {
544                kind: Some(value::Kind::BoolVal(self.bool_value)),
545            },
546            ValueKind::Decimal => {
547                let double_val = self
548                    .decimal_value
549                    .and_then(|d| {
550                        use std::str::FromStr;
551                        f64::from_str(&d.to_string()).ok()
552                    })
553                    .unwrap_or(0.0);
554                proto::Value {
555                    kind: Some(value::Kind::DoubleVal(proto::DoubleValue {
556                        value: double_val,
557                        kind: 0,
558                    })),
559                }
560            }
561            _ => proto::Value {
562                kind: Some(value::Kind::StringVal(proto::StringValue {
563                    value: self.to_proto_string(),
564                    kind: 0,
565                })),
566            },
567        }
568    }
569
570    /// Convert to a string representation for protobuf parameters
571    pub fn to_proto_string(&self) -> String {
572        match self.kind {
573            ValueKind::Null => String::new(),
574            ValueKind::Int => self.int_value.to_string(),
575            ValueKind::Bool => self.bool_value.to_string(),
576            ValueKind::String
577            | ValueKind::Xml
578            | ValueKind::Json
579            | ValueKind::Jsonb
580            | ValueKind::Url
581            | ValueKind::Domain
582            | ValueKind::Uuid
583            | ValueKind::Enum
584            | ValueKind::BitString => self.string_value.clone(),
585            ValueKind::Decimal => self
586                .decimal_value
587                .map(|d| d.to_string())
588                .unwrap_or_default(),
589            ValueKind::Array => serde_json::to_string(&self.to_json()).unwrap_or_default(),
590            ValueKind::Object => serde_json::to_string(&self.to_json()).unwrap_or_default(),
591            ValueKind::Bytea => {
592                if self.bytes_value.is_empty() {
593                    self.string_value.clone()
594                } else {
595                    format!("\\x{}", hex::encode(&self.bytes_value))
596                }
597            }
598            ValueKind::Date
599            | ValueKind::Time
600            | ValueKind::TimeTz
601            | ValueKind::Timestamp
602            | ValueKind::TimestampTz
603            | ValueKind::Interval => self.string_value.clone(),
604            ValueKind::Range => serde_json::to_string(&self.to_json()).unwrap_or_default(),
605            ValueKind::Node | ValueKind::Edge | ValueKind::Path => {
606                serde_json::to_string(&self.to_json()).unwrap_or_default()
607            }
608        }
609    }
610
611    /// Create a Value from a serde_json::Value using the default depth limit.
612    ///
613    /// # Errors
614    ///
615    /// Returns an error if the JSON nesting depth exceeds [`DEFAULT_MAX_JSON_DEPTH`].
616    pub fn from_json(json: serde_json::Value) -> Result<Self> {
617        Self::from_json_with_max_depth(json, DEFAULT_MAX_JSON_DEPTH)
618    }
619
620    /// Create a Value from a serde_json::Value with an explicit depth limit.
621    ///
622    /// # Errors
623    ///
624    /// Returns an error if the JSON nesting depth exceeds `max_depth`.
625    pub fn from_json_with_max_depth(json: serde_json::Value, max_depth: usize) -> Result<Self> {
626        Self::from_json_with_depth(json, 0, max_depth)
627    }
628
629    fn from_json_with_depth(
630        json: serde_json::Value,
631        depth: usize,
632        max_depth: usize,
633    ) -> Result<Self> {
634        if depth >= max_depth {
635            return Err(Error::limit(format!(
636                "JSON nesting depth {} exceeds max {}",
637                depth, max_depth
638            )));
639        }
640
641        match json {
642            serde_json::Value::Null => Ok(Self::null()),
643            serde_json::Value::Bool(b) => Ok(Self::bool(b)),
644            serde_json::Value::Number(n) => {
645                if let Some(i) = n.as_i64() {
646                    Ok(Self::int(i))
647                } else if let Some(f) = n.as_f64() {
648                    // Try to convert to decimal
649                    Ok(Self::string(f.to_string()))
650                } else {
651                    Ok(Self::null())
652                }
653            }
654            serde_json::Value::String(s) => Ok(Self::string(s)),
655            serde_json::Value::Array(arr) => {
656                let values: Result<Vec<Value>> = arr
657                    .into_iter()
658                    .map(|v| Self::from_json_with_depth(v, depth + 1, max_depth))
659                    .collect();
660                Ok(Self::array(values?))
661            }
662            serde_json::Value::Object(obj) => {
663                let mut map = HashMap::new();
664                for (k, v) in obj {
665                    map.insert(k, Self::from_json_with_depth(v, depth + 1, max_depth)?);
666                }
667                Ok(Self::object(map))
668            }
669        }
670    }
671}
672
673/// Decode a JSON value into a typed Value object using the default depth limit.
674///
675/// Returns an error if the JSON nesting depth exceeds [`DEFAULT_MAX_JSON_DEPTH`].
676pub fn decode_value(raw: &serde_json::Value, type_name: &str) -> Result<Value> {
677    decode_value_with_max_depth(raw, type_name, DEFAULT_MAX_JSON_DEPTH)
678}
679
680/// Decode a JSON value into a typed Value object with a specific depth limit.
681pub fn decode_value_with_max_depth(
682    raw: &serde_json::Value,
683    type_name: &str,
684    max_depth: usize,
685) -> Result<Value> {
686    decode_value_with_depth(raw, type_name, 0, max_depth)
687}
688
689fn decode_value_with_depth(
690    raw: &serde_json::Value,
691    type_name: &str,
692    depth: usize,
693    max_depth: usize,
694) -> Result<Value> {
695    if depth >= max_depth {
696        return Err(Error::limit(format!(
697            "JSON nesting depth {} exceeds max {}",
698            depth, max_depth
699        )));
700    }
701
702    if raw.is_null() {
703        return Ok(Value::null());
704    }
705
706    if type_name.eq_ignore_ascii_case("INT") {
707        if let Some(n) = raw.as_i64() {
708            Ok(Value::int(n))
709        } else if let Some(s) = raw.as_str() {
710            if let Ok(n) = s.parse::<i64>() {
711                Ok(Value::int(n))
712            } else {
713                Ok(Value::string(s))
714            }
715        } else {
716            Ok(Value::string(raw.to_string()))
717        }
718    } else if type_name.eq_ignore_ascii_case("DECIMAL") {
719        let s = raw
720            .as_str()
721            .map(|v| v.to_string())
722            .unwrap_or_else(|| raw.to_string());
723        if let Ok(dec) = s.parse::<Decimal>() {
724            Ok(Value::decimal(dec))
725        } else {
726            Ok(Value::string(s))
727        }
728    } else if type_name.eq_ignore_ascii_case("BOOL") {
729        if let Some(b) = raw.as_bool() {
730            Ok(Value::bool(b))
731        } else if let Some(s) = raw.as_str() {
732            let lower = s.to_ascii_lowercase();
733            if lower == "true" {
734                Ok(Value::bool(true))
735            } else if lower == "false" {
736                Ok(Value::bool(false))
737            } else {
738                Ok(Value::string(s))
739            }
740        } else {
741            Ok(Value::string(raw.to_string()))
742        }
743    } else if type_name.eq_ignore_ascii_case("STRING") {
744        Ok(Value::string(raw.as_str().unwrap_or("")))
745    } else if type_name.eq_ignore_ascii_case("BYTEA") {
746        let s = raw.as_str().unwrap_or("");
747        let bytes = if let Some(hex_str) = s.strip_prefix("\\x") {
748            hex::decode(hex_str).unwrap_or_default()
749        } else {
750            Vec::new()
751        };
752        Ok(Value {
753            kind: ValueKind::Bytea,
754            bytes_value: bytes,
755            string_value: s.to_string(),
756            ..Value::null()
757        })
758    } else if type_name.eq_ignore_ascii_case("JSON") {
759        Ok(Value {
760            kind: ValueKind::Json,
761            string_value: raw.to_string(),
762            ..Value::null()
763        })
764    } else if type_name.eq_ignore_ascii_case("JSONB") {
765        Ok(Value {
766            kind: ValueKind::Jsonb,
767            string_value: raw.to_string(),
768            ..Value::null()
769        })
770    } else if type_name.eq_ignore_ascii_case("DATE") {
771        let s = raw.as_str().unwrap_or("");
772        let date = NaiveDate::parse_from_str(s, "%Y-%m-%d").ok();
773        Ok(Value {
774            kind: ValueKind::Date,
775            string_value: s.to_string(),
776            date_value: date,
777            ..Value::null()
778        })
779    } else if type_name.eq_ignore_ascii_case("TIMESTAMP")
780        || type_name.eq_ignore_ascii_case("TIMESTAMPTZ")
781    {
782        let s = raw.as_str().unwrap_or("");
783        let timestamp = DateTime::parse_from_rfc3339(s)
784            .ok()
785            .map(|dt| dt.with_timezone(&Utc));
786        let kind = if type_name.eq_ignore_ascii_case("TIMESTAMPTZ") {
787            ValueKind::TimestampTz
788        } else {
789            ValueKind::Timestamp
790        };
791        Ok(Value {
792            kind,
793            string_value: s.to_string(),
794            timestamp_value: timestamp,
795            ..Value::null()
796        })
797    } else if type_name.to_ascii_uppercase().contains("RANGE") {
798        if let Some(obj) = raw.as_object() {
799            let range = Range {
800                lower: obj.get("lower").and_then(|v| {
801                    decode_value_with_depth(v, "", depth + 1, max_depth)
802                        .ok()
803                        .map(Box::new)
804                }),
805                upper: obj.get("upper").and_then(|v| {
806                    decode_value_with_depth(v, "", depth + 1, max_depth)
807                        .ok()
808                        .map(Box::new)
809                }),
810                bounds: obj
811                    .get("bounds")
812                    .and_then(|v| v.as_str())
813                    .unwrap_or("")
814                    .to_string(),
815            };
816            Ok(Value {
817                kind: ValueKind::Range,
818                range_value: Some(range),
819                ..Value::null()
820            })
821        } else {
822            Ok(Value::string(raw.to_string()))
823        }
824    } else {
825        // Handle arrays and objects generically
826        if let Some(arr) = raw.as_array() {
827            let values: Result<Vec<_>> = arr
828                .iter()
829                .map(|v| decode_value_with_depth(v, "", depth + 1, max_depth))
830                .collect();
831            Ok(Value::array(values?))
832        } else if let Some(obj) = raw.as_object() {
833            let mut map = HashMap::new();
834            for (k, v) in obj {
835                map.insert(
836                    k.clone(),
837                    decode_value_with_depth(v, "", depth + 1, max_depth)?,
838                );
839            }
840            Ok(Value::object(map))
841        } else if let Some(b) = raw.as_bool() {
842            Ok(Value::bool(b))
843        } else if let Some(n) = raw.as_i64() {
844            Ok(Value::int(n))
845        } else if let Some(f) = raw.as_f64() {
846            let s = f.to_string();
847            if let Ok(dec) = s.parse::<Decimal>() {
848                Ok(Value::decimal(dec))
849            } else {
850                Ok(Value::string(s))
851            }
852        } else if let Some(s) = raw.as_str() {
853            Ok(Value::string(s))
854        } else {
855            Ok(Value::string(raw.to_string()))
856        }
857    }
858}
859
860#[cfg(test)]
861mod tests {
862    use super::*;
863    use chrono::{Datelike, Timelike};
864    use rust_decimal_macros::dec;
865    use serde_json::json;
866
867    // ==================== ValueKind Tests ====================
868
869    #[test]
870    fn test_value_kind_equality() {
871        assert_eq!(ValueKind::Null, ValueKind::Null);
872        assert_eq!(ValueKind::Int, ValueKind::Int);
873        assert_ne!(ValueKind::Int, ValueKind::String);
874    }
875
876    #[test]
877    fn test_value_kind_copy() {
878        let kind = ValueKind::Int;
879        let kind_copy = kind;
880        assert_eq!(kind, kind_copy);
881    }
882
883    #[test]
884    fn test_value_kind_debug() {
885        let debug_str = format!("{:?}", ValueKind::Timestamp);
886        assert_eq!(debug_str, "Timestamp");
887    }
888
889    #[test]
890    fn test_value_kind_all_variants() {
891        // Ensure all variants exist and are distinct
892        let variants = [
893            ValueKind::Null,
894            ValueKind::Int,
895            ValueKind::Bool,
896            ValueKind::String,
897            ValueKind::Decimal,
898            ValueKind::Array,
899            ValueKind::Object,
900            ValueKind::Bytea,
901            ValueKind::Date,
902            ValueKind::Time,
903            ValueKind::TimeTz,
904            ValueKind::Timestamp,
905            ValueKind::TimestampTz,
906            ValueKind::Interval,
907            ValueKind::Json,
908            ValueKind::Jsonb,
909            ValueKind::Xml,
910            ValueKind::Url,
911            ValueKind::Domain,
912            ValueKind::Uuid,
913            ValueKind::Enum,
914            ValueKind::BitString,
915            ValueKind::Range,
916            ValueKind::Node,
917            ValueKind::Edge,
918            ValueKind::Path,
919        ];
920        assert_eq!(variants.len(), 26);
921        // Check uniqueness
922        for i in 0..variants.len() {
923            for j in (i + 1)..variants.len() {
924                assert_ne!(variants[i], variants[j]);
925            }
926        }
927    }
928
929    // ==================== Value Construction Tests ====================
930
931    #[test]
932    fn test_value_null() {
933        let v = Value::null();
934        assert_eq!(v.kind, ValueKind::Null);
935        assert!(v.is_null());
936    }
937
938    #[test]
939    fn test_value_int() {
940        let v = Value::int(42);
941        assert_eq!(v.kind, ValueKind::Int);
942        assert!(!v.is_null());
943        assert_eq!(v.as_int().unwrap(), 42);
944    }
945
946    #[test]
947    fn test_value_int_negative() {
948        let v = Value::int(-100);
949        assert_eq!(v.as_int().unwrap(), -100);
950    }
951
952    #[test]
953    fn test_value_int_zero() {
954        let v = Value::int(0);
955        assert_eq!(v.as_int().unwrap(), 0);
956    }
957
958    #[test]
959    fn test_value_int_max() {
960        let v = Value::int(i64::MAX);
961        assert_eq!(v.as_int().unwrap(), i64::MAX);
962    }
963
964    #[test]
965    fn test_value_int_min() {
966        let v = Value::int(i64::MIN);
967        assert_eq!(v.as_int().unwrap(), i64::MIN);
968    }
969
970    #[test]
971    fn test_value_bool_true() {
972        let v = Value::bool(true);
973        assert_eq!(v.kind, ValueKind::Bool);
974        assert!(v.as_bool().unwrap());
975    }
976
977    #[test]
978    fn test_value_bool_false() {
979        let v = Value::bool(false);
980        assert!(!v.as_bool().unwrap());
981    }
982
983    #[test]
984    fn test_value_string() {
985        let v = Value::string("hello");
986        assert_eq!(v.kind, ValueKind::String);
987        assert_eq!(v.as_string().unwrap(), "hello");
988    }
989
990    #[test]
991    fn test_value_string_empty() {
992        let v = Value::string("");
993        assert_eq!(v.as_string().unwrap(), "");
994    }
995
996    #[test]
997    fn test_value_string_unicode() {
998        let v = Value::string("こんにちは世界🌍");
999        assert_eq!(v.as_string().unwrap(), "こんにちは世界🌍");
1000    }
1001
1002    #[test]
1003    fn test_value_string_owned() {
1004        let owned = String::from("owned string");
1005        let v = Value::string(owned);
1006        assert_eq!(v.as_string().unwrap(), "owned string");
1007    }
1008
1009    #[test]
1010    fn test_value_decimal() {
1011        let v = Value::decimal(dec!(123.456));
1012        assert_eq!(v.kind, ValueKind::Decimal);
1013        assert_eq!(v.as_decimal().unwrap(), dec!(123.456));
1014    }
1015
1016    #[test]
1017    fn test_value_decimal_precision() {
1018        let v = Value::decimal(dec!(0.000000001));
1019        assert_eq!(v.as_decimal().unwrap(), dec!(0.000000001));
1020    }
1021
1022    #[test]
1023    fn test_value_decimal_large() {
1024        let v = Value::decimal(dec!(99999999999999.99));
1025        assert_eq!(v.as_decimal().unwrap(), dec!(99999999999999.99));
1026    }
1027
1028    #[test]
1029    fn test_value_array_empty() {
1030        let v = Value::array(vec![]);
1031        assert_eq!(v.kind, ValueKind::Array);
1032        assert!(v.as_array().unwrap().is_empty());
1033    }
1034
1035    #[test]
1036    fn test_value_array() {
1037        let v = Value::array(vec![Value::int(1), Value::int(2), Value::int(3)]);
1038        let arr = v.as_array().unwrap();
1039        assert_eq!(arr.len(), 3);
1040        assert_eq!(arr[0].as_int().unwrap(), 1);
1041        assert_eq!(arr[1].as_int().unwrap(), 2);
1042        assert_eq!(arr[2].as_int().unwrap(), 3);
1043    }
1044
1045    #[test]
1046    fn test_value_array_mixed() {
1047        let v = Value::array(vec![
1048            Value::int(42),
1049            Value::string("hello"),
1050            Value::bool(true),
1051            Value::null(),
1052        ]);
1053        let arr = v.as_array().unwrap();
1054        assert_eq!(arr[0].as_int().unwrap(), 42);
1055        assert_eq!(arr[1].as_string().unwrap(), "hello");
1056        assert!(arr[2].as_bool().unwrap());
1057        assert!(arr[3].is_null());
1058    }
1059
1060    #[test]
1061    fn test_value_array_nested() {
1062        let inner = Value::array(vec![Value::int(1), Value::int(2)]);
1063        let outer = Value::array(vec![inner]);
1064        let arr = outer.as_array().unwrap();
1065        let inner_arr = arr[0].as_array().unwrap();
1066        assert_eq!(inner_arr.len(), 2);
1067    }
1068
1069    #[test]
1070    fn test_value_object_empty() {
1071        let v = Value::object(HashMap::new());
1072        assert_eq!(v.kind, ValueKind::Object);
1073        assert!(v.as_object().unwrap().is_empty());
1074    }
1075
1076    #[test]
1077    fn test_value_object() {
1078        let mut map = HashMap::new();
1079        map.insert("name".to_string(), Value::string("Alice"));
1080        map.insert("age".to_string(), Value::int(30));
1081        let v = Value::object(map);
1082
1083        let obj = v.as_object().unwrap();
1084        assert_eq!(obj.get("name").unwrap().as_string().unwrap(), "Alice");
1085        assert_eq!(obj.get("age").unwrap().as_int().unwrap(), 30);
1086    }
1087
1088    #[test]
1089    fn test_value_object_nested() {
1090        let mut inner = HashMap::new();
1091        inner.insert("city".to_string(), Value::string("NYC"));
1092
1093        let mut outer = HashMap::new();
1094        outer.insert("address".to_string(), Value::object(inner));
1095
1096        let v = Value::object(outer);
1097        let obj = v.as_object().unwrap();
1098        let addr = obj.get("address").unwrap().as_object().unwrap();
1099        assert_eq!(addr.get("city").unwrap().as_string().unwrap(), "NYC");
1100    }
1101
1102    // ==================== Type Accessor Error Tests ====================
1103
1104    #[test]
1105    fn test_as_int_wrong_type() {
1106        let v = Value::string("not an int");
1107        let result = v.as_int();
1108        assert!(result.is_err());
1109        assert!(result.unwrap_err().to_string().contains("String"));
1110    }
1111
1112    #[test]
1113    fn test_as_bool_wrong_type() {
1114        let v = Value::int(42);
1115        let result = v.as_bool();
1116        assert!(result.is_err());
1117    }
1118
1119    #[test]
1120    fn test_as_string_wrong_type() {
1121        let v = Value::int(42);
1122        let result = v.as_string();
1123        assert!(result.is_err());
1124    }
1125
1126    #[test]
1127    fn test_as_decimal_wrong_type() {
1128        let v = Value::int(42);
1129        let result = v.as_decimal();
1130        assert!(result.is_err());
1131    }
1132
1133    #[test]
1134    fn test_as_array_wrong_type() {
1135        let v = Value::int(42);
1136        let result = v.as_array();
1137        assert!(result.is_err());
1138    }
1139
1140    #[test]
1141    fn test_as_object_wrong_type() {
1142        let v = Value::int(42);
1143        let result = v.as_object();
1144        assert!(result.is_err());
1145    }
1146
1147    #[test]
1148    fn test_as_bytes_wrong_type() {
1149        let v = Value::int(42);
1150        let result = v.as_bytes();
1151        assert!(result.is_err());
1152    }
1153
1154    #[test]
1155    fn test_as_date_wrong_type() {
1156        let v = Value::int(42);
1157        let result = v.as_date();
1158        assert!(result.is_err());
1159    }
1160
1161    #[test]
1162    fn test_as_timestamp_wrong_type() {
1163        let v = Value::int(42);
1164        let result = v.as_timestamp();
1165        assert!(result.is_err());
1166    }
1167
1168    #[test]
1169    fn test_as_range_wrong_type() {
1170        let v = Value::int(42);
1171        let result = v.as_range();
1172        assert!(result.is_err());
1173    }
1174
1175    // ==================== String-like Type Accessors ====================
1176
1177    #[test]
1178    fn test_as_string_from_xml() {
1179        let v = Value {
1180            kind: ValueKind::Xml,
1181            string_value: "<root/>".to_string(),
1182            ..Value::null()
1183        };
1184        assert_eq!(v.as_string().unwrap(), "<root/>");
1185    }
1186
1187    #[test]
1188    fn test_as_string_from_json() {
1189        let v = Value {
1190            kind: ValueKind::Json,
1191            string_value: r#"{"key":"value"}"#.to_string(),
1192            ..Value::null()
1193        };
1194        assert_eq!(v.as_string().unwrap(), r#"{"key":"value"}"#);
1195    }
1196
1197    #[test]
1198    fn test_as_string_from_url() {
1199        let v = Value {
1200            kind: ValueKind::Url,
1201            string_value: "https://example.com".to_string(),
1202            ..Value::null()
1203        };
1204        assert_eq!(v.as_string().unwrap(), "https://example.com");
1205    }
1206
1207    #[test]
1208    fn test_as_string_from_uuid() {
1209        let v = Value {
1210            kind: ValueKind::Uuid,
1211            string_value: "550e8400-e29b-41d4-a716-446655440000".to_string(),
1212            ..Value::null()
1213        };
1214        assert_eq!(
1215            v.as_string().unwrap(),
1216            "550e8400-e29b-41d4-a716-446655440000"
1217        );
1218    }
1219
1220    // ==================== to_json Tests ====================
1221
1222    #[test]
1223    fn test_to_json_null() {
1224        let v = Value::null();
1225        assert_eq!(v.to_json(), json!(null));
1226    }
1227
1228    #[test]
1229    fn test_to_json_int() {
1230        let v = Value::int(42);
1231        assert_eq!(v.to_json(), json!(42));
1232    }
1233
1234    #[test]
1235    fn test_to_json_bool() {
1236        let v = Value::bool(true);
1237        assert_eq!(v.to_json(), json!(true));
1238    }
1239
1240    #[test]
1241    fn test_to_json_string() {
1242        let v = Value::string("hello");
1243        assert_eq!(v.to_json(), json!("hello"));
1244    }
1245
1246    #[test]
1247    fn test_to_json_decimal() {
1248        let v = Value::decimal(dec!(123.45));
1249        assert_eq!(v.to_json(), json!("123.45"));
1250    }
1251
1252    #[test]
1253    fn test_to_json_array() {
1254        let v = Value::array(vec![Value::int(1), Value::int(2)]);
1255        assert_eq!(v.to_json(), json!([1, 2]));
1256    }
1257
1258    #[test]
1259    fn test_to_json_object() {
1260        let mut map = HashMap::new();
1261        map.insert("key".to_string(), Value::string("value"));
1262        let v = Value::object(map);
1263        assert_eq!(v.to_json(), json!({"key": "value"}));
1264    }
1265
1266    #[test]
1267    fn test_to_json_bytea_empty() {
1268        let v = Value {
1269            kind: ValueKind::Bytea,
1270            bytes_value: vec![],
1271            string_value: "".to_string(),
1272            ..Value::null()
1273        };
1274        assert_eq!(v.to_json(), json!(""));
1275    }
1276
1277    #[test]
1278    fn test_to_json_bytea_with_data() {
1279        let v = Value {
1280            kind: ValueKind::Bytea,
1281            bytes_value: vec![0xDE, 0xAD, 0xBE, 0xEF],
1282            ..Value::null()
1283        };
1284        assert_eq!(v.to_json(), json!("\\xdeadbeef"));
1285    }
1286
1287    #[test]
1288    fn test_to_json_range() {
1289        let range = Range {
1290            lower: Some(Box::new(Value::int(1))),
1291            upper: Some(Box::new(Value::int(10))),
1292            bounds: "[)".to_string(),
1293        };
1294        let v = Value {
1295            kind: ValueKind::Range,
1296            range_value: Some(range),
1297            ..Value::null()
1298        };
1299        let j = v.to_json();
1300        assert_eq!(j["lower"], json!(1));
1301        assert_eq!(j["upper"], json!(10));
1302        assert_eq!(j["bounds"], json!("[)"));
1303    }
1304
1305    #[test]
1306    fn test_to_json_range_none() {
1307        let v = Value {
1308            kind: ValueKind::Range,
1309            range_value: None,
1310            ..Value::null()
1311        };
1312        assert_eq!(v.to_json(), json!(null));
1313    }
1314
1315    // ==================== from_json Tests ====================
1316
1317    #[test]
1318    fn test_from_json_null() {
1319        let v = Value::from_json(json!(null)).unwrap();
1320        assert!(v.is_null());
1321    }
1322
1323    #[test]
1324    fn test_from_json_bool() {
1325        let v = Value::from_json(json!(true)).unwrap();
1326        assert!(v.as_bool().unwrap());
1327    }
1328
1329    #[test]
1330    fn test_from_json_int() {
1331        let v = Value::from_json(json!(42)).unwrap();
1332        assert_eq!(v.as_int().unwrap(), 42);
1333    }
1334
1335    #[test]
1336    fn test_from_json_float() {
1337        let v = Value::from_json(json!(1.5)).unwrap();
1338        // Floats are converted to strings
1339        assert_eq!(v.kind, ValueKind::String);
1340    }
1341
1342    #[test]
1343    fn test_from_json_string() {
1344        let v = Value::from_json(json!("hello")).unwrap();
1345        assert_eq!(v.as_string().unwrap(), "hello");
1346    }
1347
1348    #[test]
1349    fn test_from_json_array() {
1350        let v = Value::from_json(json!([1, 2, 3])).unwrap();
1351        let arr = v.as_array().unwrap();
1352        assert_eq!(arr.len(), 3);
1353    }
1354
1355    #[test]
1356    fn test_from_json_object() {
1357        let v = Value::from_json(json!({"name": "Alice"})).unwrap();
1358        let obj = v.as_object().unwrap();
1359        assert_eq!(obj.get("name").unwrap().as_string().unwrap(), "Alice");
1360    }
1361
1362    #[test]
1363    fn test_from_json_nested() {
1364        let v = Value::from_json(json!({
1365            "users": [
1366                {"name": "Alice", "age": 30},
1367                {"name": "Bob", "age": 25}
1368            ]
1369        }))
1370        .unwrap();
1371        let obj = v.as_object().unwrap();
1372        let users = obj.get("users").unwrap().as_array().unwrap();
1373        assert_eq!(users.len(), 2);
1374    }
1375
1376    #[test]
1377    fn test_from_json_depth_limit() {
1378        // Build deeply nested JSON: {"a":{"a":{"a":...}}}
1379        let mut json = serde_json::Value::Null;
1380        for _ in 0..70 {
1381            let mut obj = serde_json::Map::new();
1382            obj.insert("a".to_string(), json);
1383            json = serde_json::Value::Object(obj);
1384        }
1385        // Default depth limit is 64, so 70 levels should fail
1386        let result = Value::from_json(json);
1387        assert!(result.is_err());
1388        assert!(result.unwrap_err().to_string().contains("depth"));
1389    }
1390
1391    #[test]
1392    fn test_from_json_within_depth_limit() {
1393        // Build JSON nested to exactly 60 levels (under default 64 limit)
1394        let mut json = serde_json::Value::Bool(true);
1395        for _ in 0..60 {
1396            json = serde_json::Value::Array(vec![json]);
1397        }
1398        assert!(Value::from_json(json).is_ok());
1399    }
1400
1401    // ==================== decode_value Tests ====================
1402
1403    #[test]
1404    fn test_decode_value_null() {
1405        let v = decode_value(&json!(null), "INT").unwrap();
1406        assert!(v.is_null());
1407    }
1408
1409    #[test]
1410    fn test_decode_value_int_from_number() {
1411        let v = decode_value(&json!(42), "INT").unwrap();
1412        assert_eq!(v.as_int().unwrap(), 42);
1413    }
1414
1415    #[test]
1416    fn test_decode_value_int_from_string() {
1417        let v = decode_value(&json!("123"), "INT").unwrap();
1418        assert_eq!(v.as_int().unwrap(), 123);
1419    }
1420
1421    #[test]
1422    fn test_decode_value_int_invalid_string() {
1423        let v = decode_value(&json!("not_a_number"), "INT").unwrap();
1424        // Falls back to string
1425        assert_eq!(v.kind, ValueKind::String);
1426    }
1427
1428    #[test]
1429    fn test_decode_value_decimal() {
1430        let v = decode_value(&json!("123.456"), "DECIMAL").unwrap();
1431        assert_eq!(v.as_decimal().unwrap(), dec!(123.456));
1432    }
1433
1434    #[test]
1435    fn test_decode_value_decimal_from_number() {
1436        let v = decode_value(&json!(123), "DECIMAL").unwrap();
1437        assert_eq!(v.as_decimal().unwrap(), dec!(123));
1438    }
1439
1440    #[test]
1441    fn test_decode_value_bool_true() {
1442        let v = decode_value(&json!(true), "BOOL").unwrap();
1443        assert!(v.as_bool().unwrap());
1444    }
1445
1446    #[test]
1447    fn test_decode_value_bool_false() {
1448        let v = decode_value(&json!(false), "BOOL").unwrap();
1449        assert!(!v.as_bool().unwrap());
1450    }
1451
1452    #[test]
1453    fn test_decode_value_bool_from_string_true() {
1454        let v = decode_value(&json!("true"), "BOOL").unwrap();
1455        assert!(v.as_bool().unwrap());
1456    }
1457
1458    #[test]
1459    fn test_decode_value_bool_from_string_false() {
1460        let v = decode_value(&json!("false"), "BOOL").unwrap();
1461        assert!(!v.as_bool().unwrap());
1462    }
1463
1464    #[test]
1465    fn test_decode_value_bool_from_string_case_insensitive() {
1466        let v = decode_value(&json!("TRUE"), "BOOL").unwrap();
1467        assert!(v.as_bool().unwrap());
1468    }
1469
1470    #[test]
1471    fn test_decode_value_string() {
1472        let v = decode_value(&json!("hello"), "STRING").unwrap();
1473        assert_eq!(v.as_string().unwrap(), "hello");
1474    }
1475
1476    #[test]
1477    fn test_decode_value_bytea() {
1478        let v = decode_value(&json!("\\xDEADBEEF"), "BYTEA").unwrap();
1479        assert_eq!(v.kind, ValueKind::Bytea);
1480        assert_eq!(v.as_bytes().unwrap(), &[0xDE, 0xAD, 0xBE, 0xEF]);
1481    }
1482
1483    #[test]
1484    fn test_decode_value_bytea_no_prefix() {
1485        let v = decode_value(&json!("plain"), "BYTEA").unwrap();
1486        assert_eq!(v.kind, ValueKind::Bytea);
1487        assert!(v.as_bytes().unwrap().is_empty());
1488    }
1489
1490    #[test]
1491    fn test_decode_value_json() {
1492        let v = decode_value(&json!({"key": "value"}), "JSON").unwrap();
1493        assert_eq!(v.kind, ValueKind::Json);
1494    }
1495
1496    #[test]
1497    fn test_decode_value_jsonb() {
1498        let v = decode_value(&json!({"key": "value"}), "JSONB").unwrap();
1499        assert_eq!(v.kind, ValueKind::Jsonb);
1500    }
1501
1502    #[test]
1503    fn test_decode_value_date() {
1504        let v = decode_value(&json!("2024-01-15"), "DATE").unwrap();
1505        assert_eq!(v.kind, ValueKind::Date);
1506        let date = v.as_date().unwrap();
1507        assert_eq!(date.to_string(), "2024-01-15");
1508    }
1509
1510    #[test]
1511    fn test_decode_value_date_invalid() {
1512        let v = decode_value(&json!("not-a-date"), "DATE").unwrap();
1513        assert_eq!(v.kind, ValueKind::Date);
1514        // Date parsing fails, but value is stored as string
1515        assert!(v.date_value.is_none());
1516    }
1517
1518    #[test]
1519    fn test_decode_value_timestamp() {
1520        let v = decode_value(&json!("2024-01-15T10:30:00Z"), "TIMESTAMP").unwrap();
1521        assert_eq!(v.kind, ValueKind::Timestamp);
1522        let ts = v.as_timestamp().unwrap();
1523        assert_eq!(ts.to_rfc3339(), "2024-01-15T10:30:00+00:00");
1524    }
1525
1526    #[test]
1527    fn test_decode_value_timestamptz() {
1528        let v = decode_value(&json!("2024-01-15T10:30:00+05:00"), "TIMESTAMPTZ").unwrap();
1529        assert_eq!(v.kind, ValueKind::TimestampTz);
1530    }
1531
1532    #[test]
1533    fn test_decode_value_range() {
1534        let v = decode_value(
1535            &json!({"lower": 1, "upper": 10, "bounds": "[)"}),
1536            "INT4RANGE",
1537        )
1538        .unwrap();
1539        assert_eq!(v.kind, ValueKind::Range);
1540        let range = v.as_range().unwrap();
1541        assert_eq!(range.bounds, "[)");
1542    }
1543
1544    #[test]
1545    fn test_decode_value_array_generic() {
1546        let v = decode_value(&json!([1, 2, 3]), "").unwrap();
1547        assert_eq!(v.kind, ValueKind::Array);
1548        assert_eq!(v.as_array().unwrap().len(), 3);
1549    }
1550
1551    #[test]
1552    fn test_decode_value_object_generic() {
1553        let v = decode_value(&json!({"key": "value"}), "").unwrap();
1554        assert_eq!(v.kind, ValueKind::Object);
1555    }
1556
1557    #[test]
1558    fn test_decode_value_generic_bool() {
1559        let v = decode_value(&json!(true), "UNKNOWN").unwrap();
1560        assert!(v.as_bool().unwrap());
1561    }
1562
1563    #[test]
1564    fn test_decode_value_generic_int() {
1565        let v = decode_value(&json!(42), "UNKNOWN").unwrap();
1566        assert_eq!(v.as_int().unwrap(), 42);
1567    }
1568
1569    #[test]
1570    fn test_decode_value_generic_float() {
1571        let v = decode_value(&json!(1.23), "UNKNOWN").unwrap();
1572        // Floats become decimals if parseable
1573        assert_eq!(v.kind, ValueKind::Decimal);
1574    }
1575
1576    #[test]
1577    fn test_decode_value_generic_string() {
1578        let v = decode_value(&json!("hello"), "UNKNOWN").unwrap();
1579        assert_eq!(v.as_string().unwrap(), "hello");
1580    }
1581
1582    #[test]
1583    fn test_decode_value_case_insensitive() {
1584        let v1 = decode_value(&json!(42), "int").unwrap();
1585        let v2 = decode_value(&json!(42), "INT").unwrap();
1586        let v3 = decode_value(&json!(42), "Int").unwrap();
1587        assert_eq!(v1.as_int().unwrap(), 42);
1588        assert_eq!(v2.as_int().unwrap(), 42);
1589        assert_eq!(v3.as_int().unwrap(), 42);
1590    }
1591
1592    // ==================== Range Tests ====================
1593
1594    #[test]
1595    fn test_range_construction() {
1596        let range = Range {
1597            lower: Some(Box::new(Value::int(0))),
1598            upper: Some(Box::new(Value::int(100))),
1599            bounds: "[)".to_string(),
1600        };
1601        assert_eq!(range.lower.as_ref().unwrap().as_int().unwrap(), 0);
1602        assert_eq!(range.upper.as_ref().unwrap().as_int().unwrap(), 100);
1603        assert_eq!(range.bounds, "[)");
1604    }
1605
1606    #[test]
1607    fn test_range_unbounded_lower() {
1608        let range = Range {
1609            lower: None,
1610            upper: Some(Box::new(Value::int(100))),
1611            bounds: "(]".to_string(),
1612        };
1613        assert!(range.lower.is_none());
1614        assert!(range.upper.is_some());
1615    }
1616
1617    #[test]
1618    fn test_range_unbounded_upper() {
1619        let range = Range {
1620            lower: Some(Box::new(Value::int(0))),
1621            upper: None,
1622            bounds: "[)".to_string(),
1623        };
1624        assert!(range.lower.is_some());
1625        assert!(range.upper.is_none());
1626    }
1627
1628    #[test]
1629    fn test_range_clone() {
1630        let range = Range {
1631            lower: Some(Box::new(Value::int(1))),
1632            upper: Some(Box::new(Value::int(10))),
1633            bounds: "[]".to_string(),
1634        };
1635        let cloned = range.clone();
1636        assert_eq!(cloned.bounds, "[]");
1637    }
1638
1639    // ==================== Value Clone Tests ====================
1640
1641    #[test]
1642    fn test_value_clone() {
1643        let v = Value::string("test");
1644        let cloned = v.clone();
1645        assert_eq!(cloned.as_string().unwrap(), "test");
1646    }
1647
1648    #[test]
1649    fn test_value_clone_array() {
1650        let v = Value::array(vec![Value::int(1), Value::int(2)]);
1651        let cloned = v.clone();
1652        assert_eq!(cloned.as_array().unwrap().len(), 2);
1653    }
1654
1655    #[test]
1656    fn test_value_clone_object() {
1657        let mut map = HashMap::new();
1658        map.insert("key".to_string(), Value::string("value"));
1659        let v = Value::object(map);
1660        let cloned = v.clone();
1661        assert_eq!(
1662            cloned
1663                .as_object()
1664                .unwrap()
1665                .get("key")
1666                .unwrap()
1667                .as_string()
1668                .unwrap(),
1669            "value"
1670        );
1671    }
1672
1673    // ==================== JSON Round-Trip Tests ====================
1674
1675    #[test]
1676    fn test_json_roundtrip_int() {
1677        let original = Value::int(42);
1678        let json = original.to_json();
1679        let restored = Value::from_json(json).unwrap();
1680        assert_eq!(restored.as_int().unwrap(), 42);
1681    }
1682
1683    #[test]
1684    fn test_json_roundtrip_string() {
1685        let original = Value::string("hello world");
1686        let json = original.to_json();
1687        let restored = Value::from_json(json).unwrap();
1688        assert_eq!(restored.as_string().unwrap(), "hello world");
1689    }
1690
1691    #[test]
1692    fn test_json_roundtrip_bool() {
1693        let original = Value::bool(true);
1694        let json = original.to_json();
1695        let restored = Value::from_json(json).unwrap();
1696        assert!(restored.as_bool().unwrap());
1697    }
1698
1699    #[test]
1700    fn test_json_roundtrip_array() {
1701        let original = Value::array(vec![Value::int(1), Value::string("two")]);
1702        let json = original.to_json();
1703        let restored = Value::from_json(json).unwrap();
1704        let arr = restored.as_array().unwrap();
1705        assert_eq!(arr[0].as_int().unwrap(), 1);
1706        assert_eq!(arr[1].as_string().unwrap(), "two");
1707    }
1708
1709    #[test]
1710    fn test_json_roundtrip_object() {
1711        let mut map = HashMap::new();
1712        map.insert("name".to_string(), Value::string("Alice"));
1713        map.insert("age".to_string(), Value::int(30));
1714        let original = Value::object(map);
1715        let json = original.to_json();
1716        let restored = Value::from_json(json).unwrap();
1717        let obj = restored.as_object().unwrap();
1718        assert_eq!(obj.get("name").unwrap().as_string().unwrap(), "Alice");
1719        assert_eq!(obj.get("age").unwrap().as_int().unwrap(), 30);
1720    }
1721
1722    #[test]
1723    fn test_json_roundtrip_null() {
1724        let original = Value::null();
1725        let json = original.to_json();
1726        let restored = Value::from_json(json).unwrap();
1727        assert!(restored.is_null());
1728    }
1729
1730    // ==================== Timestamp Accessor Tests ====================
1731
1732    #[test]
1733    fn test_as_timestamp_from_timestamp() {
1734        let v = decode_value(&json!("2024-01-15T10:30:00Z"), "TIMESTAMP").unwrap();
1735        let ts = v.as_timestamp().unwrap();
1736        assert_eq!(ts.year(), 2024);
1737        assert_eq!(ts.month(), 1);
1738        assert_eq!(ts.day(), 15);
1739    }
1740
1741    #[test]
1742    fn test_as_timestamp_from_timestamptz() {
1743        let v = decode_value(&json!("2024-01-15T10:30:00Z"), "TIMESTAMPTZ").unwrap();
1744        let ts = v.as_timestamp().unwrap();
1745        assert!(ts.hour() == 10);
1746    }
1747
1748    #[test]
1749    fn test_value_node_accessor() {
1750        let mut props = HashMap::new();
1751        props.insert("name".to_string(), Value::string("Alice"));
1752        let node = Node {
1753            id: 42,
1754            labels: vec!["Person".into()],
1755            properties: props,
1756        };
1757        let v = Value::node(node);
1758        assert_eq!(v.kind, ValueKind::Node);
1759        let n = v.as_node().unwrap();
1760        assert_eq!(n.id, 42);
1761        assert_eq!(n.labels, vec!["Person".to_string()]);
1762        assert_eq!(
1763            n.properties.get("name").unwrap().as_string().unwrap(),
1764            "Alice"
1765        );
1766        assert!(v.as_edge().is_err());
1767    }
1768
1769    #[test]
1770    fn test_value_edge_accessor() {
1771        let edge = Edge {
1772            id: 1,
1773            start_node: 10,
1774            end_node: 20,
1775            edge_type: "KNOWS".into(),
1776            properties: HashMap::new(),
1777        };
1778        let v = Value::edge(edge);
1779        let e = v.as_edge().unwrap();
1780        assert_eq!(e.start_node, 10);
1781        assert_eq!(e.end_node, 20);
1782        assert_eq!(e.edge_type, "KNOWS");
1783    }
1784
1785    #[test]
1786    fn test_value_path_accessor() {
1787        let n0 = Node {
1788            id: 1,
1789            labels: vec!["A".into()],
1790            properties: HashMap::new(),
1791        };
1792        let n1 = Node {
1793            id: 2,
1794            labels: vec!["B".into()],
1795            properties: HashMap::new(),
1796        };
1797        let e = Edge {
1798            id: 99,
1799            start_node: 1,
1800            end_node: 2,
1801            edge_type: "R".into(),
1802            properties: HashMap::new(),
1803        };
1804        let v = Value::path(Path {
1805            nodes: vec![n0, n1],
1806            edges: vec![e],
1807        });
1808        let p = v.as_path().unwrap();
1809        assert_eq!(p.nodes.len(), 2);
1810        assert_eq!(p.edges.len(), 1);
1811        assert_eq!(p.edges[0].start_node, 1);
1812        assert_eq!(p.nodes[1].id, 2);
1813    }
1814}