pub mod error;
pub mod parse;
pub mod format;
pub use bournemacro::json;
#[cfg(not(feature = "preserve_order"))]
pub type ValueMap = hashbrown::HashMap<String, Value>;
#[cfg(feature = "preserve_order")]
pub type ValueMap = indexmap::IndexMap<String, Value>;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum Number {
Float(f64),
Int(i64),
}
#[derive(Debug, Clone)]
pub enum Value {
Null,
Boolean(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(ValueMap),
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Boolean(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value::Number(Number::Float(value))
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Value::String(value)
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Value::String(value.to_owned())
}
}
impl From<Vec<Value>> for Value {
fn from(value: Vec<Value>) -> Self {
Value::Array(value)
}
}
impl From<ValueMap> for Value {
fn from(value: ValueMap) -> Self {
Value::Object(value)
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Value::Number(Number::Int(value))
}
}
pub trait IndexOrKey {
fn get(self, value: &Value) -> Option<&Value>;
fn get_mut(self, value: &mut Value) -> Option<&mut Value>;
fn get_or_insert(self, value: &mut Value) -> &mut Value;
}
impl IndexOrKey for usize {
fn get(self, value: &Value) -> Option<&Value> {
let Value::Array(array) = value else {
return None;
};
array.get(self)
}
fn get_mut(self, value: &mut Value) -> Option<&mut Value> {
let Value::Array(array) = value else {
return None;
};
array.get_mut(self)
}
fn get_or_insert(self, _value: &mut Value) -> &mut Value {
let Value::Array(array) = _value else {
panic!("Not an array.");
};
&mut array[self]
}
}
impl IndexOrKey for &str {
fn get(self, value: &Value) -> Option<&Value> {
let Value::Object(object) = value else {
return None;
};
object.get(self)
}
fn get_mut(self, value: &mut Value) -> Option<&mut Value> {
let Value::Object(object) = value else {
return None;
};
object.get_mut(self)
}
fn get_or_insert(self, value: &mut Value) -> &mut Value {
if let Value::Null = value {
*value = Value::Object(ValueMap::new());
}
let Value::Object(object) = value else {
panic!("Not an object.");
};
object.entry(self.to_owned()).or_insert(Value::Null)
}
}
impl IndexOrKey for String {
fn get(self, value: &Value) -> Option<&Value> {
let Value::Object(object) = value else {
return None;
};
object.get(&self)
}
fn get_mut(self, value: &mut Value) -> Option<&mut Value> {
let Value::Object(object) = value else {
return None;
};
object.get_mut(&self)
}
fn get_or_insert(self, value: &mut Value) -> &mut Value {
if let Value::Null = value {
*value = Value::Object(ValueMap::new());
}
let Value::Object(object) = value else {
panic!("Not an object.");
};
object.entry(self).or_insert(Value::Null)
}
}
pub trait InsertKey {
fn insert_into(self, map: &mut ValueMap, value: Value) -> Option<Value>;
}
impl InsertKey for String {
fn insert_into(self, map: &mut ValueMap, value: Value) -> Option<Value> {
map.insert(self, value)
}
}
impl InsertKey for &str {
fn insert_into(self, map: &mut ValueMap, value: Value) -> Option<Value> {
map.insert(self.to_owned(), value)
}
}
impl Value {
pub fn push<T: Into<Value>>(&mut self, value: T) {
if let Value::Null = self {
*self = Value::Array(Vec::new());
}
let Value::Array(array) = self else {
panic!("Not an array.");
};
array.push(value.into());
}
pub fn insert<T: Into<Value>, K: InsertKey>(&mut self, k: K, v: T) -> Option<Value> {
if let Value::Null = self {
*self = Value::Object(ValueMap::new());
}
let Value::Object(object) = self else {
panic!("Not an object.");
};
k.insert_into(object, v.into())
}
pub fn get<I: IndexOrKey>(&self, i_k: I) -> Option<&Value> {
i_k.get(self)
}
pub fn get_mut<I: IndexOrKey>(&mut self, i_k: I) -> Option<&mut Value> {
i_k.get_mut(self)
}
pub fn len(&self) -> usize {
match self {
Value::String(string) => string.len(),
Value::Array(array) => array.len(),
Value::Object(object) => object.len(),
_ => 0,
}
}
}
impl<I: IndexOrKey> std::ops::Index<I> for Value {
type Output = Value;
fn index(&self, index: I) -> &Self::Output {
static NULL: Value = Value::Null;
index.get(self).unwrap_or(&NULL)
}
}
impl<I: IndexOrKey> std::ops::IndexMut<I> for Value {
fn index_mut(&mut self, index: I) -> &mut Self::Output {
index.get_or_insert(self)
}
}
pub trait ArrayExt {
fn push_value<T: Into<Value>>(&mut self, value: T);
}
impl ArrayExt for Vec<Value> {
fn push_value<T: Into<Value>>(&mut self, value: T) {
self.push(value.into());
}
}
pub trait ObjectExt {
fn insert_value<T: Into<Value>>(&mut self, key: String, value: T) -> Option<Value>;
}
impl ObjectExt for ValueMap {
fn insert_value<T: Into<Value>>(&mut self, k: String, v: T) -> Option<Value> {
self.insert(k, v.into())
}
}
#[cfg(test)]
mod tests {
use core::f64;
use std::str::FromStr;
use super::*;
#[test]
fn parse_number_test() -> Result<(), crate::error::ParseError> {
let object = Value::from_str(r#"
{
"int": 9223372036854775807,
"float": 3.14159265358979
}
"#)?;
assert!(matches!(object["int"], Value::Number(Number::Int(i64::MAX))));
assert!(matches!(object["float"], Value::Number(Number::Float(3.14159265358979))));
let json_text = object.to_string();
assert_eq!(json_text, r#"{"int":9223372036854775807,"float":3.14159265358979}"#);
Ok(())
}
#[test]
fn float_nan_infinity_test() {
use crate as bourne;
let value = json!({
"nan": f64::NAN,
"infinity": f64::INFINITY,
"min_positive": f64::MIN_POSITIVE,
"min": f64::MIN,
"max": f64::MAX,
});
println!("{value}");
}
}