eure_document/
value.rs

1use num_bigint::BigInt;
2
3use crate::{prelude_internal::*, text::Text};
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum ValueKind {
7    Hole,
8    Null,
9    Bool,
10    Integer,
11    F32,
12    F64,
13    Text,
14    Variant,
15    Array,
16    Tuple,
17    Map,
18}
19
20impl core::fmt::Display for ValueKind {
21    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22        match self {
23            Self::Hole => write!(f, "hole"),
24            Self::Null => write!(f, "null"),
25            Self::Bool => write!(f, "bool"),
26            Self::Integer => write!(f, "integer"),
27            Self::F32 => write!(f, "f32"),
28            Self::F64 => write!(f, "f64"),
29            Self::Text => write!(f, "text"),
30            Self::Variant => write!(f, "variant"),
31            Self::Array => write!(f, "array"),
32            Self::Tuple => write!(f, "tuple"),
33            Self::Map => write!(f, "map"),
34        }
35    }
36}
37
38#[derive(Debug, Clone, PartialEq)]
39pub enum PrimitiveValue {
40    Null,
41    Bool(bool),
42    Integer(BigInt),
43    F32(f32),
44    F64(f64),
45    /// Unified text type for strings and code.
46    ///
47    /// - `"..."` syntax produces `Text` with `Language::Plaintext`
48    /// - `` `...` `` syntax produces `Text` with `Language::Implicit`
49    /// - `` lang`...` `` syntax produces `Text` with `Language::Other(lang)`
50    Text(Text),
51    Variant(Variant),
52}
53
54impl PrimitiveValue {
55    /// Returns the text if this is a `Text` variant.
56    pub fn as_text(&self) -> Option<&Text> {
57        if let Self::Text(text) = self {
58            Some(text)
59        } else {
60            None
61        }
62    }
63
64    /// Returns the text content as a string slice if this is a `Text` variant.
65    pub fn as_str(&self) -> Option<&str> {
66        self.as_text().map(|t| t.as_str())
67    }
68
69    pub(crate) fn kind(&self) -> ValueKind {
70        match self {
71            Self::Null => ValueKind::Null,
72            Self::Bool(_) => ValueKind::Bool,
73            Self::Integer(_) => ValueKind::Integer,
74            Self::F32(_) => ValueKind::F32,
75            Self::F64(_) => ValueKind::F64,
76            Self::Text(_) => ValueKind::Text,
77            Self::Variant(_) => ValueKind::Variant,
78        }
79    }
80}
81
82#[derive(Debug, Clone, PartialEq)]
83pub enum Value {
84    Primitive(PrimitiveValue),
85    Array(Array),
86    Tuple(Tuple<Value>),
87    Map(Map),
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
91/// Key-comparable value which implements `Eq` and `Hash`.
92///
93/// Eure restricts map keys to four types — `String`, `Bool`, `Integer`,
94/// and `Tuple<Key...>` — for practical and predictable behavior.
95///
96/// - **Deterministic equality:**
97///   These types provide stable, well-defined equality and hashing.
98///   Types like floats, null, or holes introduce ambiguous or
99///   platform-dependent comparison rules.
100///
101/// - **Reliable round-tripping:**
102///   Keys must serialize and deserialize without losing meaning.
103///   Strings, booleans, integers, and tuples have canonical and
104///   unambiguous textual forms.
105///
106/// - **Tooling-friendly:**
107///   This set balances expressiveness and simplicity, making keys easy
108///   to validate, index, and reason about across implementations.
109pub enum ObjectKey {
110    Bool(bool),
111    Number(BigInt),
112    String(String),
113    Tuple(Tuple<ObjectKey>),
114}
115
116impl core::fmt::Display for ObjectKey {
117    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118        match self {
119            ObjectKey::Bool(bool) => write!(f, "{}", bool),
120            ObjectKey::Number(big_int) => write!(f, "{}", big_int),
121            ObjectKey::String(string) => write!(f, "{}", string),
122            ObjectKey::Tuple(tuple) => write!(f, "{}", tuple),
123        }
124    }
125}
126
127impl From<&str> for ObjectKey {
128    fn from(s: &str) -> Self {
129        ObjectKey::String(s.to_string())
130    }
131}
132
133impl From<String> for ObjectKey {
134    fn from(s: String) -> Self {
135        ObjectKey::String(s)
136    }
137}
138
139impl From<bool> for ObjectKey {
140    fn from(b: bool) -> Self {
141        ObjectKey::Bool(b)
142    }
143}
144
145impl From<i32> for ObjectKey {
146    fn from(n: i32) -> Self {
147        ObjectKey::Number(BigInt::from(n))
148    }
149}
150
151impl From<i64> for ObjectKey {
152    fn from(n: i64) -> Self {
153        ObjectKey::Number(BigInt::from(n))
154    }
155}
156
157impl From<BigInt> for ObjectKey {
158    fn from(n: BigInt) -> Self {
159        ObjectKey::Number(n)
160    }
161}
162
163#[derive(Debug, Clone, PartialEq, Plural, Default)]
164pub struct Array(pub Vec<Value>);
165
166#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Plural, Default)]
167pub struct Tuple<T>(pub Vec<T>);
168
169impl core::fmt::Display for Tuple<ObjectKey> {
170    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
171        write!(f, "(")?;
172        for (i, item) in self.0.iter().enumerate() {
173            if i != 0 {
174                write!(f, ", ")?;
175            }
176            write!(f, "{}", item)?;
177        }
178        write!(f, ")")
179    }
180}
181
182#[derive(Debug, Clone, PartialEq, Plural, Default)]
183#[plural(len, is_empty, iter, into_iter, into_iter_ref, from_iter, new)]
184pub struct Map(pub crate::Map<ObjectKey, Value>);
185
186#[derive(Debug, Clone, PartialEq)]
187pub struct Variant {
188    pub tag: String,
189    pub content: Box<Value>,
190}
191
192// ============================================================================
193// From implementations for PrimitiveValue
194// ============================================================================
195
196impl From<bool> for PrimitiveValue {
197    fn from(b: bool) -> Self {
198        PrimitiveValue::Bool(b)
199    }
200}
201
202impl From<i32> for PrimitiveValue {
203    fn from(n: i32) -> Self {
204        PrimitiveValue::Integer(BigInt::from(n))
205    }
206}
207
208impl From<i64> for PrimitiveValue {
209    fn from(n: i64) -> Self {
210        PrimitiveValue::Integer(BigInt::from(n))
211    }
212}
213
214impl From<f32> for PrimitiveValue {
215    fn from(n: f32) -> Self {
216        PrimitiveValue::F32(n)
217    }
218}
219
220impl From<f64> for PrimitiveValue {
221    fn from(n: f64) -> Self {
222        PrimitiveValue::F64(n)
223    }
224}
225
226impl From<&str> for PrimitiveValue {
227    fn from(s: &str) -> Self {
228        PrimitiveValue::Text(Text::plaintext(s))
229    }
230}
231
232impl From<String> for PrimitiveValue {
233    fn from(s: String) -> Self {
234        PrimitiveValue::Text(Text::plaintext(s))
235    }
236}
237
238impl From<Text> for PrimitiveValue {
239    fn from(t: Text) -> Self {
240        PrimitiveValue::Text(t)
241    }
242}