mod codegen;
mod parser;
mod value;
mod error;
pub mod iterators;
pub use error::JsonError;
pub use value::JsonValue;
pub use value::JsonValue::Null;
pub type JsonResult<T> = Result<T, JsonError>;
pub use parser::parse;
use codegen::{ Generator, PrettyGenerator, DumpGenerator };
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::fmt;
pub type Array = Vec<JsonValue>;
pub type Object = BTreeMap<String, JsonValue>;
impl JsonValue {
pub fn dump(&self) -> String {
let mut gen = DumpGenerator::new();
gen.write_json(self);
gen.consume()
}
pub fn pretty(&self, spaces: u16) -> String {
let mut gen = PrettyGenerator::new(spaces);
gen.write_json(self);
gen.consume()
}
}
impl fmt::Display for JsonValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if f.alternate() {
f.write_str(&self.pretty(4))
} else {
match *self {
JsonValue::String(ref value) => value.fmt(f),
JsonValue::Number(ref value) => value.fmt(f),
JsonValue::Boolean(ref value) => value.fmt(f),
JsonValue::Null => f.write_str("null"),
_ => f.write_str(&self.dump())
}
}
}
}
pub fn from<T>(value: T) -> JsonValue where T: Into<JsonValue> {
value.into()
}
pub fn stringify<T>(root: T) -> String where T: Into<JsonValue> {
let root: JsonValue = root.into();
root.dump()
}
pub fn stringify_pretty<T>(root: T, spaces: u16) -> String where T: Into<JsonValue> {
let root: JsonValue = root.into();
root.pretty(spaces)
}
#[macro_export]
macro_rules! array {
[] => ($crate::JsonValue::new_array());
[ $( $item:expr ),* ] => ({
let mut array = Vec::new();
$(
array.push($item.into());
)*
$crate::JsonValue::Array(array)
})
}
#[macro_export]
macro_rules! object {
{} => ($crate::JsonValue::new_object());
{ $( $key:expr => $value:expr ),* } => ({
use std::collections::BTreeMap;
let mut object = BTreeMap::new();
$(
object.insert($key.into(), $value.into());
)*
$crate::JsonValue::Object(object)
})
}
macro_rules! implement_extras {
($from:ty) => {
impl From<Option<$from>> for JsonValue {
fn from(val: Option<$from>) -> JsonValue {
match val {
Some(value) => value.into(),
None => Null,
}
}
}
impl From<Vec<$from>> for JsonValue {
fn from(mut val: Vec<$from>) -> JsonValue {
JsonValue::Array(
val.drain(..)
.map(|value| value.into())
.collect()
)
}
}
impl From<Vec<Option<$from>>> for JsonValue {
fn from(mut val: Vec<Option<$from>>) -> JsonValue {
JsonValue::Array(
val.drain(..)
.map(|item| item.into())
.collect()
)
}
}
}
}
macro_rules! implement {
($to:ident, $from:ty as $wanted:ty) => {
impl From<$from> for JsonValue {
fn from(val: $from) -> JsonValue {
JsonValue::$to(val as $wanted)
}
}
impl PartialEq<$from> for JsonValue {
fn eq(&self, other: &$from) -> bool {
match *self {
JsonValue::$to(ref value) => value == &(*other as $wanted),
_ => false
}
}
}
impl<'a> PartialEq<$from> for &'a JsonValue {
fn eq(&self, other: &$from) -> bool {
match **self {
JsonValue::$to(ref value) => value == &(*other as $wanted),
_ => false
}
}
}
impl PartialEq<JsonValue> for $from {
fn eq(&self, other: &JsonValue) -> bool {
match *other {
JsonValue::$to(ref value) => value == &(*self as $wanted),
_ => false
}
}
}
implement_extras!($from);
};
($to:ident, $from:ty) => {
impl From<$from> for JsonValue {
fn from(val: $from) -> JsonValue {
JsonValue::$to(val)
}
}
impl PartialEq<$from> for JsonValue {
fn eq(&self, other: &$from) -> bool {
match *self {
JsonValue::$to(ref value) => value == other,
_ => false
}
}
}
impl<'a> PartialEq<$from> for &'a JsonValue {
fn eq(&self, other: &$from) -> bool {
match **self {
JsonValue::$to(ref value) => value == other,
_ => false
}
}
}
impl PartialEq<JsonValue> for $from {
fn eq(&self, other: &JsonValue) -> bool {
match *other {
JsonValue::$to(ref value) => value == self,
_ => false
}
}
}
implement_extras!($from);
}
}
impl<'a> From<&'a str> for JsonValue {
fn from(val: &'a str) -> JsonValue {
JsonValue::String(val.to_string())
}
}
impl<'a> From<Option<&'a str>> for JsonValue {
fn from(val: Option<&'a str>) -> JsonValue {
match val {
Some(value) => value.into(),
None => Null,
}
}
}
impl From<HashMap<String, JsonValue>> for JsonValue {
fn from(mut val: HashMap<String, JsonValue>) -> JsonValue {
let mut object = BTreeMap::new();
for (key, value) in val.drain() {
object.insert(key, value);
}
JsonValue::Object(object)
}
}
impl From<Option<HashMap<String, JsonValue>>> for JsonValue {
fn from(val: Option<HashMap<String, JsonValue>>) -> JsonValue {
match val {
Some(value) => value.into(),
None => Null,
}
}
}
impl From<Option<JsonValue>> for JsonValue {
fn from(val: Option<JsonValue>) -> JsonValue {
match val {
Some(value) => value,
None => Null,
}
}
}
impl<'a> PartialEq<&'a str> for JsonValue {
fn eq(&self, other: &&str) -> bool {
match *self {
JsonValue::String(ref value) => value == *other,
_ => false
}
}
}
impl<'a> PartialEq<JsonValue> for &'a str {
fn eq(&self, other: &JsonValue) -> bool {
match *other {
JsonValue::String(ref value) => value == *self,
_ => false
}
}
}
impl PartialEq<str> for JsonValue {
fn eq(&self, other: &str) -> bool {
match *self {
JsonValue::String(ref value) => value == other,
_ => false
}
}
}
impl<'a> PartialEq<JsonValue> for str {
fn eq(&self, other: &JsonValue) -> bool {
match *other {
JsonValue::String(ref value) => value == self,
_ => false
}
}
}
implement!(String, String);
implement!(Number, isize as f64);
implement!(Number, usize as f64);
implement!(Number, i8 as f64);
implement!(Number, i16 as f64);
implement!(Number, i32 as f64);
implement!(Number, i64 as f64);
implement!(Number, u8 as f64);
implement!(Number, u16 as f64);
implement!(Number, u32 as f64);
implement!(Number, u64 as f64);
implement!(Number, f32 as f64);
implement!(Number, f64);
implement!(Object, Object);
implement!(Array, Array);
implement!(Boolean, bool);