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