eure_document/
value.rs

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