use serde_json::value::Value;
use result::Result;
use error::*;
use ty::*;
trait OkType<T> {
fn ok_type(self, &'static str, Ty) -> Result<T>;
}
impl<T> OkType<T> for Option<T> {
fn ok_type(self, expected: &'static str, actual: Ty) -> Result<T> {
match self {
Some(v) => Ok(v),
None => Err(Error::TypeMismatch(expected, actual))
}
}
}
trait ValueEx {
fn as_number(&self) -> Result<f64>;
fn as_string_opt(&self) -> Result<Option<&str>>;
fn as_array_opt(&self) -> Result<Option<&Vec<Value>>>;
fn as_object_opt(&self) -> Result<Option<&Object>>;
fn as_boolean_opt(&self) -> Result<Option<bool>>;
fn as_i64_opt(&self) -> Result<Option<i64>>;
fn as_u64_opt(&self) -> Result<Option<u64>>;
fn as_f64_opt(&self) -> Result<Option<f64>>;
fn as_number_opt(&self) -> Result<Option<f64>>;
}
impl ValueEx for Value {
fn as_number(&self) -> Result<f64> {
Ok(match self {
&Value::I64(ref v) => *v as f64,
&Value::U64(ref v) => *v as f64,
&Value::F64(ref v) => *v,
_ => { return type_error("number", self.ty()); }
})
}
fn as_string_opt(&self) -> Result<Option<&str>> {
Ok(match self {
&Value::Null => None,
&Value::String(ref s) => Some(&s[..]),
_ => { return type_error("string or null", self.ty()); }
})
}
fn as_array_opt(&self) -> Result<Option<&Vec<Value>>> {
Ok(match self {
&Value::Null => None,
&Value::Array(ref a) => Some(a),
_ => { return type_error("array or null", self.ty()); }
})
}
fn as_object_opt(&self) -> Result<Option<&Object>> {
Ok(match self {
&Value::Null => None,
&Value::Object(ref o) => Some(o),
_ => { return type_error("object or null", self.ty()); }
})
}
fn as_boolean_opt(&self) -> Result<Option<bool>> {
Ok(match self {
&Value::Null => None,
&Value::Bool(ref b) => Some(*b),
_ => { return type_error("boolean or null", self.ty()); }
})
}
fn as_i64_opt(&self) -> Result<Option<i64>> {
Ok(match self {
&Value::Null => None,
&Value::I64(ref v) => Some(*v),
_ => { return type_error("i64 or null", self.ty()); }
})
}
fn as_u64_opt(&self) -> Result<Option<u64>> {
Ok(match self {
&Value::Null => None,
&Value::U64(ref v) => Some(*v),
_ => { return type_error("u64 or null", self.ty()); }
})
}
fn as_f64_opt(&self) -> Result<Option<f64>> {
Ok(match self {
&Value::Null => None,
&Value::F64(ref v) => Some(*v),
_ => { return type_error("f64 or null", self.ty()); }
})
}
fn as_number_opt(&self) -> Result<Option<f64>> {
Ok(match self {
&Value::Null => None,
&Value::I64(ref v) => Some(*v as f64),
&Value::U64(ref v) => Some(*v as f64),
&Value::F64(ref v) => Some(*v),
_ => { return type_error("number or null", self.ty()); }
})
}
}
pub trait Unjson {
fn into_array(self) -> Result<Array>;
fn into_array_opt(self) -> Result<Option<Array>>;
fn into_string(self) -> Result<String>;
fn into_string_opt(self) -> Result<Option<String>>;
fn into_object(self) -> Result<Object>;
fn into_object_opt(self) -> Result<Option<Object>>;
fn into_bool(self) -> Result<bool>;
fn into_bool_opt(self) -> Result<Option<bool>>;
fn into_i64(self) -> Result<i64>;
fn into_i64_opt(self) -> Result<Option<i64>>;
fn into_u64(self) -> Result<u64>;
fn into_u64_opt(self) -> Result<Option<u64>>;
fn into_f64(self) -> Result<f64>;
fn into_f64_opt(self) -> Result<Option<f64>>;
fn into_number(self) -> Result<f64>;
fn into_number_opt(self) -> Result<Option<f64>>;
}
impl Unjson for Value {
fn into_array(self) -> Result<Array> {
match self {
Value::Array(a) => Ok(a),
_ => { return type_error("array", self.ty()); }
}
}
fn into_array_opt(self) -> Result<Option<Array>> {
match self {
Value::Array(a) => Ok(Some(a)),
Value::Null => Ok(None),
_ => { return type_error("array or null", self.ty()); }
}
}
fn into_string(self) -> Result<String> {
match self {
Value::String(s) => Ok(s),
_ => { return type_error("string", self.ty()); }
}
}
fn into_string_opt(self) -> Result<Option<String>> {
match self {
Value::String(s) => Ok(Some(s)),
Value::Null => Ok(None),
_ => { return type_error("string or null", self.ty()); }
}
}
fn into_object(self) -> Result<Object> {
match self {
Value::Object(o) => Ok(o),
_ => { return type_error("object", self.ty()); }
}
}
fn into_object_opt(self) -> Result<Option<Object>> {
match self {
Value::Object(o) => Ok(Some(o)),
Value::Null => Ok(None),
_ => { return type_error("object or null", self.ty()); }
}
}
fn into_bool(self) -> Result<bool> {
match self {
Value::Bool(b) => Ok(b),
_ => { return type_error("boolean", self.ty()); }
}
}
fn into_bool_opt(self) -> Result<Option<bool>> {
match self {
Value::Bool(b) => Ok(Some(b)),
Value::Null => Ok(None),
_ => { return type_error("boolean", self.ty()); }
}
}
fn into_i64(self) -> Result<i64> {
match self {
Value::I64(i) => Ok(i),
_ => { return type_error("i64", self.ty()); }
}
}
fn into_i64_opt(self) -> Result<Option<i64>> {
match self {
Value::I64(i) => Ok(Some(i)),
Value::Null => Ok(None),
_ => { return type_error("i64", self.ty()); }
}
}
fn into_u64(self) -> Result<u64> {
match self {
Value::U64(u) => Ok(u),
_ => { return type_error("u64", self.ty()); }
}
}
fn into_u64_opt(self) -> Result<Option<u64>> {
match self {
Value::U64(u) => Ok(Some(u)),
Value::Null => Ok(None),
_ => { return type_error("u64", self.ty()); }
}
}
fn into_f64(self) -> Result<f64> {
match self {
Value::F64(f) => Ok(f),
_ => { return type_error("f64", self.ty()); }
}
}
fn into_f64_opt(self) -> Result<Option<f64>> {
match self {
Value::F64(f) => Ok(Some(f)),
Value::Null => Ok(None),
_ => { return type_error("f64", self.ty()); }
}
}
fn into_number(self) -> Result<f64> {
match self {
Value::I64(i) => Ok(i as f64),
Value::U64(u) => Ok(u as f64),
Value::F64(f) => Ok(f),
_ => { return type_error("number", self.ty()); }
}
}
fn into_number_opt(self) -> Result<Option<f64>> {
match self {
Value::I64(i) => Ok(Some(i as f64)),
Value::U64(u) => Ok(Some(u as f64)),
Value::F64(f) => Ok(Some(f)),
Value::Null => Ok(None),
_ => { return type_error("number", self.ty()); }
}
}
}
pub trait GetField {
fn get_field(&self, &'static str) -> Result<&Value>;
fn get_string(&self, &'static str) -> Result<&str>;
fn get_string_opt(&self, &'static str) -> Result<Option<&str>>;
fn get_array(&self, &'static str) -> Result<&Array>;
fn get_array_opt(&self, &'static str) -> Result<Option<&Array>>;
fn get_object(&self, &'static str) -> Result<&Object>;
fn get_object_opt(&self, &'static str) -> Result<Option<&Object>>;
fn get_bool(&self, &'static str) -> Result<bool>;
fn get_bool_opt(&self, &'static str) -> Result<Option<bool>>;
fn get_i64(&self, &'static str) -> Result<i64>;
fn get_i64_opt(&self, &'static str) -> Result<Option<i64>>;
fn get_u64(&self, &'static str) -> Result<u64>;
fn get_u64_opt(&self, &'static str) -> Result<Option<u64>>;
fn get_f64(&self, &'static str) -> Result<f64>;
fn get_f64_opt(&self, &'static str) -> Result<Option<f64>>;
fn get_number(&self, &'static str) -> Result<f64>;
fn get_number_opt(&self, &'static str) -> Result<Option<f64>>;
}
impl GetField for Object {
fn get_field(&self, name: &'static str) -> Result<&Value> {
match self.get(name) {
Some(json) => Ok(json),
None => Err(Error::MissingField(name))
}
}
fn get_string(&self, name: &'static str) -> Result<&str> {
self.get_field(name).and_then(|v| v.as_string().ok_type("string", v.ty()))
}
fn get_string_opt(&self, name: &'static str) -> Result<Option<&str>> {
self.get_field(name).and_then(|v| v.as_string_opt())
}
fn get_array(&self, name: &'static str) -> Result<&Array> {
self.get_field(name).and_then(|v| v.as_array().ok_type("array", v.ty()))
}
fn get_array_opt(&self, name: &'static str) -> Result<Option<&Array>> {
self.get_field(name).and_then(|v| v.as_array_opt())
}
fn get_object(&self, name: &'static str) -> Result<&Object> {
self.get_field(name).and_then(|v| v.as_object().ok_type("object", v.ty()))
}
fn get_object_opt(&self, name: &'static str) -> Result<Option<&Object>> {
self.get_field(name).and_then(|v| v.as_object_opt())
}
fn get_bool(&self, name: &'static str) -> Result<bool> {
self.get_field(name).and_then(|v| v.as_boolean().ok_type("boolean", v.ty()))
}
fn get_bool_opt(&self, name: &'static str) -> Result<Option<bool>> {
self.get_field(name).and_then(|v| v.as_boolean_opt())
}
fn get_i64(&self, name: &'static str) -> Result<i64> {
self.get_field(name).and_then(|v| v.as_i64().ok_type("i64", v.ty()))
}
fn get_i64_opt(&self, name: &'static str) -> Result<Option<i64>> {
self.get_field(name).and_then(|v| v.as_i64_opt())
}
fn get_u64(&self, name: &'static str) -> Result<u64> {
self.get_field(name).and_then(|v| v.as_u64().ok_type("u64", v.ty()))
}
fn get_u64_opt(&self, name: &'static str) -> Result<Option<u64>> {
self.get_field(name).and_then(|v| v.as_u64_opt())
}
fn get_f64(&self, name: &'static str) -> Result<f64> {
self.get_field(name).and_then(|v| v.as_f64().ok_type("f64", v.ty()))
}
fn get_f64_opt(&self, name: &'static str) -> Result<Option<f64>> {
self.get_field(name).and_then(|v| v.as_f64_opt())
}
fn get_number(&self, name: &'static str) -> Result<f64> {
self.get_field(name).and_then(|v| v.as_number())
}
fn get_number_opt(&self, name: &'static str) -> Result<Option<f64>> {
self.get_field(name).and_then(|v| v.as_number_opt())
}
}
pub trait ExtractField {
fn extract_field(&mut self, &'static str) -> Result<Value>;
fn extract_string(&mut self, &'static str) -> Result<String>;
fn extract_string_opt(&mut self, &'static str) -> Result<Option<String>>;
fn extract_array(&mut self, &'static str) -> Result<Array>;
fn extract_array_opt(&mut self, &'static str) -> Result<Option<Array>>;
fn extract_object(&mut self, &'static str) -> Result<Object>;
fn extract_object_opt(&mut self, &'static str) -> Result<Option<Object>>;
fn extract_bool(&mut self, &'static str) -> Result<bool>;
fn extract_bool_opt(&mut self, &'static str) -> Result<Option<bool>>;
fn extract_i64(&mut self, &'static str) -> Result<i64>;
fn extract_i64_opt(&mut self, &'static str) -> Result<Option<i64>>;
fn extract_u64(&mut self, &'static str) -> Result<u64>;
fn extract_u64_opt(&mut self, &'static str) -> Result<Option<u64>>;
fn extract_f64(&mut self, &'static str) -> Result<f64>;
fn extract_f64_opt(&mut self, &'static str) -> Result<Option<f64>>;
fn extract_number(&mut self, &'static str) -> Result<f64>;
fn extract_number_opt(&mut self, &'static str) -> Result<Option<f64>>;
}
impl ExtractField for Object {
fn extract_field(&mut self, name: &'static str) -> Result<Value> {
match self.remove(name) {
Some(json) => Ok(json),
None => Err(Error::MissingField(name))
}
}
fn extract_string(&mut self, name: &'static str) -> Result<String> {
self.extract_field(name).and_then(|v| v.into_string())
}
fn extract_string_opt(&mut self, name: &'static str) -> Result<Option<String>> {
self.extract_field(name).and_then(|v| v.into_string_opt())
}
fn extract_array(&mut self, name: &'static str) -> Result<Array> {
self.extract_field(name).and_then(|v| v.into_array())
}
fn extract_array_opt(&mut self, name: &'static str) -> Result<Option<Array>> {
self.extract_field(name).and_then(|v| v.into_array_opt())
}
fn extract_object(&mut self, name: &'static str) -> Result<Object> {
self.extract_field(name).and_then(|v| v.into_object())
}
fn extract_object_opt(&mut self, name: &'static str) -> Result<Option<Object>> {
self.extract_field(name).and_then(|v| v.into_object_opt())
}
fn extract_bool(&mut self, name: &'static str) -> Result<bool> {
self.extract_field(name).and_then(|v| v.into_bool())
}
fn extract_bool_opt(&mut self, name: &'static str) -> Result<Option<bool>> {
self.extract_field(name).and_then(|v| v.into_bool_opt())
}
fn extract_i64(&mut self, name: &'static str) -> Result<i64> {
self.extract_field(name).and_then(|v| v.into_i64())
}
fn extract_i64_opt(&mut self, name: &'static str) -> Result<Option<i64>> {
self.extract_field(name).and_then(|v| v.into_i64_opt())
}
fn extract_u64(&mut self, name: &'static str) -> Result<u64> {
self.extract_field(name).and_then(|v| v.into_u64())
}
fn extract_u64_opt(&mut self, name: &'static str) -> Result<Option<u64>> {
self.extract_field(name).and_then(|v| v.into_u64_opt())
}
fn extract_f64(&mut self, name: &'static str) -> Result<f64> {
self.extract_field(name).and_then(|v| v.into_f64())
}
fn extract_f64_opt(&mut self, name: &'static str) -> Result<Option<f64>> {
self.extract_field(name).and_then(|v| v.into_f64_opt())
}
fn extract_number(&mut self, name: &'static str) -> Result<f64> {
self.extract_field(name).and_then(|v| v.into_number())
}
fn extract_number_opt(&mut self, name: &'static str) -> Result<Option<f64>> {
self.extract_field(name).and_then(|v| v.into_number_opt())
}
}