json_rs/
json.rs

1use std::collections::HashMap;
2use std::error::Error;
3use std::fmt::Display;
4use std::str::FromStr;
5use std::ops::{Index, IndexMut};
6
7use crate::lexer::Lexer;
8use crate::parser::Parser;
9
10#[derive(Debug)]
11pub enum JSONError {
12    SyntaxError(String),
13    LexerError(String),
14    ParseError(String),
15    ValueError(String),
16    KeyError(String),
17    IndexError(String),
18}
19
20impl Error for JSONError {}
21
22impl Display for JSONError {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        match self {
25            Self::SyntaxError(what) => write!(f, "JSON Syntax Error: {}", what),
26            Self::LexerError(what) => write!(f, "JSON Lexer Error: {}", what),
27            Self::ParseError(what) => write!(f, "JSON Parse Error: {}", what),
28            Self::ValueError(what) => write!(f, "JSON Value Error: {}", what),
29            Self::KeyError(what) => write!(f, "JSON Key Error: {}", what),
30            Self::IndexError(what) => write!(f, "JSON Index Error: {}", what),
31        }
32    }
33}
34
35#[derive(Clone, Debug, PartialEq)]
36pub enum JSONValue {
37    Bool(bool),
38    Number(f64),
39    String(String),
40    Array(Vec<JSONValue>),
41    Object(HashMap<String, JSONValue>),
42    Null,
43}
44
45pub type Result<T> = std::result::Result<T, JSONError>;
46
47impl JSONValue {
48    ///////////////////////////////////////////////
49    // Functions that assume `self` is an Object //
50    ///////////////////////////////////////////////
51
52    pub fn get(&self, key: &str) -> Result<&JSONValue> {
53        match self {
54            Self::Object(vals) => {
55                if let Some(val) = vals.get(key) {
56                    Ok(val)
57                } else {
58                    Err(JSONError::KeyError(format!("key {} not found", key)))
59                }
60            }
61            other => {
62                Err(JSONError::ValueError(format!("expected object, found {:?}", other.name())))
63            }
64        }
65    }
66    pub fn get_mut(&mut self, key: &str) -> Result<&mut JSONValue> {
67        match self {
68            Self::Object(vals) => {
69                if let Some(val) = vals.get_mut(key) {
70                    Ok(val)
71                } else {
72                    Err(JSONError::KeyError(format!("key {} not found", key)))
73                }
74            }
75            other => {
76                Err(JSONError::ValueError(format!("expected object, found {:?}", other.name())))
77            }
78        }
79    }
80    pub fn obj_insert(&mut self, key: &str, value: JSONValue) -> Result<()> {
81        match self {
82            Self::Object(map) => {
83                if let Some(_) = map.get_mut(key) {
84                    Err(JSONError::KeyError(format!("key {} already in object", key)))
85                } else {
86                    map.insert(key.to_string(), value);
87                    Ok(())
88                }
89            }
90            other => {
91                Err(JSONError::ValueError(format!("expected object, found {:?}", other.name())))
92            }
93        }
94    }
95    pub fn obj_remove(&mut self, key: &str) -> Result<(String, JSONValue)> {
96        match self {
97            Self::Object(map) => {
98                if let Some(v) = map.remove(key) {
99                    Ok((key.to_string(), v))
100                } else {
101                    Err(JSONError::KeyError(format!("key {} not found", key)))
102                }
103            }
104            other => {
105                Err(JSONError::ValueError(format!("expected object, found {:?}", other.name())))
106            }
107        }
108    }
109
110
111    //////////////////////////////////////////////
112    // Functions that assume `self` is an Array //
113    //////////////////////////////////////////////
114
115    pub fn try_index(&self, index: usize) -> Result<&JSONValue> {
116        match self {
117            Self::Array(arr) => {
118                if let Some(val) = arr.get(index) {
119                    Ok(val)
120                } else {
121                    Err(JSONError::ValueError(format!("index {} out of bounds for length {}", index, arr.len())))
122                }
123            }
124            other => {
125                Err(JSONError::ValueError(format!("expected array, found {}", other.name())))
126            }
127        }
128    }
129    pub fn try_index_mut(&mut self, index: usize) -> Result<&mut JSONValue> {
130        match self {
131            Self::Array(arr) => {
132                let len = arr.len().clone();
133
134                if let Some(val) = arr.get_mut(index) {
135                    Ok(val)
136                } else {
137                    Err(JSONError::ValueError(format!("index {} out of bounds for length {}", index, len)))
138                }
139            }
140            other => {
141                Err(JSONError::ValueError(format!("expected array, found {}", other.name())))
142            }
143        }
144    }
145    pub fn arr_push(&mut self, val: JSONValue) -> Result<()> {
146        match self {
147            Self::Array(arr) => {
148                arr.push(val);
149                Ok(())
150            }
151            other => {
152                Err(JSONError::ValueError(format!("expected array, found {}", other.name())))
153            }
154        }
155    }
156    pub fn arr_pop(&mut self) -> Result<JSONValue> {
157        match self {
158            Self::Array(arr) => {
159                if let Some(v) = arr.pop() {
160                    Ok(v)
161                } else {
162                    Err(JSONError::ValueError("cannot pop an array of zero length".to_string()))
163                }
164            }
165            other => {
166                Err(JSONError::ValueError(format!("expected array, found {}", other.name())))
167            }
168        }
169    }
170    pub fn arr_insert(&mut self, pos: usize, val: JSONValue) -> Result<()> {
171        match self {
172            Self::Array(arr) => {
173                let len = arr.len().clone();
174
175                if pos > len {
176                    Err(JSONError::IndexError(format!("index {} out of bounds for length {}", pos, len)))
177                } else {
178                    arr.insert(pos, val);
179
180                    Ok(())
181                }
182            }
183            other => {
184                Err(JSONError::ValueError(format!("expected array, found {}", other.name())))
185            }
186        }
187    }
188    pub fn arr_remove(&mut self, pos: usize) -> Result<JSONValue> {
189        match self {
190            Self::Array(arr) => {
191                let len = arr.len().clone();
192
193                if pos > len {
194                    Err(JSONError::IndexError(format!("index {} out of bounds for length {}", pos, len)))
195                } else {
196                    Ok(arr.remove(pos))
197                }
198            }
199            other => {
200                Err(JSONError::ValueError(format!("expected array, found {}", other.name())))
201            }
202        }
203    }
204
205    /// Constructs a JSON null value.
206    #[inline]
207    pub const fn null() -> Self {
208        Self::Null
209    }
210
211    // helper function to assist with <JSONValue as Display>::fmt(). Allows printed
212    // JSON text to auto-format spacing. 
213    fn fmt_recursive(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
214        match self {
215            Self::Bool(b) => { write!(f, "{}", b)?; }
216            Self::Number(n) => { write!(f, "{}", n)?; }
217            Self::String(s) => { write!(f, "\"{}\"", s)?; }
218            Self::Array(arr) => {
219                let tab_width = level * 4;
220                write!(f, "[\n")?;
221                for i in 0..arr.len() {
222                    write!(f, "    {: <1$}", "", tab_width)?;
223                    arr[i].fmt_recursive(f, level + 1)?;
224                    if i != arr.len() - 1 {
225                        write!(f, ",")?;
226                    }
227                    write!(f, "\n")?;
228                }
229                write!(f, "{: <1$}]", "", tab_width)?;
230            }
231            Self::Object(obj) => {
232                let tab_width = level * 4;
233                write!(f, "{{\n")?;
234                let mut i = 0;
235                for key in obj.keys() {
236                    write!(f, "    {: <1$}", "", tab_width)?;
237                    write!(f, "\"{}\": ", key)?;
238                    obj[key].fmt_recursive(f, level + 1)?;
239                    if i != obj.len() - 1 {
240                        write!(f, ",")?;
241                        i += 1;
242                    }
243                    write!(f, "\n")?;
244                }
245                write!(f, "{: <1$}}}", "", tab_width)?;
246            }
247            Self::Null => { write!(f, "null")?; }
248        }
249
250
251        Ok(())
252    }
253
254    // used for debug messages
255    fn name(&self) -> &'static str {
256        match self {
257            Self::Bool(_) => "boolean",
258            Self::Number(_) => "number",
259            Self::String(_) => "string",
260            Self::Array(_) => "array",
261            Self::Object(_) => "object",
262            Self::Null => "null",
263        }
264    }
265}
266
267///////////////////////////////////
268// JSON-to-Rust Type Conversions //
269///////////////////////////////////
270
271/// A helper trait that performs non-consuming type conversions from
272/// JSONValues to Rust primitive types.
273pub trait Cast<T> {
274    fn cast(&self) -> Result<T>;
275}
276
277impl Cast<bool> for JSONValue {
278    fn cast(&self) -> Result<bool> {
279        match self {
280            Self::Bool(b) => Ok(*b),
281            other => Err(JSONError::ValueError(format!("expected boolean, found {:?}", other.name())))
282        }
283    }
284}
285
286impl Cast<f64> for JSONValue {
287    fn cast(&self) -> Result<f64> {
288        match self {
289            Self::Number(v) => Ok(*v),
290            other => Err(JSONError::ValueError(format!("expected number, found {:?}", other.name())))
291        }
292    }
293}
294
295impl Cast<String> for JSONValue {
296    fn cast(&self) -> Result<String> {
297        match self {
298            Self::String(s) => Ok(s.clone()),
299            other => Err(JSONError::ValueError(format!("expected string, found {:?}", other.name())))
300        }
301    }
302}
303
304macro_rules! impl_cast_int {
305    {$($type_name:ty) +} => {
306        $(impl Cast<$type_name> for JSONValue {
307            fn cast(&self) -> crate::json::Result<$type_name> {
308                match self {
309                    Self::Number(v) => Ok(v.clone() as $type_name),
310                    other => Err(JSONError::ValueError(format!("expected number, found {:?}", other.name()))),
311                }
312            }
313        })+
314    }
315}
316
317impl_cast_int!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32);
318
319///////////////////////////////////
320// Rust-to-JSON Type Conversions //
321///////////////////////////////////
322
323// equivalent to <Self as FromStr>::from_str(self, &Vec<u8>::to_string())
324impl TryFrom<Vec<u8>> for JSONValue {
325    type Error = JSONError;
326
327    fn try_from(value: Vec<u8>) -> std::result::Result<Self, Self::Error> {
328        Parser::from(
329            Lexer::new(value).tokenify()?
330        ).parse()
331    }
332}
333
334impl From<f64> for JSONValue {
335    fn from(value: f64) -> Self {
336        Self::Number(value)
337    }
338}
339
340// macro for auto-implementing From<> traits for numeric types
341macro_rules! impl_from_int {
342    {$($type_name:ty) +} => {
343        $(impl From<$type_name> for JSONValue {
344            fn from(value: $type_name) -> Self {
345                Self::Number(value as f64)
346            }
347        })+
348    }
349}
350
351
352
353impl_from_int!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32);
354
355// NOTE: this directly constructs a JSONValue::String, and does not perform any parsing
356impl From<String> for JSONValue {
357    fn from(value: String) -> Self {
358        Self::String(value)
359    }
360}
361
362impl From<bool> for JSONValue {
363    fn from(value: bool) -> Self {
364        Self::Bool(value)
365    }
366}
367
368impl From<Vec<JSONValue>> for JSONValue {
369    fn from(value: Vec<JSONValue>) -> Self {
370        Self::Array(value)
371    }
372}
373
374
375/// Constructs a JSON null value. Equivalent to Self::null()
376impl From<()> for JSONValue {
377    fn from(_: ()) -> Self {
378        Self::Null
379    }
380}
381
382impl<T> From<Option<T>> for JSONValue where JSONValue: From<T> {
383    fn from(value: Option<T>) -> Self {
384        match value {
385            Some(v) => <Self as From<T>>::from(v),
386            None => Self::Null,
387        }
388    }
389} 
390
391///////////////////////////////
392// JSON-Text I/O Conversions //
393///////////////////////////////
394
395// conversion from raw json text into a JSONValue
396impl FromStr for JSONValue {
397    type Err = JSONError;
398    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
399        Self::try_from(s.as_bytes().to_vec())
400    }
401}
402
403impl Display for JSONValue {
404    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
405        self.fmt_recursive(f, 0)
406    }
407}
408
409//////////////////////////////////////////
410// Indexing without Result<> protection //
411//////////////////////////////////////////
412
413impl Index<&str> for JSONValue {
414    type Output = JSONValue;
415    fn index(&self, index: &str) -> &Self::Output {
416        self.get(index).unwrap()
417    }
418}
419
420impl IndexMut<&str> for JSONValue {
421    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
422        self.get_mut(index).unwrap()
423    }
424}
425
426impl Index<String> for JSONValue {
427    type Output = JSONValue;
428    fn index(&self, index: String) -> &Self::Output {
429        self.get(&index).unwrap()
430    }
431}
432
433impl IndexMut<String> for JSONValue {
434    fn index_mut(&mut self, index: String) -> &mut Self::Output {
435        self.get_mut(&index).unwrap()
436    }
437}
438
439impl Index<usize> for JSONValue {
440    type Output = JSONValue;
441    fn index(&self, index: usize) -> &Self::Output {
442        match self {
443            JSONValue::Array(arr) => &arr[index],
444            other => panic!("expected array, found {:?}", other.name()),
445        }
446    }
447}
448
449impl IndexMut<usize> for JSONValue {
450    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
451        match self {
452            JSONValue::Array(arr) => &mut arr[index],
453            other => panic!("expected array, found {:?}", other.name()),
454        }
455    }
456}
457
458impl<T> PartialEq<T> for JSONValue
459    where JSONValue: Cast<T>,
460    T: PartialEq<T>,
461{
462    fn eq(&self, other: &T) -> bool {
463        let res: Result<T> = self.cast();
464        match res {
465            Ok(v) => &v == other,
466            Err(_) => false,
467        }
468    }
469}