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