use super::date_time::{DateTimeValue, DateValue, TimeValue};
use super::decimal128::Decimal128Value;
use super::geography::Geography;
use super::interval::IntervalValue;
use super::json::{Json, JsonB};
use super::list::List;
use super::null::NullType;
use super::uuid::UuidValue;
use super::vector::VectorValue;
use super::{ArrayValue, StructValue};
use crate::types::storage_ids::{EdgeId, VertexId};
use crate::vertex_edge_path::{Edge, EdgeHeader, Path, Tag, Vertex};
use crate::DataSet;
use crate::Value;
use std::collections::{HashMap, HashSet};
fn exhaustive_variant_check(value: &Value) {
debug_assert!(matches!(
value,
Value::Empty
| Value::Null(_)
| Value::Bool(_)
| Value::SmallInt(_)
| Value::Int(_)
| Value::BigInt(_)
| Value::Float(_)
| Value::Double(_)
| Value::Decimal128(_)
| Value::String(_)
| Value::FixedString(_)
| Value::Blob(_)
| Value::Date(_)
| Value::Time(_)
| Value::DateTime(_)
| Value::Vertex(_)
| Value::Edge(_)
| Value::EdgeHeader(_)
| Value::Path(_)
| Value::List(_)
| Value::Map(_)
| Value::Set(_)
| Value::Geography(_)
| Value::Vector(_)
| Value::DataSet(_)
| Value::Json(_)
| Value::JsonB(_)
| Value::Uuid(_)
| Value::Interval(_)
| Value::VertexId(_)
| Value::EdgeId(_)
| Value::Struct(_)
| Value::Array(_)
));
}
fn all_sample_values() -> Vec<Value> {
let mut list = List::new();
list.push(Value::Int(7));
let mut map = HashMap::new();
map.insert(Value::string("k"), Value::string("v"));
let mut set = HashSet::new();
set.insert(Value::Int(1));
set.insert(Value::BigInt(2));
let mut dataset = DataSet::new();
dataset.add_row(vec![Value::Int(1)]);
dataset.add_row(vec![Value::Int(2)]);
let vertex = Vertex::new(
VertexId::try_from_int64(10).expect("test vertex id"),
Tag::new("Person".into(), HashMap::new()),
);
let edge = Edge::new_empty(
VertexId::try_from_int64(1).expect("test vertex id"),
VertexId::try_from_int64(2).expect("test vertex id"),
"KNOWS".to_string(),
0,
);
let edge_header = EdgeHeader::new(
VertexId::try_from_int64(1).expect("test vertex id"),
VertexId::try_from_int64(2).expect("test vertex id"),
"KNOWS".to_string(),
0,
);
let path = Path::new(Vertex::new(
VertexId::try_from_int64(1).expect("test vertex id"),
Tag::new(String::new(), HashMap::new()),
));
vec![
Value::Empty,
Value::Null(NullType::Null),
Value::Bool(true),
Value::SmallInt(-42),
Value::Int(-42),
Value::BigInt(-42),
Value::Float(1.5),
Value::Double(1.5),
Value::Decimal128(Decimal128Value::from_i64(12345)),
Value::string("hello"),
Value::fixed_string(8, "fixed".to_string()),
Value::Blob(vec![1, 2, 3]),
Value::Date(DateValue {
year: 2026,
month: 8,
day: 15,
}),
Value::Time(TimeValue {
hour: 10,
minute: 30,
sec: 45,
microsec: 123,
}),
Value::DateTime(DateTimeValue {
year: 2026,
month: 8,
day: 15,
hour: 10,
minute: 30,
sec: 45,
microsec: 123,
}),
Value::Vertex(Box::new(vertex)),
Value::Edge(Box::new(edge)),
Value::EdgeHeader(Box::new(edge_header)),
Value::Path(Box::new(path)),
Value::list(list),
Value::map(map),
Value::set(set),
Value::Geography(Geography::from_wkt("POINT(1 2)").expect("wkt should parse")),
Value::Vector(VectorValue::dense(vec![1.0, 2.0, 3.0])),
Value::DataSet(Box::new(dataset)),
Value::Json(Box::new(
Json::parse(r#"{"a":1}"#).expect("json should parse"),
)),
Value::JsonB(Box::new(
JsonB::parse(r#"{"b":2}"#).expect("jsonb should parse"),
)),
Value::Uuid(UuidValue([9u8; 16])),
Value::Interval(IntervalValue::new(14, 3, 1000)),
Value::VertexId(VertexId::try_from_int64(99).expect("test vertex id")),
Value::EdgeId(EdgeId::new(99)),
Value::Struct(Box::new(StructValue::new(vec![
("city".into(), Value::string("x")),
(
"geo".to_string(),
Value::Struct(Box::new(StructValue::new(vec![(
"lat".to_string(),
Value::Double(1.5),
)]))),
),
]))),
Value::Array(Box::new(ArrayValue::new(vec![
Value::Int(1),
Value::Int(2),
Value::Int(3),
]))),
]
}
#[test]
fn all_value_variants_roundtrip_through_postcard() {
for value in all_sample_values() {
exhaustive_variant_check(&value);
let encoded = postcard::to_allocvec(&value).expect("encode value");
let decoded: Value = postcard::from_bytes(&encoded).expect("decode value");
assert_eq!(
decoded, value,
"postcard roundtrip must preserve the value exactly: {value:?}"
);
}
}
#[test]
fn all_value_variants_roundtrip_via_value_in_container() {
let values = all_sample_values();
let encoded = postcard::to_allocvec(&values).expect("encode container");
let decoded: Vec<Value> = postcard::from_bytes(&encoded).expect("decode container");
assert_eq!(decoded.len(), values.len());
for (decoded, original) in decoded.iter().zip(values.iter()) {
assert_eq!(decoded, original);
}
}
#[test]
fn map_with_non_string_keys_roundtrips() {
let mut map = HashMap::new();
map.insert(Value::Int(7), Value::string("seven"));
map.insert(Value::string("name"), Value::string("x"));
map.insert(Value::Double(0.5), Value::Bool(true));
let value = Value::map(map);
let encoded = postcard::to_allocvec(&value).expect("encode map");
let decoded: Value = postcard::from_bytes(&encoded).expect("decode map");
assert_eq!(decoded, value);
assert_eq!(decoded.hash_value(), value.hash_value());
}
#[test]
fn map_comparison_and_hash_are_key_order_independent() {
let mut a = HashMap::new();
a.insert(Value::Int(1), Value::string("one"));
a.insert(Value::Int(2), Value::string("two"));
let mut b = HashMap::new();
b.insert(Value::Int(2), Value::string("two"));
b.insert(Value::Int(1), Value::string("one"));
let va = Value::map(a);
let vb = Value::map(b);
assert_eq!(va, vb);
assert_eq!(va.cmp(&vb), std::cmp::Ordering::Equal);
assert_eq!(va.hash_value(), vb.hash_value());
}