varar_core/value.rs
1//! The dynamic value model — the Rust replacement for Java varar-core's `Object`
2//! with `instanceof Map`/`List`/`String` duck-typing (see `CellDiff.java`,
3//! `DocStringDiff.java`, `ParamDiff.java`). One closed enum carries handler
4//! arguments, handler returns, thread-through state, row objects, table rows,
5//! and the conformance wire values.
6//!
7//! Equality is derived `PartialEq`, the analog of Java's `Objects.equals`:
8//! `Int(2) != Float(2.0)` (Java `Integer(2).equals(Double(2.0))` is false), and
9//! `Map` equality is order-insensitive (`BTreeMap`), matching `Map.of(...)`
10//! vs `LinkedHashMap` equality in the Java tests.
11
12use std::collections::BTreeMap;
13
14/// A dynamic JSON-ish value. `BTreeMap` gives order-insensitive map equality and
15/// a free recursive key-sort for canonical JSON.
16#[derive(Clone, Debug, PartialEq)]
17pub enum Value {
18 Null,
19 Bool(bool),
20 /// Integer (Java `Integer`/`Long`; `{int}` transforms here).
21 Int(i64),
22 /// Floating-point (Java `Double`); serialized as an integer when integral.
23 Float(f64),
24 String(String),
25 List(Vec<Value>),
26 Map(BTreeMap<String, Value>),
27}
28
29impl Value {
30 /// A short type name (for `ReturnShapeError` messages, mirroring Java's
31 /// `getClass().getSimpleName()`).
32 pub fn type_name(&self) -> &'static str {
33 match self {
34 Value::Null => "null",
35 Value::Bool(_) => "Boolean",
36 Value::Int(_) => "Integer",
37 Value::Float(_) => "Double",
38 Value::String(_) => "String",
39 Value::List(_) => "List",
40 Value::Map(_) => "Map",
41 }
42 }
43
44 /// Builds a [`Value::List`] from anything iterable of `Value`.
45 pub fn list(items: impl IntoIterator<Item = Value>) -> Value {
46 Value::List(items.into_iter().collect())
47 }
48
49 /// Builds a [`Value::Map`] from `(String, Value)` pairs.
50 pub fn map(entries: impl IntoIterator<Item = (String, Value)>) -> Value {
51 Value::Map(entries.into_iter().collect())
52 }
53}
54
55impl From<i64> for Value {
56 fn from(v: i64) -> Value {
57 Value::Int(v)
58 }
59}
60
61impl From<i32> for Value {
62 fn from(v: i32) -> Value {
63 Value::Int(i64::from(v))
64 }
65}
66
67impl From<bool> for Value {
68 fn from(v: bool) -> Value {
69 Value::Bool(v)
70 }
71}
72
73impl From<f64> for Value {
74 fn from(v: f64) -> Value {
75 Value::Float(v)
76 }
77}
78
79impl From<&str> for Value {
80 fn from(v: &str) -> Value {
81 Value::String(v.to_string())
82 }
83}
84
85impl From<String> for Value {
86 fn from(v: String) -> Value {
87 Value::String(v)
88 }
89}
90
91impl From<Vec<Value>> for Value {
92 fn from(v: Vec<Value>) -> Value {
93 Value::List(v)
94 }
95}