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    /// Create a Value from a serde_json::Value
341    pub fn from_json(json: serde_json::Value) -> Self {
342        match json {
343            serde_json::Value::Null => Self::null(),
344            serde_json::Value::Bool(b) => Self::bool(b),
345            serde_json::Value::Number(n) => {
346                if let Some(i) = n.as_i64() {
347                    Self::int(i)
348                } else if let Some(f) = n.as_f64() {
349                    // Try to convert to decimal
350                    Self::string(f.to_string())
351                } else {
352                    Self::null()
353                }
354            }
355            serde_json::Value::String(s) => Self::string(s),
356            serde_json::Value::Array(arr) => {
357                let values: Vec<Value> = arr.into_iter().map(Self::from_json).collect();
358                Self::array(values)
359            }
360            serde_json::Value::Object(obj) => {
361                let mut map = HashMap::new();
362                for (k, v) in obj {
363                    map.insert(k, Self::from_json(v));
364                }
365                Self::object(map)
366            }
367        }
368    }
369}
370
371/// Decode a JSON value into a typed Value object
372pub fn decode_value(raw: &serde_json::Value, type_name: &str) -> Result<Value> {
373    if raw.is_null() {
374        return Ok(Value::null());
375    }
376
377    let type_upper = type_name.to_uppercase();
378
379    match type_upper.as_str() {
380        "INT" => {
381            if let Some(n) = raw.as_i64() {
382                Ok(Value::int(n))
383            } else if let Some(s) = raw.as_str() {
384                if let Ok(n) = s.parse::<i64>() {
385                    Ok(Value::int(n))
386                } else {
387                    Ok(Value::string(s))
388                }
389            } else {
390                Ok(Value::string(raw.to_string()))
391            }
392        }
393        "DECIMAL" => {
394            let s = raw
395                .as_str()
396                .map(|v| v.to_string())
397                .unwrap_or_else(|| raw.to_string());
398            if let Ok(dec) = s.parse::<Decimal>() {
399                Ok(Value::decimal(dec))
400            } else {
401                Ok(Value::string(s))
402            }
403        }
404        "BOOL" => {
405            if let Some(b) = raw.as_bool() {
406                Ok(Value::bool(b))
407            } else if let Some(s) = raw.as_str() {
408                let lower = s.to_ascii_lowercase();
409                if lower == "true" {
410                    Ok(Value::bool(true))
411                } else if lower == "false" {
412                    Ok(Value::bool(false))
413                } else {
414                    Ok(Value::string(s))
415                }
416            } else {
417                Ok(Value::string(raw.to_string()))
418            }
419        }
420        "STRING" => Ok(Value::string(raw.as_str().unwrap_or(""))),
421        "BYTEA" => {
422            let s = raw.as_str().unwrap_or("");
423            let bytes = if let Some(hex_str) = s.strip_prefix("\\x") {
424                hex::decode(hex_str).unwrap_or_default()
425            } else {
426                Vec::new()
427            };
428            Ok(Value {
429                kind: ValueKind::Bytea,
430                bytes_value: bytes,
431                string_value: s.to_string(),
432                ..Value::null()
433            })
434        }
435        "JSON" => Ok(Value {
436            kind: ValueKind::Json,
437            string_value: raw.to_string(),
438            ..Value::null()
439        }),
440        "JSONB" => Ok(Value {
441            kind: ValueKind::Jsonb,
442            string_value: raw.to_string(),
443            ..Value::null()
444        }),
445        "DATE" => {
446            let s = raw.as_str().unwrap_or("");
447            let date = NaiveDate::parse_from_str(s, "%Y-%m-%d").ok();
448            Ok(Value {
449                kind: ValueKind::Date,
450                string_value: s.to_string(),
451                date_value: date,
452                ..Value::null()
453            })
454        }
455        "TIMESTAMP" | "TIMESTAMPTZ" => {
456            let s = raw.as_str().unwrap_or("");
457            let timestamp = DateTime::parse_from_rfc3339(s)
458                .ok()
459                .map(|dt| dt.with_timezone(&Utc));
460            let kind = if type_upper == "TIMESTAMPTZ" {
461                ValueKind::TimestampTz
462            } else {
463                ValueKind::Timestamp
464            };
465            Ok(Value {
466                kind,
467                string_value: s.to_string(),
468                timestamp_value: timestamp,
469                ..Value::null()
470            })
471        }
472        _ if type_upper.contains("RANGE") => {
473            if let Some(obj) = raw.as_object() {
474                let range = Range {
475                    lower: obj
476                        .get("lower")
477                        .and_then(|v| decode_value(v, "").ok().map(Box::new)),
478                    upper: obj
479                        .get("upper")
480                        .and_then(|v| decode_value(v, "").ok().map(Box::new)),
481                    bounds: obj
482                        .get("bounds")
483                        .and_then(|v| v.as_str())
484                        .unwrap_or("")
485                        .to_string(),
486                };
487                Ok(Value {
488                    kind: ValueKind::Range,
489                    range_value: Some(range),
490                    ..Value::null()
491                })
492            } else {
493                Ok(Value::string(raw.to_string()))
494            }
495        }
496        _ => {
497            // Handle arrays and objects generically
498            if let Some(arr) = raw.as_array() {
499                let values: Result<Vec<_>> = arr.iter().map(|v| decode_value(v, "")).collect();
500                Ok(Value::array(values?))
501            } else if let Some(obj) = raw.as_object() {
502                let mut map = HashMap::new();
503                for (k, v) in obj {
504                    map.insert(k.clone(), decode_value(v, "")?);
505                }
506                Ok(Value::object(map))
507            } else if let Some(b) = raw.as_bool() {
508                Ok(Value::bool(b))
509            } else if let Some(n) = raw.as_i64() {
510                Ok(Value::int(n))
511            } else if let Some(f) = raw.as_f64() {
512                let s = f.to_string();
513                if let Ok(dec) = s.parse::<Decimal>() {
514                    Ok(Value::decimal(dec))
515                } else {
516                    Ok(Value::string(s))
517                }
518            } else if let Some(s) = raw.as_str() {
519                Ok(Value::string(s))
520            } else {
521                Ok(Value::string(raw.to_string()))
522            }
523        }
524    }
525}
526
527#[cfg(test)]
528mod tests {
529    use super::*;
530    use chrono::{Datelike, Timelike};
531    use rust_decimal_macros::dec;
532    use serde_json::json;
533
534    // ==================== ValueKind Tests ====================
535
536    #[test]
537    fn test_value_kind_equality() {
538        assert_eq!(ValueKind::Null, ValueKind::Null);
539        assert_eq!(ValueKind::Int, ValueKind::Int);
540        assert_ne!(ValueKind::Int, ValueKind::String);
541    }
542
543    #[test]
544    fn test_value_kind_copy() {
545        let kind = ValueKind::Int;
546        let kind_copy = kind;
547        assert_eq!(kind, kind_copy);
548    }
549
550    #[test]
551    fn test_value_kind_debug() {
552        let debug_str = format!("{:?}", ValueKind::Timestamp);
553        assert_eq!(debug_str, "Timestamp");
554    }
555
556    #[test]
557    fn test_value_kind_all_variants() {
558        // Ensure all variants exist and are distinct
559        let variants = [
560            ValueKind::Null,
561            ValueKind::Int,
562            ValueKind::Bool,
563            ValueKind::String,
564            ValueKind::Decimal,
565            ValueKind::Array,
566            ValueKind::Object,
567            ValueKind::Bytea,
568            ValueKind::Date,
569            ValueKind::Time,
570            ValueKind::TimeTz,
571            ValueKind::Timestamp,
572            ValueKind::TimestampTz,
573            ValueKind::Interval,
574            ValueKind::Json,
575            ValueKind::Jsonb,
576            ValueKind::Xml,
577            ValueKind::Url,
578            ValueKind::Domain,
579            ValueKind::Uuid,
580            ValueKind::Enum,
581            ValueKind::BitString,
582            ValueKind::Range,
583        ];
584        assert_eq!(variants.len(), 23);
585        // Check uniqueness
586        for i in 0..variants.len() {
587            for j in (i + 1)..variants.len() {
588                assert_ne!(variants[i], variants[j]);
589            }
590        }
591    }
592
593    // ==================== Value Construction Tests ====================
594
595    #[test]
596    fn test_value_null() {
597        let v = Value::null();
598        assert_eq!(v.kind, ValueKind::Null);
599        assert!(v.is_null());
600    }
601
602    #[test]
603    fn test_value_int() {
604        let v = Value::int(42);
605        assert_eq!(v.kind, ValueKind::Int);
606        assert!(!v.is_null());
607        assert_eq!(v.as_int().unwrap(), 42);
608    }
609
610    #[test]
611    fn test_value_int_negative() {
612        let v = Value::int(-100);
613        assert_eq!(v.as_int().unwrap(), -100);
614    }
615
616    #[test]
617    fn test_value_int_zero() {
618        let v = Value::int(0);
619        assert_eq!(v.as_int().unwrap(), 0);
620    }
621
622    #[test]
623    fn test_value_int_max() {
624        let v = Value::int(i64::MAX);
625        assert_eq!(v.as_int().unwrap(), i64::MAX);
626    }
627
628    #[test]
629    fn test_value_int_min() {
630        let v = Value::int(i64::MIN);
631        assert_eq!(v.as_int().unwrap(), i64::MIN);
632    }
633
634    #[test]
635    fn test_value_bool_true() {
636        let v = Value::bool(true);
637        assert_eq!(v.kind, ValueKind::Bool);
638        assert!(v.as_bool().unwrap());
639    }
640
641    #[test]
642    fn test_value_bool_false() {
643        let v = Value::bool(false);
644        assert!(!v.as_bool().unwrap());
645    }
646
647    #[test]
648    fn test_value_string() {
649        let v = Value::string("hello");
650        assert_eq!(v.kind, ValueKind::String);
651        assert_eq!(v.as_string().unwrap(), "hello");
652    }
653
654    #[test]
655    fn test_value_string_empty() {
656        let v = Value::string("");
657        assert_eq!(v.as_string().unwrap(), "");
658    }
659
660    #[test]
661    fn test_value_string_unicode() {
662        let v = Value::string("こんにちは世界🌍");
663        assert_eq!(v.as_string().unwrap(), "こんにちは世界🌍");
664    }
665
666    #[test]
667    fn test_value_string_owned() {
668        let owned = String::from("owned string");
669        let v = Value::string(owned);
670        assert_eq!(v.as_string().unwrap(), "owned string");
671    }
672
673    #[test]
674    fn test_value_decimal() {
675        let v = Value::decimal(dec!(123.456));
676        assert_eq!(v.kind, ValueKind::Decimal);
677        assert_eq!(v.as_decimal().unwrap(), dec!(123.456));
678    }
679
680    #[test]
681    fn test_value_decimal_precision() {
682        let v = Value::decimal(dec!(0.000000001));
683        assert_eq!(v.as_decimal().unwrap(), dec!(0.000000001));
684    }
685
686    #[test]
687    fn test_value_decimal_large() {
688        let v = Value::decimal(dec!(99999999999999.99));
689        assert_eq!(v.as_decimal().unwrap(), dec!(99999999999999.99));
690    }
691
692    #[test]
693    fn test_value_array_empty() {
694        let v = Value::array(vec![]);
695        assert_eq!(v.kind, ValueKind::Array);
696        assert!(v.as_array().unwrap().is_empty());
697    }
698
699    #[test]
700    fn test_value_array() {
701        let v = Value::array(vec![Value::int(1), Value::int(2), Value::int(3)]);
702        let arr = v.as_array().unwrap();
703        assert_eq!(arr.len(), 3);
704        assert_eq!(arr[0].as_int().unwrap(), 1);
705        assert_eq!(arr[1].as_int().unwrap(), 2);
706        assert_eq!(arr[2].as_int().unwrap(), 3);
707    }
708
709    #[test]
710    fn test_value_array_mixed() {
711        let v = Value::array(vec![
712            Value::int(42),
713            Value::string("hello"),
714            Value::bool(true),
715            Value::null(),
716        ]);
717        let arr = v.as_array().unwrap();
718        assert_eq!(arr[0].as_int().unwrap(), 42);
719        assert_eq!(arr[1].as_string().unwrap(), "hello");
720        assert!(arr[2].as_bool().unwrap());
721        assert!(arr[3].is_null());
722    }
723
724    #[test]
725    fn test_value_array_nested() {
726        let inner = Value::array(vec![Value::int(1), Value::int(2)]);
727        let outer = Value::array(vec![inner]);
728        let arr = outer.as_array().unwrap();
729        let inner_arr = arr[0].as_array().unwrap();
730        assert_eq!(inner_arr.len(), 2);
731    }
732
733    #[test]
734    fn test_value_object_empty() {
735        let v = Value::object(HashMap::new());
736        assert_eq!(v.kind, ValueKind::Object);
737        assert!(v.as_object().unwrap().is_empty());
738    }
739
740    #[test]
741    fn test_value_object() {
742        let mut map = HashMap::new();
743        map.insert("name".to_string(), Value::string("Alice"));
744        map.insert("age".to_string(), Value::int(30));
745        let v = Value::object(map);
746
747        let obj = v.as_object().unwrap();
748        assert_eq!(obj.get("name").unwrap().as_string().unwrap(), "Alice");
749        assert_eq!(obj.get("age").unwrap().as_int().unwrap(), 30);
750    }
751
752    #[test]
753    fn test_value_object_nested() {
754        let mut inner = HashMap::new();
755        inner.insert("city".to_string(), Value::string("NYC"));
756
757        let mut outer = HashMap::new();
758        outer.insert("address".to_string(), Value::object(inner));
759
760        let v = Value::object(outer);
761        let obj = v.as_object().unwrap();
762        let addr = obj.get("address").unwrap().as_object().unwrap();
763        assert_eq!(addr.get("city").unwrap().as_string().unwrap(), "NYC");
764    }
765
766    // ==================== Type Accessor Error Tests ====================
767
768    #[test]
769    fn test_as_int_wrong_type() {
770        let v = Value::string("not an int");
771        let result = v.as_int();
772        assert!(result.is_err());
773        assert!(result.unwrap_err().to_string().contains("String"));
774    }
775
776    #[test]
777    fn test_as_bool_wrong_type() {
778        let v = Value::int(42);
779        let result = v.as_bool();
780        assert!(result.is_err());
781    }
782
783    #[test]
784    fn test_as_string_wrong_type() {
785        let v = Value::int(42);
786        let result = v.as_string();
787        assert!(result.is_err());
788    }
789
790    #[test]
791    fn test_as_decimal_wrong_type() {
792        let v = Value::int(42);
793        let result = v.as_decimal();
794        assert!(result.is_err());
795    }
796
797    #[test]
798    fn test_as_array_wrong_type() {
799        let v = Value::int(42);
800        let result = v.as_array();
801        assert!(result.is_err());
802    }
803
804    #[test]
805    fn test_as_object_wrong_type() {
806        let v = Value::int(42);
807        let result = v.as_object();
808        assert!(result.is_err());
809    }
810
811    #[test]
812    fn test_as_bytes_wrong_type() {
813        let v = Value::int(42);
814        let result = v.as_bytes();
815        assert!(result.is_err());
816    }
817
818    #[test]
819    fn test_as_date_wrong_type() {
820        let v = Value::int(42);
821        let result = v.as_date();
822        assert!(result.is_err());
823    }
824
825    #[test]
826    fn test_as_timestamp_wrong_type() {
827        let v = Value::int(42);
828        let result = v.as_timestamp();
829        assert!(result.is_err());
830    }
831
832    #[test]
833    fn test_as_range_wrong_type() {
834        let v = Value::int(42);
835        let result = v.as_range();
836        assert!(result.is_err());
837    }
838
839    // ==================== String-like Type Accessors ====================
840
841    #[test]
842    fn test_as_string_from_xml() {
843        let v = Value {
844            kind: ValueKind::Xml,
845            string_value: "<root/>".to_string(),
846            ..Value::null()
847        };
848        assert_eq!(v.as_string().unwrap(), "<root/>");
849    }
850
851    #[test]
852    fn test_as_string_from_json() {
853        let v = Value {
854            kind: ValueKind::Json,
855            string_value: r#"{"key":"value"}"#.to_string(),
856            ..Value::null()
857        };
858        assert_eq!(v.as_string().unwrap(), r#"{"key":"value"}"#);
859    }
860
861    #[test]
862    fn test_as_string_from_url() {
863        let v = Value {
864            kind: ValueKind::Url,
865            string_value: "https://example.com".to_string(),
866            ..Value::null()
867        };
868        assert_eq!(v.as_string().unwrap(), "https://example.com");
869    }
870
871    #[test]
872    fn test_as_string_from_uuid() {
873        let v = Value {
874            kind: ValueKind::Uuid,
875            string_value: "550e8400-e29b-41d4-a716-446655440000".to_string(),
876            ..Value::null()
877        };
878        assert_eq!(
879            v.as_string().unwrap(),
880            "550e8400-e29b-41d4-a716-446655440000"
881        );
882    }
883
884    // ==================== to_json Tests ====================
885
886    #[test]
887    fn test_to_json_null() {
888        let v = Value::null();
889        assert_eq!(v.to_json(), json!(null));
890    }
891
892    #[test]
893    fn test_to_json_int() {
894        let v = Value::int(42);
895        assert_eq!(v.to_json(), json!(42));
896    }
897
898    #[test]
899    fn test_to_json_bool() {
900        let v = Value::bool(true);
901        assert_eq!(v.to_json(), json!(true));
902    }
903
904    #[test]
905    fn test_to_json_string() {
906        let v = Value::string("hello");
907        assert_eq!(v.to_json(), json!("hello"));
908    }
909
910    #[test]
911    fn test_to_json_decimal() {
912        let v = Value::decimal(dec!(123.45));
913        assert_eq!(v.to_json(), json!("123.45"));
914    }
915
916    #[test]
917    fn test_to_json_array() {
918        let v = Value::array(vec![Value::int(1), Value::int(2)]);
919        assert_eq!(v.to_json(), json!([1, 2]));
920    }
921
922    #[test]
923    fn test_to_json_object() {
924        let mut map = HashMap::new();
925        map.insert("key".to_string(), Value::string("value"));
926        let v = Value::object(map);
927        assert_eq!(v.to_json(), json!({"key": "value"}));
928    }
929
930    #[test]
931    fn test_to_json_bytea_empty() {
932        let v = Value {
933            kind: ValueKind::Bytea,
934            bytes_value: vec![],
935            string_value: "".to_string(),
936            ..Value::null()
937        };
938        assert_eq!(v.to_json(), json!(""));
939    }
940
941    #[test]
942    fn test_to_json_bytea_with_data() {
943        let v = Value {
944            kind: ValueKind::Bytea,
945            bytes_value: vec![0xDE, 0xAD, 0xBE, 0xEF],
946            ..Value::null()
947        };
948        assert_eq!(v.to_json(), json!("\\xdeadbeef"));
949    }
950
951    #[test]
952    fn test_to_json_range() {
953        let range = Range {
954            lower: Some(Box::new(Value::int(1))),
955            upper: Some(Box::new(Value::int(10))),
956            bounds: "[)".to_string(),
957        };
958        let v = Value {
959            kind: ValueKind::Range,
960            range_value: Some(range),
961            ..Value::null()
962        };
963        let j = v.to_json();
964        assert_eq!(j["lower"], json!(1));
965        assert_eq!(j["upper"], json!(10));
966        assert_eq!(j["bounds"], json!("[)"));
967    }
968
969    #[test]
970    fn test_to_json_range_none() {
971        let v = Value {
972            kind: ValueKind::Range,
973            range_value: None,
974            ..Value::null()
975        };
976        assert_eq!(v.to_json(), json!(null));
977    }
978
979    // ==================== from_json Tests ====================
980
981    #[test]
982    fn test_from_json_null() {
983        let v = Value::from_json(json!(null));
984        assert!(v.is_null());
985    }
986
987    #[test]
988    fn test_from_json_bool() {
989        let v = Value::from_json(json!(true));
990        assert!(v.as_bool().unwrap());
991    }
992
993    #[test]
994    fn test_from_json_int() {
995        let v = Value::from_json(json!(42));
996        assert_eq!(v.as_int().unwrap(), 42);
997    }
998
999    #[test]
1000    fn test_from_json_float() {
1001        let v = Value::from_json(json!(1.5));
1002        // Floats are converted to strings
1003        assert_eq!(v.kind, ValueKind::String);
1004    }
1005
1006    #[test]
1007    fn test_from_json_string() {
1008        let v = Value::from_json(json!("hello"));
1009        assert_eq!(v.as_string().unwrap(), "hello");
1010    }
1011
1012    #[test]
1013    fn test_from_json_array() {
1014        let v = Value::from_json(json!([1, 2, 3]));
1015        let arr = v.as_array().unwrap();
1016        assert_eq!(arr.len(), 3);
1017    }
1018
1019    #[test]
1020    fn test_from_json_object() {
1021        let v = Value::from_json(json!({"name": "Alice"}));
1022        let obj = v.as_object().unwrap();
1023        assert_eq!(obj.get("name").unwrap().as_string().unwrap(), "Alice");
1024    }
1025
1026    #[test]
1027    fn test_from_json_nested() {
1028        let v = Value::from_json(json!({
1029            "users": [
1030                {"name": "Alice", "age": 30},
1031                {"name": "Bob", "age": 25}
1032            ]
1033        }));
1034        let obj = v.as_object().unwrap();
1035        let users = obj.get("users").unwrap().as_array().unwrap();
1036        assert_eq!(users.len(), 2);
1037    }
1038
1039    // ==================== decode_value Tests ====================
1040
1041    #[test]
1042    fn test_decode_value_null() {
1043        let v = decode_value(&json!(null), "INT").unwrap();
1044        assert!(v.is_null());
1045    }
1046
1047    #[test]
1048    fn test_decode_value_int_from_number() {
1049        let v = decode_value(&json!(42), "INT").unwrap();
1050        assert_eq!(v.as_int().unwrap(), 42);
1051    }
1052
1053    #[test]
1054    fn test_decode_value_int_from_string() {
1055        let v = decode_value(&json!("123"), "INT").unwrap();
1056        assert_eq!(v.as_int().unwrap(), 123);
1057    }
1058
1059    #[test]
1060    fn test_decode_value_int_invalid_string() {
1061        let v = decode_value(&json!("not_a_number"), "INT").unwrap();
1062        // Falls back to string
1063        assert_eq!(v.kind, ValueKind::String);
1064    }
1065
1066    #[test]
1067    fn test_decode_value_decimal() {
1068        let v = decode_value(&json!("123.456"), "DECIMAL").unwrap();
1069        assert_eq!(v.as_decimal().unwrap(), dec!(123.456));
1070    }
1071
1072    #[test]
1073    fn test_decode_value_decimal_from_number() {
1074        let v = decode_value(&json!(123), "DECIMAL").unwrap();
1075        assert_eq!(v.as_decimal().unwrap(), dec!(123));
1076    }
1077
1078    #[test]
1079    fn test_decode_value_bool_true() {
1080        let v = decode_value(&json!(true), "BOOL").unwrap();
1081        assert!(v.as_bool().unwrap());
1082    }
1083
1084    #[test]
1085    fn test_decode_value_bool_false() {
1086        let v = decode_value(&json!(false), "BOOL").unwrap();
1087        assert!(!v.as_bool().unwrap());
1088    }
1089
1090    #[test]
1091    fn test_decode_value_bool_from_string_true() {
1092        let v = decode_value(&json!("true"), "BOOL").unwrap();
1093        assert!(v.as_bool().unwrap());
1094    }
1095
1096    #[test]
1097    fn test_decode_value_bool_from_string_false() {
1098        let v = decode_value(&json!("false"), "BOOL").unwrap();
1099        assert!(!v.as_bool().unwrap());
1100    }
1101
1102    #[test]
1103    fn test_decode_value_bool_from_string_case_insensitive() {
1104        let v = decode_value(&json!("TRUE"), "BOOL").unwrap();
1105        assert!(v.as_bool().unwrap());
1106    }
1107
1108    #[test]
1109    fn test_decode_value_string() {
1110        let v = decode_value(&json!("hello"), "STRING").unwrap();
1111        assert_eq!(v.as_string().unwrap(), "hello");
1112    }
1113
1114    #[test]
1115    fn test_decode_value_bytea() {
1116        let v = decode_value(&json!("\\xDEADBEEF"), "BYTEA").unwrap();
1117        assert_eq!(v.kind, ValueKind::Bytea);
1118        assert_eq!(v.as_bytes().unwrap(), &[0xDE, 0xAD, 0xBE, 0xEF]);
1119    }
1120
1121    #[test]
1122    fn test_decode_value_bytea_no_prefix() {
1123        let v = decode_value(&json!("plain"), "BYTEA").unwrap();
1124        assert_eq!(v.kind, ValueKind::Bytea);
1125        assert!(v.as_bytes().unwrap().is_empty());
1126    }
1127
1128    #[test]
1129    fn test_decode_value_json() {
1130        let v = decode_value(&json!({"key": "value"}), "JSON").unwrap();
1131        assert_eq!(v.kind, ValueKind::Json);
1132    }
1133
1134    #[test]
1135    fn test_decode_value_jsonb() {
1136        let v = decode_value(&json!({"key": "value"}), "JSONB").unwrap();
1137        assert_eq!(v.kind, ValueKind::Jsonb);
1138    }
1139
1140    #[test]
1141    fn test_decode_value_date() {
1142        let v = decode_value(&json!("2024-01-15"), "DATE").unwrap();
1143        assert_eq!(v.kind, ValueKind::Date);
1144        let date = v.as_date().unwrap();
1145        assert_eq!(date.to_string(), "2024-01-15");
1146    }
1147
1148    #[test]
1149    fn test_decode_value_date_invalid() {
1150        let v = decode_value(&json!("not-a-date"), "DATE").unwrap();
1151        assert_eq!(v.kind, ValueKind::Date);
1152        // Date parsing fails, but value is stored as string
1153        assert!(v.date_value.is_none());
1154    }
1155
1156    #[test]
1157    fn test_decode_value_timestamp() {
1158        let v = decode_value(&json!("2024-01-15T10:30:00Z"), "TIMESTAMP").unwrap();
1159        assert_eq!(v.kind, ValueKind::Timestamp);
1160        let ts = v.as_timestamp().unwrap();
1161        assert_eq!(ts.to_rfc3339(), "2024-01-15T10:30:00+00:00");
1162    }
1163
1164    #[test]
1165    fn test_decode_value_timestamptz() {
1166        let v = decode_value(&json!("2024-01-15T10:30:00+05:00"), "TIMESTAMPTZ").unwrap();
1167        assert_eq!(v.kind, ValueKind::TimestampTz);
1168    }
1169
1170    #[test]
1171    fn test_decode_value_range() {
1172        let v = decode_value(
1173            &json!({"lower": 1, "upper": 10, "bounds": "[)"}),
1174            "INT4RANGE",
1175        )
1176        .unwrap();
1177        assert_eq!(v.kind, ValueKind::Range);
1178        let range = v.as_range().unwrap();
1179        assert_eq!(range.bounds, "[)");
1180    }
1181
1182    #[test]
1183    fn test_decode_value_array_generic() {
1184        let v = decode_value(&json!([1, 2, 3]), "").unwrap();
1185        assert_eq!(v.kind, ValueKind::Array);
1186        assert_eq!(v.as_array().unwrap().len(), 3);
1187    }
1188
1189    #[test]
1190    fn test_decode_value_object_generic() {
1191        let v = decode_value(&json!({"key": "value"}), "").unwrap();
1192        assert_eq!(v.kind, ValueKind::Object);
1193    }
1194
1195    #[test]
1196    fn test_decode_value_generic_bool() {
1197        let v = decode_value(&json!(true), "UNKNOWN").unwrap();
1198        assert!(v.as_bool().unwrap());
1199    }
1200
1201    #[test]
1202    fn test_decode_value_generic_int() {
1203        let v = decode_value(&json!(42), "UNKNOWN").unwrap();
1204        assert_eq!(v.as_int().unwrap(), 42);
1205    }
1206
1207    #[test]
1208    fn test_decode_value_generic_float() {
1209        let v = decode_value(&json!(1.23), "UNKNOWN").unwrap();
1210        // Floats become decimals if parseable
1211        assert_eq!(v.kind, ValueKind::Decimal);
1212    }
1213
1214    #[test]
1215    fn test_decode_value_generic_string() {
1216        let v = decode_value(&json!("hello"), "UNKNOWN").unwrap();
1217        assert_eq!(v.as_string().unwrap(), "hello");
1218    }
1219
1220    #[test]
1221    fn test_decode_value_case_insensitive() {
1222        let v1 = decode_value(&json!(42), "int").unwrap();
1223        let v2 = decode_value(&json!(42), "INT").unwrap();
1224        let v3 = decode_value(&json!(42), "Int").unwrap();
1225        assert_eq!(v1.as_int().unwrap(), 42);
1226        assert_eq!(v2.as_int().unwrap(), 42);
1227        assert_eq!(v3.as_int().unwrap(), 42);
1228    }
1229
1230    // ==================== Range Tests ====================
1231
1232    #[test]
1233    fn test_range_construction() {
1234        let range = Range {
1235            lower: Some(Box::new(Value::int(0))),
1236            upper: Some(Box::new(Value::int(100))),
1237            bounds: "[)".to_string(),
1238        };
1239        assert_eq!(range.lower.as_ref().unwrap().as_int().unwrap(), 0);
1240        assert_eq!(range.upper.as_ref().unwrap().as_int().unwrap(), 100);
1241        assert_eq!(range.bounds, "[)");
1242    }
1243
1244    #[test]
1245    fn test_range_unbounded_lower() {
1246        let range = Range {
1247            lower: None,
1248            upper: Some(Box::new(Value::int(100))),
1249            bounds: "(]".to_string(),
1250        };
1251        assert!(range.lower.is_none());
1252        assert!(range.upper.is_some());
1253    }
1254
1255    #[test]
1256    fn test_range_unbounded_upper() {
1257        let range = Range {
1258            lower: Some(Box::new(Value::int(0))),
1259            upper: None,
1260            bounds: "[)".to_string(),
1261        };
1262        assert!(range.lower.is_some());
1263        assert!(range.upper.is_none());
1264    }
1265
1266    #[test]
1267    fn test_range_clone() {
1268        let range = Range {
1269            lower: Some(Box::new(Value::int(1))),
1270            upper: Some(Box::new(Value::int(10))),
1271            bounds: "[]".to_string(),
1272        };
1273        let cloned = range.clone();
1274        assert_eq!(cloned.bounds, "[]");
1275    }
1276
1277    // ==================== Value Clone Tests ====================
1278
1279    #[test]
1280    fn test_value_clone() {
1281        let v = Value::string("test");
1282        let cloned = v.clone();
1283        assert_eq!(cloned.as_string().unwrap(), "test");
1284    }
1285
1286    #[test]
1287    fn test_value_clone_array() {
1288        let v = Value::array(vec![Value::int(1), Value::int(2)]);
1289        let cloned = v.clone();
1290        assert_eq!(cloned.as_array().unwrap().len(), 2);
1291    }
1292
1293    #[test]
1294    fn test_value_clone_object() {
1295        let mut map = HashMap::new();
1296        map.insert("key".to_string(), Value::string("value"));
1297        let v = Value::object(map);
1298        let cloned = v.clone();
1299        assert_eq!(
1300            cloned
1301                .as_object()
1302                .unwrap()
1303                .get("key")
1304                .unwrap()
1305                .as_string()
1306                .unwrap(),
1307            "value"
1308        );
1309    }
1310
1311    // ==================== JSON Round-Trip Tests ====================
1312
1313    #[test]
1314    fn test_json_roundtrip_int() {
1315        let original = Value::int(42);
1316        let json = original.to_json();
1317        let restored = Value::from_json(json);
1318        assert_eq!(restored.as_int().unwrap(), 42);
1319    }
1320
1321    #[test]
1322    fn test_json_roundtrip_string() {
1323        let original = Value::string("hello world");
1324        let json = original.to_json();
1325        let restored = Value::from_json(json);
1326        assert_eq!(restored.as_string().unwrap(), "hello world");
1327    }
1328
1329    #[test]
1330    fn test_json_roundtrip_bool() {
1331        let original = Value::bool(true);
1332        let json = original.to_json();
1333        let restored = Value::from_json(json);
1334        assert!(restored.as_bool().unwrap());
1335    }
1336
1337    #[test]
1338    fn test_json_roundtrip_array() {
1339        let original = Value::array(vec![Value::int(1), Value::string("two")]);
1340        let json = original.to_json();
1341        let restored = Value::from_json(json);
1342        let arr = restored.as_array().unwrap();
1343        assert_eq!(arr[0].as_int().unwrap(), 1);
1344        assert_eq!(arr[1].as_string().unwrap(), "two");
1345    }
1346
1347    #[test]
1348    fn test_json_roundtrip_object() {
1349        let mut map = HashMap::new();
1350        map.insert("name".to_string(), Value::string("Alice"));
1351        map.insert("age".to_string(), Value::int(30));
1352        let original = Value::object(map);
1353        let json = original.to_json();
1354        let restored = Value::from_json(json);
1355        let obj = restored.as_object().unwrap();
1356        assert_eq!(obj.get("name").unwrap().as_string().unwrap(), "Alice");
1357        assert_eq!(obj.get("age").unwrap().as_int().unwrap(), 30);
1358    }
1359
1360    #[test]
1361    fn test_json_roundtrip_null() {
1362        let original = Value::null();
1363        let json = original.to_json();
1364        let restored = Value::from_json(json);
1365        assert!(restored.is_null());
1366    }
1367
1368    // ==================== Timestamp Accessor Tests ====================
1369
1370    #[test]
1371    fn test_as_timestamp_from_timestamp() {
1372        let v = decode_value(&json!("2024-01-15T10:30:00Z"), "TIMESTAMP").unwrap();
1373        let ts = v.as_timestamp().unwrap();
1374        assert_eq!(ts.year(), 2024);
1375        assert_eq!(ts.month(), 1);
1376        assert_eq!(ts.day(), 15);
1377    }
1378
1379    #[test]
1380    fn test_as_timestamp_from_timestamptz() {
1381        let v = decode_value(&json!("2024-01-15T10:30:00Z"), "TIMESTAMPTZ").unwrap();
1382        let ts = v.as_timestamp().unwrap();
1383        assert!(ts.hour() == 10);
1384    }
1385}