bourne/
lib.rs

1pub mod error;
2pub mod parse;
3pub mod format;
4pub use bournemacro::json;
5
6/// The Mapping that [Value] uses for [Value::Object].  
7/// Uses [hashbrown::HashMap].
8#[cfg(not(feature = "preserve_order"))]
9pub type ValueMap = hashbrown::HashMap<String, Value>;
10/// The Mapping that [Value] uses for [Value::Object].  
11/// Uses [indexmap::IndexMap] (`preserve_order` feature is on)
12#[cfg(feature = "preserve_order")]
13pub type ValueMap = indexmap::IndexMap<String, Value>;
14
15#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
16pub enum Number {
17    Float(f64),
18    Int(i64),
19}
20
21/// JSON Value.
22#[derive(Debug, Clone)]
23pub enum Value {
24    /// Null value.
25    /// ```no_run,json
26    /// null
27    /// ```
28    Null,
29    /// A boolean value.
30    /// ```no_run,json
31    /// true
32    /// ```
33    /// or
34    /// ```no_run,json
35    /// false
36    /// ```
37    Boolean(bool),
38    /// An [f64] or [i64] number.
39    /// ```no_run,json
40    /// 3.14159265358979
41    /// ```
42    Number(Number),
43    /// A UTF-8 encoded string.
44    /// ```no_run,json
45    /// "The quick brown fox jumps over the lazy dog.\nhello, world"
46    /// ```
47    /// The following characters must be escaped:  
48    /// * `\u{0}`to `\u{1f}` (inclusive)
49    /// * `\n` (newline)
50    /// * `\r` (carriage return)
51    /// * `\t` (tab) (optional)
52    /// * `"`
53    /// * `'` (optional)
54    /// * `\`
55    /// * `/` (optional)
56    /// * `\u{8}`
57    /// * `\u{c}`
58    String(String),
59    /// An array of JSON [Value]s.
60    /// ```no_run,json
61    /// [
62    ///     "hello, world",
63    ///     1234,
64    ///     3.14,
65    ///     true,
66    ///     false,
67    ///     null,
68    /// ]
69    /// ```
70    Array(Vec<Value>),
71    /// A Mapping of JSON [Value]s by their name.
72    /// ```no_run,json
73    /// {
74    ///     "tag": null,
75    ///     "registered": true,
76    ///     "age": 197,
77    ///     "name": "Fred",
78    ///     "classes": [
79    ///         "Algebra",
80    ///         "History of Programming",
81    ///         "Algorithms and Datastructures",
82    ///         "Cryptography",
83    ///     ],
84    ///     "rgb_for_some_reason": {
85    ///         "r": 4,
86    ///         "g": 7
87    ///         "b": 3,
88    ///     }
89    /// }
90    /// ```
91    Object(ValueMap),
92}
93
94impl From<bool> for Value {
95    /// Create a [Value] from a [bool].
96    fn from(value: bool) -> Self {
97        Value::Boolean(value)
98    }
99}
100
101impl From<f64> for Value {
102    /// Create a [Value] from an [f64].
103    fn from(value: f64) -> Self {
104        Value::Number(Number::Float(value))
105    }
106}
107
108impl From<String> for Value {
109    /// Create a [Value] from a [String].
110    fn from(value: String) -> Self {
111        Value::String(value)
112    }
113}
114
115impl From<&str> for Value {
116    /// Create a [Value] from string.
117    fn from(value: &str) -> Self {
118        Value::String(value.to_owned())
119    }
120}
121
122impl From<Vec<Value>> for Value {
123    /// Create a [Value] from a [Vec<Value>]
124    fn from(value: Vec<Value>) -> Self {
125        Value::Array(value)
126    }
127}
128
129impl From<ValueMap> for Value {
130    /// Create a [Value] from a [ValueMap]. (`hashbrown::HashMap` when not `preserve_order`, `indexmap::IndexMap` when `preserve_order`)
131    fn from(value: ValueMap) -> Self {
132        Value::Object(value)
133    }
134}
135
136impl From<i64> for Value {
137    /// Create a [Value] from an [i64]. Note that there is loss in precision because this value will be converted to [f64].
138    fn from(value: i64) -> Self {
139        Value::Number(Number::Int(value))
140    }
141}
142
143/// Allows for indexing into a [Value] by [String] or [usize]
144pub trait IndexOrKey {
145    /// Get an immutable reference to a [Value].
146    fn get(self, value: &Value) -> Option<&Value>;
147    /// Get a mutable reference to a [Value].
148    fn get_mut(self, value: &mut Value) -> Option<&mut Value>;
149    /// Get a mutable reference or insert [Value::Null] and return a mutable reference to that.
150    fn get_or_insert(self, value: &mut Value) -> &mut Value;
151}
152
153impl IndexOrKey for usize {
154    /// Get an immutable reference to a [Value] in a [Value::Array].
155    fn get(self, value: &Value) -> Option<&Value> {
156        let Value::Array(array) = value else {
157            return None;
158        };
159        array.get(self)
160    }
161
162    /// Get an immutable reference to a [Value] in a [Value::Array].
163    fn get_mut(self, value: &mut Value) -> Option<&mut Value> {
164        let Value::Array(array) = value else {
165            return None;
166        };
167        array.get_mut(self)
168    }
169
170    /// Get a mutable refence to a [Value] in a [Value::Array]. This function will panic if
171    /// the [Value] is not an array.
172    fn get_or_insert(self, _value: &mut Value) -> &mut Value {
173        let Value::Array(array) = _value else {
174            panic!("Not an array.");
175        };
176        &mut array[self]
177    }
178}
179
180impl IndexOrKey for &str {
181    /// Get an immutable reference to a [Value] in a [Value::Object].
182    fn get(self, value: &Value) -> Option<&Value> {
183        let Value::Object(object) = value else {
184            return None;
185        };
186        object.get(self)
187    }
188
189    /// Get a mutable reference to a [Value] in a [Value::Object].
190    fn get_mut(self, value: &mut Value) -> Option<&mut Value> {
191        let Value::Object(object) = value else {
192            return None;
193        };
194        object.get_mut(self)
195    }
196
197    /// Get a mutable reference to a [Value] in a [Value::Object] if it exists, otherwise
198    /// insert [Value::Null] and return a mutable reference to that.
199    fn get_or_insert(self, value: &mut Value) -> &mut Value {
200        if let Value::Null = value {
201            *value = Value::Object(ValueMap::new());
202        }
203        let Value::Object(object) = value else {
204            panic!("Not an object.");
205        };
206        object.entry(self.to_owned()).or_insert(Value::Null)
207    }
208}
209
210impl IndexOrKey for String {
211    /// Get an immutable reference to a [Value] in a [Value::Object].
212    fn get(self, value: &Value) -> Option<&Value> {
213        let Value::Object(object) = value else {
214            return None;
215        };
216        object.get(&self)
217    }
218
219    /// Get a mutable reference to a [Value] in a [Value::Object].
220    fn get_mut(self, value: &mut Value) -> Option<&mut Value> {
221        let Value::Object(object) = value else {
222            return None;
223        };
224        object.get_mut(&self)
225    }
226
227    /// Get a mutable reference to a [Value] in a [Value::Object] if it exists, otherwise
228    /// insert [Value::Null] and return a mutable reference to that.
229    fn get_or_insert(self, value: &mut Value) -> &mut Value {
230        if let Value::Null = value {
231            *value = Value::Object(ValueMap::new());
232        }
233        let Value::Object(object) = value else {
234            panic!("Not an object.");
235        };
236        object.entry(self).or_insert(Value::Null)
237    }
238}
239
240// By implementing InsertKey for String and &str, I can make Value::insert(k, v) generic for the key type.
241pub trait InsertKey {
242    fn insert_into(self, map: &mut ValueMap, value: Value) -> Option<Value>;
243}
244
245impl InsertKey for String {
246    fn insert_into(self, map: &mut ValueMap, value: Value) -> Option<Value> {
247        map.insert(self, value)
248    }
249}
250
251impl InsertKey for &str {
252    fn insert_into(self, map: &mut ValueMap, value: Value) -> Option<Value> {
253        map.insert(self.to_owned(), value)
254    }
255}
256
257impl Value {
258    /// Push `value` into a [Value::Array]. If the [Value] is [Value::Null], convert it
259    /// into a [Value::Array] and push `value` into it.
260    /// 
261    /// Panics if self [Value] is not [Value::Null] or [Value::Array].
262    pub fn push<T: Into<Value>>(&mut self, value: T) {
263        if let Value::Null = self {
264            *self = Value::Array(Vec::new());
265        }
266        let Value::Array(array) = self else {
267            panic!("Not an array.");
268        };
269        array.push(value.into());
270    }
271
272    /// Insert `value` into a [Value::Object]. If the [Value] is [Value::Null], convert it
273    /// into a [Value::Array] and insert `value` into it.
274    /// 
275    /// Panics if self [Value] is not [Value::Null] or [Value::Array].
276    pub fn insert<T: Into<Value>, K: InsertKey>(&mut self, k: K, v: T) -> Option<Value> {
277        if let Value::Null = self {
278            *self = Value::Object(ValueMap::new());
279        }
280        let Value::Object(object) = self else {
281            panic!("Not an object.");
282        };
283        k.insert_into(object, v.into())
284    }
285
286    /// Get an immutable reference to a [Value] by index or key.
287    pub fn get<I: IndexOrKey>(&self, i_k: I) -> Option<&Value> {
288        i_k.get(self)
289    }
290
291    /// Get a mutable reference to a [Value] by index or key.
292    pub fn get_mut<I: IndexOrKey>(&mut self, i_k: I) -> Option<&mut Value> {
293        i_k.get_mut(self)
294    }
295
296    /// Get the length of the [Value] if it is one of the following variants:
297    /// * [Value::String]
298    /// * [Value::Array]
299    /// * [Value::Object]
300    pub fn len(&self) -> usize {
301        match self {
302            Value::String(string) => string.len(),
303            Value::Array(array) => array.len(),
304            Value::Object(object) => object.len(),
305            _ => 0,
306        }
307    }
308}
309
310impl<I: IndexOrKey> std::ops::Index<I> for Value {
311    type Output = Value;
312    fn index(&self, index: I) -> &Self::Output {
313        static NULL: Value = Value::Null;
314        index.get(self).unwrap_or(&NULL)
315    }
316}
317
318impl<I: IndexOrKey> std::ops::IndexMut<I> for Value {
319    fn index_mut(&mut self, index: I) -> &mut Self::Output {
320        index.get_or_insert(self)
321    }
322}
323
324pub trait ArrayExt {
325    fn push_value<T: Into<Value>>(&mut self, value: T);
326}
327
328impl ArrayExt for Vec<Value> {
329    fn push_value<T: Into<Value>>(&mut self, value: T) {
330        self.push(value.into());
331    }
332}
333
334pub trait ObjectExt {
335    fn insert_value<T: Into<Value>>(&mut self, key: String, value: T) -> Option<Value>;
336}
337
338impl ObjectExt for ValueMap {
339    fn insert_value<T: Into<Value>>(&mut self, k: String, v: T) -> Option<Value> {
340        self.insert(k, v.into())
341    }
342}
343
344#[cfg(test)]
345mod tests {
346    use core::f64;
347    use std::str::FromStr;
348
349    use super::*;
350    #[test]
351    fn parse_number_test() -> Result<(), crate::error::ParseError> {
352        let object = Value::from_str(r#"
353            {
354                "int": 9223372036854775807,
355                "float": 3.14159265358979
356            }
357        "#)?;
358        assert!(matches!(object["int"], Value::Number(Number::Int(i64::MAX))));
359        assert!(matches!(object["float"], Value::Number(Number::Float(3.14159265358979))));
360        let json_text = object.to_string();
361        assert_eq!(json_text, r#"{"int":9223372036854775807,"float":3.14159265358979}"#);
362        Ok(())
363    }
364
365    #[test]
366    fn float_nan_infinity_test() {
367        use crate as bourne;
368        let value = json!({
369            "nan": f64::NAN,
370            "infinity": f64::INFINITY,
371            "min_positive": f64::MIN_POSITIVE,
372            "min": f64::MIN,
373            "max": f64::MAX,
374        });
375        println!("{value}");
376    }
377}