estree 0.0.5

A deserializer for the ESTree format.
Documentation
use easter::obj::{Prop, PropKey, PropVal};
use easter::expr::Expr;
use unjson::ty::{Object, Ty};
use unjson::ExtractField;

use tag::{Tag, TagOf};
use id::IntoId;
use result::Result;
use error::{Error, type_error, array_error};
use node::ExtractNode;
use expr::IntoExpr;
use fun::IntoFun;

pub trait IntoObj {
    fn into_prop(self) -> Result<Prop>;
    fn into_prop_key(self) -> Result<PropKey>;
}

impl IntoObj for Object {
    fn into_prop(mut self) -> Result<Prop> {
        let key = try!(try!(self.extract_object("key").map_err(Error::Json)).into_prop_key());
        let mut val = try!(self.extract_object("value").map_err(Error::Json));
        let kind = try!(self.extract_string("kind").map_err(Error::Json));
        let val = match &kind[..] {
            "init" => PropVal::Init(try!(val.into_expr())),
            "get" => PropVal::Get(None, try!(try!(val.extract_object("body").map_err(Error::Json)).extract_stmt_list("body"))),
            "set" => {
                let fun = try!(val.into_fun());
                let params = fun.params.list;
                if params.len() != 1 {
                    return array_error(1, params.len());
                }
                let param = params.into_iter().next().unwrap();
                PropVal::Set(None, param, fun.body)
            }
            _ => { return type_error("'init', 'get', or 'set'", Ty::String); }
        };
        Ok(Prop { location: None, key: key, val: val })
    }

    fn into_prop_key(self) -> Result<PropKey> {
        if try!(self.tag()) == Tag::Identifier {
            let id = try!(self.into_id());
            return Ok(PropKey::Id(None, id.name.into_string()));
        }
        match try!(self.into_lit()) {
            Expr::Number(_, lit) => Ok(PropKey::Number(None, lit)),
            Expr::String(_, lit) => Ok(PropKey::String(None, lit)),
            _ => { return type_error("identifier, number literal, or string literal", Ty::Object); }
        }
    }
}