unjson 0.0.1

Tools for destructuring JSON data.
use serde_json::value::Value;
use result::Result;
use error::*;
use 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 ExtractField {
    fn extract(&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>>;


    //fn extract_object_array(&mut self, &'static str) -> Result<Vec<Object>>;
    //fn extract_object_opt_array(&mut self, &'static str) -> Result<Vec<Option<Object>>>;
}

impl ExtractField for Object {
    fn extract(&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(name).and_then(|v| v.into_string())
    }

    fn extract_string_opt(&mut self, name: &'static str) -> Result<Option<String>> {
        self.extract(name).and_then(|v| v.into_string_opt())
    }

    fn extract_array(&mut self, name: &'static str) -> Result<Array> {
        self.extract(name).and_then(|v| v.into_array())
    }

    fn extract_array_opt(&mut self, name: &'static str) -> Result<Option<Array>> {
        self.extract(name).and_then(|v| v.into_array_opt())
    }

    fn extract_object(&mut self, name: &'static str) -> Result<Object> {
        self.extract(name).and_then(|v| v.into_object())
    }

    fn extract_object_opt(&mut self, name: &'static str) -> Result<Option<Object>> {
        self.extract(name).and_then(|v| v.into_object_opt())
    }

    fn extract_bool(&mut self, name: &'static str) -> Result<bool> {
        self.extract(name).and_then(|v| v.into_bool())
    }

    fn extract_bool_opt(&mut self, name: &'static str) -> Result<Option<bool>> {
        self.extract(name).and_then(|v| v.into_bool_opt())
    }

    fn extract_i64(&mut self, name: &'static str) -> Result<i64> {
        self.extract(name).and_then(|v| v.into_i64())
    }

    fn extract_i64_opt(&mut self, name: &'static str) -> Result<Option<i64>> {
        self.extract(name).and_then(|v| v.into_i64_opt())
    }

    fn extract_u64(&mut self, name: &'static str) -> Result<u64> {
        self.extract(name).and_then(|v| v.into_u64())
    }

    fn extract_u64_opt(&mut self, name: &'static str) -> Result<Option<u64>> {
        self.extract(name).and_then(|v| v.into_u64_opt())
    }

    fn extract_f64(&mut self, name: &'static str) -> Result<f64> {
        self.extract(name).and_then(|v| v.into_f64())
    }

    fn extract_f64_opt(&mut self, name: &'static str) -> Result<Option<f64>> {
        self.extract(name).and_then(|v| v.into_f64_opt())
    }

    fn extract_number(&mut self, name: &'static str) -> Result<f64> {
        self.extract(name).and_then(|v| v.into_number())
    }

    fn extract_number_opt(&mut self, name: &'static str) -> Result<Option<f64>> {
        self.extract(name).and_then(|v| v.into_number_opt())
    }
}