use std::cmp::{Ord, Ordering, PartialOrd};
use std::convert::{From, TryFrom, TryInto};
use std::default::Default;
use std::fmt::{self, Display, Write};
use std::ops::RangeBounds;
use std::str::FromStr;
use crate::error::{Error, Result};
use crate::lex::Lex;
use crate::num::{Floating, Integral};
use crate::parse::parse_value;
use crate::property::{self, Property};
use crate::{jptr, ops};
#[derive(Clone, Debug)]
pub enum Json {
Null,
Bool(bool),
Integer(Integral),
Float(Floating),
String(String),
Array(Vec<Json>),
Object(Vec<Property>),
#[doc(hidden)]
__Error(Error),
#[doc(hidden)]
__Minbound,
#[doc(hidden)]
__Maxbound,
}
impl Json {
pub fn new<T>(value: T) -> Json
where
Self: From<T>,
{
value.into()
}
#[allow(dead_code)]
pub(crate) fn minbound() -> Json {
Json::__Minbound
}
#[allow(dead_code)]
pub(crate) fn maxbound() -> Json {
Json::__Maxbound
}
pub fn validate(&mut self) -> Result<()> {
use crate::json::Json::{Array, Float, Integer, Object};
match self {
Array(items) => {
for item in items.iter_mut() {
item.validate()?
}
}
Object(props) => {
for prop in props.iter_mut() {
prop.as_mut_value().validate()?
}
}
Integer(item) => {
item.compute()?;
}
Float(item) => {
item.compute()?;
}
_ => (),
};
Ok(())
}
pub fn compute(&mut self) -> Result<()> {
use crate::json::Json::{Array, Float, Integer, Object};
match self {
Array(items) => {
for item in items.iter_mut() {
item.compute()?
}
}
Object(props) => {
for prop in props.iter_mut() {
prop.as_mut_value().compute()?
}
}
Integer(item) => {
item.compute()?;
}
Float(item) => {
item.compute()?;
}
_ => (),
};
Ok(())
}
pub fn typename(&self) -> String {
match self {
Json::Null => "null".to_string(),
Json::Bool(_) => "bool".to_string(),
Json::Integer(_) => "integer".to_string(),
Json::Float(_) => "float".to_string(),
Json::String(_) => "string".to_string(),
Json::Array(_) => "array".to_string(),
Json::Object(_) => "object".to_string(),
Json::__Error(_) => "error".to_string(),
Json::__Minbound => "minbound".to_string(),
Json::__Maxbound => "maxbound".to_string(),
}
}
}
impl Json {
pub fn get(&self, path: &str) -> Result<Json> {
if path.is_empty() {
Ok(self.clone())
} else {
let path = jptr::fix_prefix(path)?;
let (json, key) = jptr::lookup_ref(self, path)?;
Ok(json[key.as_str()].to_result()?.clone())
}
}
pub fn set(&mut self, path: &str, value: Json) -> Result<()> {
if path.is_empty() {
return Ok(());
}
let path = jptr::fix_prefix(path)?;
let (json, frag) = jptr::lookup_mut(self, path)?;
match json {
Json::Array(arr) => match frag.parse::<usize>() {
Ok(n) => {
if n >= arr.len() {
Err(Error::IndexOutofBound(n.try_into().unwrap()))
} else {
arr[n] = value;
Ok(())
}
}
Err(err) => Err(Error::InvalidIndex(err.to_string())),
},
Json::Object(props) => match property::search_by_key(&props, &frag) {
Ok(n) => {
props[n].set_value(value);
Ok(())
}
Err(n) => {
props.insert(n, Property::new(frag, value));
Ok(())
}
},
_ => Err(Error::InvalidContainer(json.typename())),
}
}
pub fn delete(&mut self, path: &str) -> Result<()> {
if path.is_empty() {
return Ok(());
}
let path = jptr::fix_prefix(path)?;
let (json, frag) = jptr::lookup_mut(self, path)?;
match json {
Json::Array(arr) => match frag.parse::<usize>() {
Ok(n) => {
if n >= arr.len() {
Err(Error::IndexOutofBound(n.try_into().unwrap()))
} else {
arr.remove(n);
Ok(())
}
}
Err(err) => Err(Error::InvalidIndex(err.to_string())),
},
Json::Object(props) => match property::search_by_key(&props, &frag) {
Ok(n) => {
props.remove(n);
Ok(())
}
Err(_) => Err(Error::PropertyNotFound(frag)),
},
_ => Err(Error::InvalidContainer(json.typename())),
}
}
pub fn append(&mut self, path: &str, value: Json) -> Result<()> {
if path.is_empty() {
return Ok(());
}
let path = jptr::fix_prefix(path)?;
let (json, frag) = jptr::lookup_mut(self, path)?;
match ops::index_mut(json, frag.as_str())? {
Json::String(j) => {
if let Json::String(s) = value {
j.push_str(&s);
Ok(())
} else {
Err(Error::AppendString(value.typename()))
}
}
Json::Array(arr) => {
let n = arr.len();
arr.insert(n, value);
Ok(())
}
_ => Err(Error::InvalidContainer(json.typename())),
}
}
pub fn range<R>(&self, range: R) -> Json
where
R: RangeBounds<isize>,
{
use std::ops::Bound::{Excluded, Included, Unbounded};
match self {
Json::__Error(_) => self.clone(),
Json::Array(arr) => {
let (start, s) = match range.start_bound() {
Included(n) => (ops::normalized_offset(*n, arr.len()), *n),
Excluded(n) => (ops::normalized_offset((*n) + 1, arr.len()), *n),
Unbounded => (Some(0), 0),
};
let (end, e) = match range.end_bound() {
Included(n) => (ops::normalized_offset((*n) + 1, arr.len()), *n),
Excluded(n) => (ops::normalized_offset(*n, arr.len()), *n),
Unbounded => (Some(arr.len()), arr.len().try_into().unwrap()),
};
match (start, end) {
(Some(start), Some(end)) => Json::Array(arr[start..end].to_vec()),
(None, _) => Json::__Error(Error::IndexOutofBound(s)),
(_, None) => Json::__Error(Error::IndexOutofBound(e)),
}
}
_ => Json::__Error(Error::NotAnArray(format!("{}", self))),
}
}
}
impl Json {
pub fn is_null(&self) -> bool {
matches!(self, Json::Null)
}
pub fn to_bool(&self) -> Option<bool> {
match self {
Json::Bool(s) => Some(*s),
_ => None,
}
}
pub fn to_integer(&self) -> Option<i128> {
match self {
Json::Integer(item) => item.integer(),
_ => None,
}
}
pub fn to_float(&self) -> Option<f64> {
match self {
Json::Float(item) => item.float(),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Json::String(s) => Some(s),
_ => None,
}
}
pub fn to_array(&self) -> Option<Vec<Json>> {
match self {
Json::Array(arr) => Some(arr.clone()),
_ => None,
}
}
pub fn to_object(&self) -> Option<Vec<Property>> {
match self {
Json::Object(obj) => Some(obj.clone()),
_ => None,
}
}
pub fn is_error(&self) -> bool {
matches!(self, Json::__Error(_))
}
pub fn to_error(&self) -> Option<Error> {
match self {
Json::__Error(err) => Some(err.clone()),
_ => None,
}
}
pub fn to_result(&self) -> Result<&Json> {
match self {
Json::__Error(err) => Err(err.clone()),
_ => Ok(self),
}
}
}
impl Eq for Json {}
impl PartialEq for Json {
fn eq(&self, other: &Json) -> bool {
use crate::Json::{Array, Bool, Float, Integer, Null, Object, String as S};
use std::i128;
match (self, other) {
(Null, Null) => true,
(Bool(a), Bool(b)) => a == b,
(Integer(_), Integer(_)) => self.to_integer() == other.to_integer(),
(Integer(a), Float(b)) => match (a.integer(), b.float()) {
(Some(x), Some(y)) => {
let num = y as i128;
if num == i128::MIN || num == i128::MAX || y.is_nan() {
return false;
}
x == num
}
_ => false,
},
(Float(_), Float(_)) => {
let (fs, fo) = (self.to_float().unwrap(), other.to_float().unwrap());
if fs.is_finite() && fo.is_finite() {
return fs == fo;
} else if fs.is_nan() && fo.is_nan() {
return true;
} else if fs.is_infinite() && fo.is_infinite() {
return fs.is_sign_positive() == fo.is_sign_positive();
}
false
}
(Float(a), Integer(b)) => match (a.float(), b.integer()) {
(Some(x), Some(y)) => {
let num = x as i128;
if num == i128::MIN || num == i128::MAX || x.is_nan() {
return false;
}
y == num
}
_ => false,
},
(S(a), S(b)) => a == b,
(Array(a), Array(b)) => a == b,
(Object(a), Object(b)) => a == b,
(Json::__Minbound, Json::__Minbound) => true,
(Json::__Maxbound, Json::__Maxbound) => true,
_ => false,
}
}
}
impl PartialOrd for Json {
fn partial_cmp(&self, other: &Json) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Json {
fn cmp(&self, other: &Json) -> Ordering {
use crate::Json::{Array, Bool, Float, Integer, Null, Object, String as S};
match (self, other) {
(Null, Null) => Ordering::Equal,
(Bool(a), Bool(b)) => {
if (*a) == (*b) {
Ordering::Equal
} else if !(*a) {
Ordering::Less
} else {
Ordering::Greater
}
}
(Integer(a), Integer(b)) => {
let (x, y) = (a.integer().unwrap(), b.integer().unwrap());
x.cmp(&y)
}
(Float(a), Float(b)) => {
let (fs, fo) = (a.float().unwrap(), b.float().unwrap());
if fs.is_finite() && fo.is_finite() {
if fs < fo {
Ordering::Less
} else if fs > fo {
Ordering::Greater
} else if fs == 0.0 || fo == 0.0 {
if fs.is_sign_negative() {
Ordering::Less
} else if fo.is_sign_negative() {
Ordering::Greater
} else {
Ordering::Equal
}
} else {
Ordering::Equal
}
} else {
let is = if fs.is_infinite() {
fs.signum() as i32
} else {
2
};
let io = if fo.is_infinite() {
fo.signum() as i32
} else {
2
};
is.cmp(&io)
}
}
(Integer(a), Float(b)) => match (a.integer(), b.float()) {
(Some(x), Some(y)) => x.cmp(&(y as i128)),
(Some(_), None) => Ordering::Greater,
(None, Some(_)) => Ordering::Less,
(None, None) => Ordering::Equal,
},
(Float(a), Integer(b)) => match (a.float(), b.integer()) {
(Some(x), Some(y)) => (x as i128).cmp(&y),
(Some(_), None) => Ordering::Greater,
(None, Some(_)) => Ordering::Less,
(None, None) => Ordering::Equal,
},
(S(a), S(b)) => a.cmp(b),
(Array(this), Array(that)) => {
for (i, a) in this.iter().enumerate() {
if i == that.len() {
return Ordering::Greater;
}
let cmp = a.cmp(&that[i]);
if cmp != Ordering::Equal {
return cmp;
}
}
if this.len() == that.len() {
Ordering::Equal
} else {
Ordering::Less
}
}
(Object(this), Object(that)) => {
for (i, a) in this.iter().enumerate() {
if i == that.len() {
return Ordering::Greater;
}
let cmp = a.as_ref_key().cmp(that[i].as_ref_key());
if cmp != Ordering::Equal {
return cmp;
}
let cmp = a.as_ref_value().cmp(that[i].as_ref_value());
if cmp != Ordering::Equal {
return cmp;
}
}
if this.len() == that.len() {
Ordering::Equal
} else {
Ordering::Less
}
}
(_, Json::__Error(_)) => Ordering::Less,
(Json::__Error(_), _) => Ordering::Greater,
(Json::__Minbound, Json::__Minbound) => Ordering::Equal,
(Json::__Maxbound, Json::__Maxbound) => Ordering::Equal,
(Json::__Minbound, _) => Ordering::Less,
(Json::__Maxbound, _) => Ordering::Greater,
(_, Json::__Minbound) => Ordering::Greater,
(_, Json::__Maxbound) => Ordering::Less,
(Null, _) => Ordering::Less,
(_, Null) => Ordering::Greater,
(Bool(_), _) => Ordering::Less,
(_, Bool(_)) => Ordering::Greater,
(Integer(_), _) => Ordering::Less,
(_, Integer(_)) => Ordering::Greater,
(Float(_), _) => Ordering::Less,
(_, Float(_)) => Ordering::Greater,
(S(_), _) => Ordering::Less,
(_, S(_)) => Ordering::Greater,
(Array(_), _) => Ordering::Less,
(_, Array(_)) => Ordering::Greater,
}
}
}
impl Default for Json {
fn default() -> Json {
Json::Null
}
}
impl From<bool> for Json {
fn from(val: bool) -> Json {
Json::Bool(val)
}
}
impl From<u8> for Json {
fn from(num: u8) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<i8> for Json {
fn from(num: i8) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<u16> for Json {
fn from(num: u16) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<i16> for Json {
fn from(num: i16) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<u32> for Json {
fn from(num: u32) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<i32> for Json {
fn from(num: i32) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<u64> for Json {
fn from(num: u64) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<i64> for Json {
fn from(num: i64) -> Json {
let num: i128 = num.into();
Json::Integer(Integral::new(num))
}
}
impl From<u128> for Json {
fn from(num: u128) -> Json {
let inum: i128 = num.try_into().unwrap();
Json::Integer(Integral::new(inum))
}
}
impl From<i128> for Json {
fn from(val: i128) -> Json {
Json::Integer(Integral::new(val))
}
}
impl From<usize> for Json {
fn from(num: usize) -> Json {
let inum: i128 = num.try_into().unwrap();
Json::Integer(Integral::new(inum))
}
}
impl From<isize> for Json {
fn from(num: isize) -> Json {
let inum: i128 = num.try_into().unwrap();
Json::Integer(Integral::new(inum))
}
}
impl TryFrom<Json> for u8 {
type Error = Error;
fn try_from(val: Json) -> Result<u8> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for i8 {
type Error = Error;
fn try_from(val: Json) -> Result<i8> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for u16 {
type Error = Error;
fn try_from(val: Json) -> Result<u16> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for i16 {
type Error = Error;
fn try_from(val: Json) -> Result<i16> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for u32 {
type Error = Error;
fn try_from(val: Json) -> Result<u32> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for i32 {
type Error = Error;
fn try_from(val: Json) -> Result<i32> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for u64 {
type Error = Error;
fn try_from(val: Json) -> Result<u64> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for i64 {
type Error = Error;
fn try_from(val: Json) -> Result<i64> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for u128 {
type Error = Error;
fn try_from(val: Json) -> Result<u128> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for i128 {
type Error = Error;
fn try_from(val: Json) -> Result<i128> {
match val.to_integer() {
Some(val) => Ok(val),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for usize {
type Error = Error;
fn try_from(val: Json) -> Result<usize> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for isize {
type Error = Error;
fn try_from(val: Json) -> Result<isize> {
match val.to_integer() {
Some(val) => match val.try_into() {
Ok(val) => Ok(val),
Err(err) => Err(Error::InvalidNumber(err.to_string())),
},
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for f32 {
type Error = Error;
fn try_from(val: Json) -> Result<f32> {
match val.to_float() {
Some(val) if (((val as f32) as f64) - val).abs() > f64::EPSILON => {
Err(Error::InvalidNumber(val.to_string()))
}
Some(val) => Ok(val as f32),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for f64 {
type Error = Error;
fn try_from(val: Json) -> Result<f64> {
match val.to_float() {
Some(val) => Ok(val),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for String {
type Error = Error;
fn try_from(val: Json) -> Result<String> {
match val.as_str() {
Some(s) => Ok(s.to_string()),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl TryFrom<Json> for Vec<Property> {
type Error = Error;
fn try_from(val: Json) -> Result<Vec<Property>> {
match val.to_object() {
Some(val) => Ok(val),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl<T> TryFrom<Json> for (T,)
where
T: TryFrom<Json, Error = Error>,
{
type Error = Error;
fn try_from(val: Json) -> Result<(T,)> {
match val.to_array() {
Some(val) if val.len() == 1 => Ok((val[0].clone().try_into()?,)),
Some(v) => Err(Error::InvalidType(format!(
"{} tuple-arity-1 {}",
val.typename(),
v.len(),
))),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl<U, V> TryFrom<Json> for (U, V)
where
U: TryFrom<Json, Error = Error>,
V: TryFrom<Json, Error = Error>,
{
type Error = Error;
fn try_from(val: Json) -> Result<(U, V)> {
match val.to_array() {
Some(val) if val.len() == 2 => {
Ok((val[0].clone().try_into()?, val[1].clone().try_into()?))
}
Some(v) => Err(Error::InvalidType(format!(
"{} tuple-arity-2 {}",
val.typename(),
v.len(),
))),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl<A, B, C> TryFrom<Json> for (A, B, C)
where
A: TryFrom<Json, Error = Error>,
B: TryFrom<Json, Error = Error>,
C: TryFrom<Json, Error = Error>,
{
type Error = Error;
fn try_from(val: Json) -> Result<(A, B, C)> {
match val.to_array() {
Some(val) if val.len() == 3 => Ok((
val[0].clone().try_into()?,
val[1].clone().try_into()?,
val[2].clone().try_into()?,
)),
Some(v) => Err(Error::InvalidType(format!(
"{} tuple-arity-3 {}",
val.typename(),
v.len()
))),
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl<T> From<Vec<T>> for Json
where
T: Into<Json>,
{
fn from(val: Vec<T>) -> Json {
let inner: Vec<Json> = val.into_iter().map(|v| v.into()).collect();
Json::Array(inner)
}
}
impl<T> TryFrom<Json> for Vec<T>
where
T: TryFrom<Json, Error = Error>,
{
type Error = Error;
fn try_from(val: Json) -> Result<Vec<T>> {
match val.to_array() {
Some(val) => {
let mut out = vec![];
for v in val.into_iter() {
out.push(v.try_into()?);
}
Ok(out)
}
None => Err(Error::InvalidType(val.typename())),
}
}
}
impl From<f32> for Json {
fn from(num: f32) -> Json {
let num: f64 = num.into();
Json::Float(Floating::new(num))
}
}
impl From<f64> for Json {
fn from(num: f64) -> Json {
Json::Float(Floating::new(num))
}
}
impl From<String> for Json {
fn from(val: String) -> Json {
Json::String(val)
}
}
impl From<&str> for Json {
fn from(val: &str) -> Json {
Json::String(val.to_string())
}
}
impl From<Vec<Property>> for Json {
fn from(val: Vec<Property>) -> Json {
let mut obj = Json::Object(vec![]);
val.into_iter().for_each(|item| insert(&mut obj, item));
obj
}
}
impl<T> From<(T,)> for Json
where
T: Into<Json>,
{
fn from(val: (T,)) -> Json {
Json::Array(vec![val.0.into()])
}
}
impl<U, V> From<(U, V)> for Json
where
U: Into<Json>,
V: Into<Json>,
{
fn from(val: (U, V)) -> Json {
let inner = vec![val.0.into(), val.1.into()];
Json::Array(inner)
}
}
impl<A, B, C> From<(A, B, C)> for Json
where
A: Into<Json>,
B: Into<Json>,
C: Into<Json>,
{
fn from(val: (A, B, C)) -> Json {
let inner = vec![val.0.into(), val.1.into(), val.2.into()];
Json::Array(inner)
}
}
impl From<Json> for bool {
fn from(val: Json) -> bool {
use crate::json::Json::String as S;
use crate::json::Json::{Array, Bool, Float, Integer, Null, Object};
match val {
Null => false,
Bool(v) => v,
Integer(_) => val.to_integer().unwrap() != 0,
Float(_) => val.to_float().unwrap() != 0.0,
S(s) => !s.is_empty(),
Array(a) => !a.is_empty(),
Object(o) => !o.is_empty(),
Json::__Error(_) => false,
Json::__Minbound => true,
Json::__Maxbound => true,
}
}
}
impl FromStr for Json {
type Err = Error;
fn from_str(text: &str) -> Result<Json> {
let mut lex = Lex::new(0, 1, 1);
parse_value(&text, &mut lex)
}
}
impl AsRef<str> for Json {
fn as_ref(&self) -> &str {
match self {
Json::String(s) => s,
_ => panic!("Json is not string"),
}
}
}
impl AsRef<Vec<Json>> for Json {
fn as_ref(&self) -> &Vec<Json> {
match self {
Json::Array(arr) => arr,
_ => panic!("Json is not an array"),
}
}
}
impl AsRef<Vec<Property>> for Json {
fn as_ref(&self) -> &Vec<Property> {
match self {
Json::Object(obj) => obj,
_ => panic!("Json is not an object"),
}
}
}
impl AsMut<str> for Json {
fn as_mut(&mut self) -> &mut str {
match self {
Json::String(s) => s,
_ => panic!("Json is not string"),
}
}
}
impl AsMut<Vec<Json>> for Json {
fn as_mut(&mut self) -> &mut Vec<Json> {
match self {
Json::Array(arr) => arr,
_ => panic!("Json is not an array"),
}
}
}
impl AsMut<Vec<Property>> for Json {
fn as_mut(&mut self) -> &mut Vec<Property> {
match self {
Json::Object(obj) => obj,
_ => panic!("Json is not an object"),
}
}
}
impl Display for Json {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Json::{Array, Bool, Float, Integer, Null, Object, String as S};
use std::str::from_utf8;
match self {
Null => write!(f, "null"),
Bool(true) => write!(f, "true"),
Bool(false) => write!(f, "false"),
Integer(Integral::Text { len, bytes }) => {
let arg = from_utf8(&bytes[..*len]).unwrap();
write!(f, "{}", arg)
}
Integer(Integral::Data { value: v }) => write!(f, "{}", v),
Float(Floating::Text { len, bytes }) => {
let arg = from_utf8(&bytes[..*len]).unwrap();
write!(f, "{}", arg)
}
Float(Floating::Data { value: v }) => write!(f, "{:e}", v),
S(val) => {
encode_string(f, &val)?;
Ok(())
}
Array(val) => {
if val.is_empty() {
write!(f, "[]")
} else {
write!(f, "[")?;
for item in val[..val.len() - 1].iter() {
write!(f, "{},", item)?;
}
write!(f, "{}", val[val.len() - 1])?;
write!(f, "]")
}
}
Object(val) => {
let val_len = val.len();
if val_len == 0 {
write!(f, "{{}}")
} else {
write!(f, "{{")?;
for (i, prop) in val.iter().enumerate() {
encode_string(f, prop.as_ref_key())?;
write!(f, ":{}", prop.as_ref_value())?;
if i < (val_len - 1) {
write!(f, ",")?;
}
}
write!(f, "}}")
}
}
Json::__Error(err) => write!(f, "error: {:?}", err),
Json::__Minbound => write!(f, "minbound"),
Json::__Maxbound => write!(f, "maxbound"),
}
}
}
fn encode_string<W: Write>(w: &mut W, val: &str) -> fmt::Result {
write!(w, "\"")?;
let mut start = 0;
for (i, byte) in val.bytes().enumerate() {
let escstr = ESCAPE[usize::from(byte)];
if escstr.is_empty() {
continue;
}
if start < i {
write!(w, "{}", &val[start..i])?;
}
write!(w, "{}", escstr)?;
start = i + 1;
}
if start != val.len() {
write!(w, "{}", &val[start..])?;
}
write!(w, "\"")
}
pub fn insert(json: &mut Json, item: Property) {
if let Json::Object(obj) = json {
match property::search_by_key(&obj, item.as_ref_key()) {
Ok(off) => {
obj.push(item);
obj.swap_remove(off);
}
Err(off) => obj.insert(off, item),
}
}
}
static ESCAPE: [&str; 256] = [
"\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006",
"\\u0007", "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f",
"\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016",
"\\u0017", "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d",
"\\u001e", "\\u001f", "", "", "\\\"", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "\\\\", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "\\u007f",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "",
];
#[cfg(test)]
#[path = "json_test.rs"]
mod json_test;