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