use std::collections::BTreeMap;
use std::ops::{ Index, IndexMut };
use iterators::{ Members, MembersMut, Entries, EntriesMut };
use { JsonResult, JsonError };
#[derive(Debug, PartialEq, Clone)]
pub enum JsonValue {
String(String),
Number(f64),
Boolean(bool),
Null,
Object(BTreeMap<String, JsonValue>),
Array(Vec<JsonValue>),
}
static NULL: JsonValue = JsonValue::Null;
impl JsonValue {
pub fn new_object() -> JsonValue {
JsonValue::Object(BTreeMap::new())
}
pub fn new_array() -> JsonValue {
JsonValue::Array(Vec::new())
}
pub fn is<T>(&self, other: T) -> bool where T: Into<JsonValue> {
*self == other.into()
}
pub fn is_string(&self) -> bool {
match *self {
JsonValue::String(_) => true,
_ => false,
}
}
pub fn as_string(&self) -> JsonResult<&String> {
match *self {
JsonValue::String(ref value) => Ok(value),
_ => Err(JsonError::wrong_type("String"))
}
}
pub fn is_number(&self) -> bool {
match *self {
JsonValue::Number(_) => true,
_ => false,
}
}
pub fn as_number(&self) -> JsonResult<&f64> {
match *self {
JsonValue::Number(ref value) => Ok(value),
_ => Err(JsonError::wrong_type("Number"))
}
}
pub fn is_boolean(&self) -> bool {
match *self {
JsonValue::Boolean(_) => true,
_ => false
}
}
pub fn as_boolean(&self) -> JsonResult<&bool> {
match *self {
JsonValue::Boolean(ref value) => Ok(value),
_ => Err(JsonError::wrong_type("Boolean"))
}
}
pub fn is_null(&self) -> bool {
match *self {
JsonValue::Null => true,
_ => false,
}
}
pub fn is_object(&self) -> bool {
match *self {
JsonValue::Object(_) => true,
_ => false,
}
}
pub fn is_array(&self) -> bool {
match *self {
JsonValue::Array(_) => true,
_ => false,
}
}
#[must_use]
#[deprecated(since="0.6.0", note="Use `object[key] = value.into()` instead")]
pub fn put<T>(&mut self, key: &str, value: T) -> JsonResult<()>
where T: Into<JsonValue> {
match *self {
JsonValue::Object(ref mut btree) => {
btree.insert(key.into(), value.into());
Ok(())
},
_ => Err(JsonError::wrong_type("Object"))
}
}
#[deprecated(since="0.6.0", note="Use `object[key]` instead")]
pub fn get(&self, key: &str) -> JsonResult<&JsonValue> {
match *self {
JsonValue::Object(ref btree) => match btree.get(key) {
Some(value) => Ok(value),
_ => Err(JsonError::undefined(key))
},
_ => Err(JsonError::wrong_type("Object"))
}
}
#[deprecated(since="0.6.0", note="Use `object[key]` instead")]
pub fn get_mut(&mut self, key: &str) -> JsonResult<&mut JsonValue> {
match *self {
JsonValue::Object(ref mut btree) => match btree.get_mut(key) {
Some(value) => Ok(value),
_ => Err(JsonError::undefined(key))
},
_ => Err(JsonError::wrong_type("Object"))
}
}
#[deprecated(since="0.6.0", note="Use `object[key]` instead")]
pub fn with(&mut self, key: &str) -> &mut JsonValue {
if !self.is_object() {
*self = JsonValue::new_object();
}
match *self {
JsonValue::Object(ref mut btree) => {
if !btree.contains_key(key) {
btree.insert(key.to_string(), JsonValue::Null);
}
btree.get_mut(key).unwrap()
},
_ => unreachable!()
}
}
#[must_use]
pub fn push<T>(&mut self, value: T) -> JsonResult<()>
where T: Into<JsonValue> {
match *self {
JsonValue::Array(ref mut vec) => {
vec.push(value.into());
Ok(())
},
_ => Err(JsonError::wrong_type("Array"))
}
}
#[deprecated(since="0.6.0", note="Use `array[index]` instead")]
pub fn at(&self, index: usize) -> JsonResult<&JsonValue> {
match *self {
JsonValue::Array(ref vec) => {
if index < vec.len() {
Ok(&vec[index])
} else {
Err(JsonError::ArrayIndexOutOfBounds)
}
},
_ => Err(JsonError::wrong_type("Array"))
}
}
#[deprecated(since="0.6.0", note="Use `array[index]` instead")]
pub fn at_mut(&mut self, index: usize) -> JsonResult<&mut JsonValue> {
match *self {
JsonValue::Array(ref mut vec) => {
if index < vec.len() {
Ok(&mut vec[index])
} else {
Err(JsonError::ArrayIndexOutOfBounds)
}
},
_ => Err(JsonError::wrong_type("Array"))
}
}
pub fn contains<T>(&self, item: T) -> bool where T: Into<JsonValue> {
match *self {
JsonValue::Array(ref vec) => {
vec.contains(&item.into())
},
_ => false
}
}
pub fn len(&self) -> usize {
match *self {
JsonValue::Array(ref vec) => {
vec.len()
},
JsonValue::Object(ref btree) => {
btree.len()
},
_ => 0
}
}
pub fn members(&self) -> Members {
match *self {
JsonValue::Array(ref vec) => {
Members::Some(vec.iter())
},
_ => Members::None
}
}
pub fn members_mut(&mut self) -> MembersMut {
match *self {
JsonValue::Array(ref mut vec) => {
MembersMut::Some(vec.iter_mut())
},
_ => MembersMut::None
}
}
pub fn entries(&self) -> Entries {
match *self {
JsonValue::Object(ref btree) => {
Entries::Some(btree.iter())
},
_ => Entries::None
}
}
pub fn entries_mut(&mut self) -> EntriesMut {
match *self {
JsonValue::Object(ref mut btree) => {
EntriesMut::Some(btree.iter_mut())
},
_ => EntriesMut::None
}
}
}
impl Index<usize> for JsonValue {
type Output = JsonValue;
fn index(&self, index: usize) -> &JsonValue {
match *self {
JsonValue::Array(ref vec) => vec.get(index).unwrap_or(&NULL),
_ => &NULL
}
}
}
impl IndexMut<usize> for JsonValue {
fn index_mut(&mut self, index: usize) -> &mut JsonValue {
match *self {
JsonValue::Array(ref mut vec) => {
let in_bounds = index < vec.len();
if in_bounds {
&mut vec[index]
} else {
vec.push(JsonValue::Null);
vec.last_mut().unwrap()
}
}
_ => {
*self = JsonValue::new_array();
self.push(JsonValue::Null).unwrap();
&mut self[0]
}
}
}
}
impl<'a> Index<&'a str> for JsonValue {
type Output = JsonValue;
fn index(&self, index: &str) -> &JsonValue {
match *self {
JsonValue::Object(ref btree) => match btree.get(index) {
Some(value) => value,
_ => &NULL
},
_ => &NULL
}
}
}
impl<'a> IndexMut<&'a str> for JsonValue {
fn index_mut(&mut self, index: &str) -> &mut JsonValue {
match *self {
JsonValue::Object(ref mut btree) => {
if !btree.contains_key(index) {
btree.insert(index.to_string(), JsonValue::Null);
}
btree.get_mut(index).unwrap()
},
_ => {
*self = JsonValue::new_object();
&mut self[index]
}
}
}
}