rson_core/
value.rs

1//! RSON value types and data model.
2//!
3//! This module defines the core `RsonValue` enum that represents all possible
4//! values in the RSON format, along with supporting types and utilities.
5
6use core::fmt;
7#[cfg(not(feature = "std"))]
8use alloc::{
9    collections::BTreeMap as HashMap,
10    string::{String, ToString},
11    vec::Vec,
12};
13
14use indexmap::IndexMap;
15
16/// A value in the RSON format.
17///
18/// This enum represents all possible values that can be expressed in RSON,
19/// including both JSON-compatible values and RSON-specific extensions.
20#[derive(Debug, Clone, PartialEq)]
21pub enum RsonValue {
22    /// Null value (maps to None in Option types)
23    Null,
24    
25    /// Boolean value
26    Bool(bool),
27    
28    /// Integer value
29    Int(i64),
30    
31    /// Floating-point value  
32    Float(f64),
33    
34    /// String value
35    String(String),
36    
37    /// Character value (RSON extension)
38    Char(char),
39    
40    /// Array of values
41    Array(Vec<RsonValue>),
42    
43    /// Map with string keys (like JSON object)
44    Map(IndexMap<String, RsonValue>),
45    
46    /// Struct with named fields (RSON extension)
47    Struct {
48        name: String,
49        fields: IndexMap<String, RsonValue>,
50    },
51    
52    /// Tuple with ordered values (RSON extension)
53    Tuple(Vec<RsonValue>),
54    
55    /// Enum variant (RSON extension)
56    Enum {
57        name: String,
58        variant: String,
59        value: Option<Box<RsonValue>>,
60    },
61    
62    /// Optional value (RSON extension)
63    Option(Option<Box<RsonValue>>),
64}
65
66/// The type of an RSON value.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum RsonType {
69    Null,
70    Bool,
71    Int,
72    Float,
73    String,
74    Char,
75    Array,
76    Map,
77    Struct,
78    Tuple,
79    Enum,
80    Option,
81}
82
83impl RsonValue {
84    /// Get the type of this value.
85    pub fn value_type(&self) -> RsonType {
86        match self {
87            RsonValue::Null => RsonType::Null,
88            RsonValue::Bool(_) => RsonType::Bool,
89            RsonValue::Int(_) => RsonType::Int,
90            RsonValue::Float(_) => RsonType::Float,
91            RsonValue::String(_) => RsonType::String,
92            RsonValue::Char(_) => RsonType::Char,
93            RsonValue::Array(_) => RsonType::Array,
94            RsonValue::Map(_) => RsonType::Map,
95            RsonValue::Struct { .. } => RsonType::Struct,
96            RsonValue::Tuple(_) => RsonType::Tuple,
97            RsonValue::Enum { .. } => RsonType::Enum,
98            RsonValue::Option(_) => RsonType::Option,
99        }
100    }
101    
102    /// Check if this value is null.
103    pub fn is_null(&self) -> bool {
104        matches!(self, RsonValue::Null)
105    }
106    
107    /// Check if this value is a boolean.
108    pub fn is_bool(&self) -> bool {
109        matches!(self, RsonValue::Bool(_))
110    }
111    
112    /// Check if this value is a number (int or float).
113    pub fn is_number(&self) -> bool {
114        matches!(self, RsonValue::Int(_) | RsonValue::Float(_))
115    }
116    
117    /// Check if this value is a string.
118    pub fn is_string(&self) -> bool {
119        matches!(self, RsonValue::String(_))
120    }
121    
122    /// Check if this value is an array.
123    pub fn is_array(&self) -> bool {
124        matches!(self, RsonValue::Array(_))
125    }
126    
127    /// Check if this value is a map or struct.
128    pub fn is_object(&self) -> bool {
129        matches!(self, RsonValue::Map(_) | RsonValue::Struct { .. })
130    }
131    
132    /// Try to get this value as a boolean.
133    pub fn as_bool(&self) -> Option<bool> {
134        match self {
135            RsonValue::Bool(b) => Some(*b),
136            _ => None,
137        }
138    }
139    
140    /// Try to get this value as an integer.
141    pub fn as_i64(&self) -> Option<i64> {
142        match self {
143            RsonValue::Int(i) => Some(*i),
144            RsonValue::Float(f) if f.fract() == 0.0 => Some(*f as i64),
145            _ => None,
146        }
147    }
148    
149    /// Try to get this value as a float.
150    pub fn as_f64(&self) -> Option<f64> {
151        match self {
152            RsonValue::Float(f) => Some(*f),
153            RsonValue::Int(i) => Some(*i as f64),
154            _ => None,
155        }
156    }
157    
158    /// Try to get this value as a string reference.
159    pub fn as_str(&self) -> Option<&str> {
160        match self {
161            RsonValue::String(s) => Some(s),
162            _ => None,
163        }
164    }
165    
166    /// Try to get this value as an array reference.
167    pub fn as_array(&self) -> Option<&Vec<RsonValue>> {
168        match self {
169            RsonValue::Array(arr) => Some(arr),
170            _ => None,
171        }
172    }
173    
174    /// Try to get this value as a map reference.
175    pub fn as_map(&self) -> Option<&IndexMap<String, RsonValue>> {
176        match self {
177            RsonValue::Map(map) => Some(map),
178            _ => None,
179        }
180    }
181    
182    /// Get the value at the given index if this is an array.
183    pub fn get_index(&self, index: usize) -> Option<&RsonValue> {
184        match self {
185            RsonValue::Array(arr) => arr.get(index),
186            RsonValue::Tuple(arr) => arr.get(index),
187            _ => None,
188        }
189    }
190    
191    /// Get the value with the given key if this is a map or struct.
192    pub fn get(&self, key: &str) -> Option<&RsonValue> {
193        match self {
194            RsonValue::Map(map) => map.get(key),
195            RsonValue::Struct { fields, .. } => fields.get(key),
196            _ => None,
197        }
198    }
199    
200    /// Create a Some variant of Option.
201    pub fn some(value: RsonValue) -> Self {
202        RsonValue::Option(Some(Box::new(value)))
203    }
204    
205    /// Create a None variant of Option.
206    pub fn none() -> Self {
207        RsonValue::Option(None)
208    }
209}
210
211impl fmt::Display for RsonValue {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        match self {
214            RsonValue::Null => write!(f, "null"),
215            RsonValue::Bool(b) => write!(f, "{}", b),
216            RsonValue::Int(i) => write!(f, "{}", i),
217            RsonValue::Float(fl) => write!(f, "{}", fl),
218            RsonValue::String(s) => write!(f, "\"{}\"", s),
219            RsonValue::Char(c) => write!(f, "'{}'", c),
220            RsonValue::Array(arr) => {
221                write!(f, "[")?;
222                for (i, item) in arr.iter().enumerate() {
223                    if i > 0 { write!(f, ", ")?; }
224                    write!(f, "{}", item)?;
225                }
226                write!(f, "]")
227            }
228            RsonValue::Map(map) => {
229                write!(f, "{{")?;
230                for (i, (key, value)) in map.iter().enumerate() {
231                    if i > 0 { write!(f, ", ")?; }
232                    write!(f, "{}: {}", key, value)?;
233                }
234                write!(f, "}}")
235            }
236            RsonValue::Struct { name, fields } => {
237                write!(f, "{}(", name)?;
238                for (i, (key, value)) in fields.iter().enumerate() {
239                    if i > 0 { write!(f, ", ")?; }
240                    write!(f, "{}: {}", key, value)?;
241                }
242                write!(f, ")")
243            }
244            RsonValue::Tuple(values) => {
245                write!(f, "(")?;
246                for (i, value) in values.iter().enumerate() {
247                    if i > 0 { write!(f, ", ")?; }
248                    write!(f, "{}", value)?;
249                }
250                write!(f, ")")
251            }
252            RsonValue::Enum { name, variant, value } => {
253                write!(f, "{}::{}", name, variant)?;
254                if let Some(val) = value {
255                    write!(f, "({})", val)?;
256                }
257                Ok(())
258            }
259            RsonValue::Option(Some(value)) => write!(f, "Some({})", value),
260            RsonValue::Option(None) => write!(f, "None"),
261        }
262    }
263}
264
265impl fmt::Display for RsonType {
266    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267        match self {
268            RsonType::Null => write!(f, "null"),
269            RsonType::Bool => write!(f, "bool"),
270            RsonType::Int => write!(f, "int"),
271            RsonType::Float => write!(f, "float"),
272            RsonType::String => write!(f, "string"),
273            RsonType::Char => write!(f, "char"),
274            RsonType::Array => write!(f, "array"),
275            RsonType::Map => write!(f, "map"),
276            RsonType::Struct => write!(f, "struct"),
277            RsonType::Tuple => write!(f, "tuple"),
278            RsonType::Enum => write!(f, "enum"),
279            RsonType::Option => write!(f, "option"),
280        }
281    }
282}
283
284// Convenience constructors
285impl From<bool> for RsonValue {
286    fn from(b: bool) -> Self {
287        RsonValue::Bool(b)
288    }
289}
290
291impl From<i32> for RsonValue {
292    fn from(i: i32) -> Self {
293        RsonValue::Int(i as i64)
294    }
295}
296
297impl From<i64> for RsonValue {
298    fn from(i: i64) -> Self {
299        RsonValue::Int(i)
300    }
301}
302
303impl From<f64> for RsonValue {
304    fn from(f: f64) -> Self {
305        RsonValue::Float(f)
306    }
307}
308
309impl From<String> for RsonValue {
310    fn from(s: String) -> Self {
311        RsonValue::String(s)
312    }
313}
314
315impl From<&str> for RsonValue {
316    fn from(s: &str) -> Self {
317        RsonValue::String(s.to_string())
318    }
319}
320
321impl From<char> for RsonValue {
322    fn from(c: char) -> Self {
323        RsonValue::Char(c)
324    }
325}
326
327impl<T: Into<RsonValue>> From<Vec<T>> for RsonValue {
328    fn from(vec: Vec<T>) -> Self {
329        RsonValue::Array(vec.into_iter().map(Into::into).collect())
330    }
331}
332
333impl<T: Into<RsonValue>> From<Option<T>> for RsonValue {
334    fn from(opt: Option<T>) -> Self {
335        RsonValue::Option(opt.map(|v| Box::new(v.into())))
336    }
337}