estree 0.0.1

A deserializer for the ESTree format.
use std::fmt;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
use unjson::ty::Object;
use unjson::*;

use result::Result;
use error::Error;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Tag {
    Identifier,
    Literal,

    BinaryExpression,
    AssignmentExpression,
    LogicalExpression,
    UnaryExpression,
    UpdateExpression,
    MemberExpression,
    CallExpression,
    NewExpression,
    ArrayExpression,
    FunctionExpression,
    SequenceExpression,
    ObjectExpression,
    ConditionalExpression,
    ThisExpression,

    FunctionDeclaration,
    VariableDeclaration,

    EmptyStatement,
    ExpressionStatement,
    IfStatement,
    DoWhileStatement,
    WhileStatement,
    ForStatement,
    ForInStatement,
    ForOfStatement,
    BlockStatement,
    ReturnStatement,
    LabeledStatement,
    BreakStatement,
    ContinueStatement,
    SwitchStatement,
    WithStatement,
    ThrowStatement,
    DebuggerStatement,
    TryStatement
}

impl Display for Tag {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_fmt(format_args!("{:?}", self))
    }
}

impl FromStr for Tag {
    type Err = Error;

    fn from_str(s: &str) -> Result<Tag> {
        Ok(match s {
            "Identifier"            => Tag::Identifier,
            "Literal"               => Tag::Literal,
            "BinaryExpression"      => Tag::BinaryExpression,
            "AssignmentExpression"  => Tag::AssignmentExpression,
            "LogicalExpression"     => Tag::LogicalExpression,
            "UnaryExpression"       => Tag::UnaryExpression,
            "UpdateExpression"      => Tag::UpdateExpression,
            "MemberExpression"      => Tag::MemberExpression,
            "CallExpression"        => Tag::CallExpression,
            "NewExpression"         => Tag::NewExpression,
            "ArrayExpression"       => Tag::ArrayExpression,
            "FunctionExpression"    => Tag::FunctionExpression,
            "SequenceExpression"    => Tag::SequenceExpression,
            "ObjectExpression"      => Tag::ObjectExpression,
            "ConditionalExpression" => Tag::ConditionalExpression,
            "ThisExpression"        => Tag::ThisExpression,
            "FunctionDeclaration"   => Tag::FunctionDeclaration,
            "VariableDeclaration"   => Tag::VariableDeclaration,
            "EmptyStatement"        => Tag::EmptyStatement,
            "ExpressionStatement"   => Tag::ExpressionStatement,
            "IfStatement"           => Tag::IfStatement,
            "DoWhileStatement"      => Tag::DoWhileStatement,
            "WhileStatement"        => Tag::WhileStatement,
            "ForStatement"          => Tag::ForStatement,
            "ForInStatement"        => Tag::ForInStatement,
            "ForOfStatement"        => Tag::ForOfStatement,
            "BlockStatement"        => Tag::BlockStatement,
            "ReturnStatement"       => Tag::ReturnStatement,
            "LabeledStatement"      => Tag::LabeledStatement,
            "BreakStatement"        => Tag::BreakStatement,
            "ContinueStatement"     => Tag::ContinueStatement,
            "SwitchStatement"       => Tag::SwitchStatement,
            "WithStatement"         => Tag::WithStatement,
            "ThrowStatement"        => Tag::ThrowStatement,
            "DebuggerStatement"     => Tag::DebuggerStatement,
            "TryStatement"          => Tag::TryStatement,
            _ => { return Err(Error::InvalidTypeTag(String::from(s))); }
        })
    }
}

pub trait TagOf {
    fn tag(&self) -> Result<Tag>;
}

impl TagOf for Object {
    fn tag(&self) -> Result<Tag> {
        let str = try!(self.get_string("type").map_err(Error::Json));
        str.parse()
           .map_err(|_| Error::InvalidTypeTag(String::from(str)))
    }
}