estree 0.0.1

A deserializer for the ESTree format.
use unjson::ty::Object;
use unjson::{ExtractField, Unjson};
use easter::id::Id;
use easter::expr::{Expr, IntoAssignmentPattern};
use easter::stmt::{Stmt, StmtListItem, Case, Catch};
use easter::patt::{Patt, APatt};
use easter::obj::Prop;
use easter::decl::Dtor;

use error::Error;
use result::{Result, Map};
use id::IntoId;
use stmt::IntoStmt;
use expr::IntoExpr;
use patt::IntoPatt;
use obj::IntoObj;
use decl::IntoDecl;

pub trait ExtractNode {
    fn extract_id(&mut self, &'static str) -> Result<Id>;
    fn extract_id_opt(&mut self, &'static str) -> Result<Option<Id>>;
    fn extract_apatt(&mut self, &'static str) -> Result<APatt>;
    fn extract_stmt(&mut self, &'static str) -> Result<Stmt>;
    fn extract_expr(&mut self, &'static str) -> Result<Expr>;
    fn extract_expr_opt(&mut self, &'static str) -> Result<Option<Expr>>;
    fn extract_expr_list(&mut self, &'static str) -> Result<Vec<Expr>>;
    fn extract_expr_opt_list(&mut self, &'static str) -> Result<Vec<Option<Expr>>>;
    fn extract_stmt_opt(&mut self, &'static str) -> Result<Option<Stmt>>;
    fn extract_stmt_list(&mut self, &'static str) -> Result<Vec<StmtListItem>>;
    fn extract_patt(&mut self, &'static str) -> Result<Patt>;
    fn extract_patt_list(&mut self, &'static str) -> Result<Vec<Patt>>;
    fn extract_prop_list(&mut self, &'static str) -> Result<Vec<Prop>>;
    fn extract_dtor_list(&mut self, &'static str) -> Result<Vec<Dtor>>;
    fn extract_case_list(&mut self, &'static str) -> Result<Vec<Case>>;
    fn extract_catch_opt(&mut self, &'static str) -> Result<Option<Catch>>;
}

impl ExtractNode for Object {
    fn extract_id(&mut self, name: &'static str) -> Result<Id> {
        self.extract_object(name).map_err(Error::Json).and_then(|o| o.into_id())
    }

    fn extract_id_opt(&mut self, name: &'static str) -> Result<Option<Id>> {
        Ok(match try!(self.extract_object_opt(name).map_err(Error::Json)) {
            Some(obj) => Some(try!(obj.into_id())),
            None      => None
        })
    }

    fn extract_apatt(&mut self, name: &'static str) -> Result<APatt> {
        let expr = try!(self.extract_expr(name));
        match expr.into_assignment_pattern() {
            Ok(patt) => Ok(patt),
            _ => Err(Error::InvalidLHS(name))
        }
    }

    fn extract_stmt(&mut self, name: &'static str) -> Result<Stmt> {
        self.extract_object(name).map_err(Error::Json).and_then(|o| o.into_stmt())
    }

    fn extract_expr(&mut self, name: &'static str) -> Result<Expr> {
        self.extract_object(name).map_err(Error::Json).and_then(|o| o.into_expr())
    }

    fn extract_expr_opt(&mut self, name: &'static str) -> Result<Option<Expr>> {
        Ok(match try!(self.extract_object_opt(name).map_err(Error::Json)) {
            Some(o) => Some(try!(o.into_expr())),
            None => None
        })
    }

    fn extract_expr_list(&mut self, name: &'static str) -> Result<Vec<Expr>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        let objs = try!(list.map(|v| v.into_object().map_err(Error::Json)));
        objs.map(|o| o.into_expr())
    }

    fn extract_expr_opt_list(&mut self, name: &'static str) -> Result<Vec<Option<Expr>>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        list.map(|v| {
            match try!(v.into_object_opt().map_err(Error::Json)) {
                None => Ok(None),
                Some(o) => o.into_expr().map(Some)
            }
        })
    }

    fn extract_stmt_opt(&mut self, name: &'static str) -> Result<Option<Stmt>> {
        Ok(match try!(self.extract_object_opt(name).map_err(Error::Json)) {
            Some(o) => Some(try!(o.into_stmt())),
            None => None
        })
    }

    fn extract_stmt_list(&mut self, name: &'static str) -> Result<Vec<StmtListItem>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        let objs = try!(list.map(|v| v.into_object().map_err(Error::Json)));
        objs.map(|o| o.into_stmt_list_item())
    }

    fn extract_patt(&mut self, name: &'static str) -> Result<Patt> {
        self.extract_object(name).map_err(Error::Json).and_then(|o| o.into_patt())
    }

    fn extract_patt_list(&mut self, name: &'static str) -> Result<Vec<Patt>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        let objs = try!(list.map(|v| v.into_object().map_err(Error::Json)));
        objs.map(|o| o.into_patt())
    }

    fn extract_prop_list(&mut self, name: &'static str) -> Result<Vec<Prop>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        let objs = try!(list.map(|v| v.into_object().map_err(Error::Json)));
        objs.map(|o| o.into_prop())
    }

    fn extract_dtor_list(&mut self, name: &'static str) -> Result<Vec<Dtor>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        let objs = try!(list.map(|v| v.into_object().map_err(Error::Json)));
        objs.map(|o| o.into_dtor())
    }

    fn extract_case_list(&mut self, name: &'static str) -> Result<Vec<Case>> {
        let list = try!(self.extract_array(name).map_err(Error::Json));
        let objs = try!(list.map(|v| v.into_object().map_err(Error::Json)));
        objs.map(|o| o.into_case())
    }

    fn extract_catch_opt(&mut self, name: &'static str) -> Result<Option<Catch>> {
        Ok(match try!(self.extract_object_opt(name).map_err(Error::Json)) {
            Some(o) => Some(try!(o.into_catch())),
            None => None
        })
    }

}