Skip to main content

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}