estree 0.0.1

A deserializer for the ESTree format.
use std::fmt;
use std::fmt::{Display, Formatter};

use easter::expr::Expr;
use easter::patt::CompoundPatt;
use unjson;
use unjson::ty::Ty;
use result::Result;
use tag::Tag;

pub enum Error {
    Json(unjson::error::Error),
    InvalidTypeTag(String),
    NodeTypeMismatch(&'static str, Tag),
    UnexpectedInitializer(Expr),
    InvalidLHS(&'static str),
    UninitializedPattern(CompoundPatt)
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match self {
            &Error::Json(ref err) => {
                fmt.write_fmt(format_args!("{}", err))
            }
            &Error::InvalidTypeTag(ref actual) => {
                fmt.write_fmt(format_args!("expected node type tag, got {}", actual))
            }
            &Error::NodeTypeMismatch(ref expected, ref actual) => {
                fmt.write_fmt(format_args!("expected {} node, got {}", expected, actual))
            }
            &Error::UnexpectedInitializer(_) => {
                // FIXME: stringify the expression?
                fmt.write_fmt(format_args!("unexpected initializer in for-in loop"))
            }
            &Error::InvalidLHS(_) => {
                fmt.write_fmt(format_args!("invalid left-hand side of assignment"))
            }
            &Error::UninitializedPattern(_) => {
                // FIXME: better error message
                fmt.write_fmt(format_args!("uninitialized compound pattern"))
            }
        }
    }
}

pub fn type_error<T>(expected: &'static str, actual: Ty) -> Result<T> {
    unjson::error::type_error(expected, actual).map_err(Error::Json)
}

pub fn field_error<T>(name: &'static str) -> Result<T> {
    unjson::error::field_error(name).map_err(Error::Json)
}

pub fn array_error<T>(minimum: usize, actual: usize) -> Result<T> {
    unjson::error::array_error(minimum, actual).map_err(Error::Json)
}

pub fn string_error<T>(expected: &'static str, actual: String) -> Result<T> {
    unjson::error::string_error(expected, actual).map_err(Error::Json)
}

// FIXME: tag_error

// FIXME: node_type_error

pub fn node_type_error<T>(expected: &'static str, actual: Tag) -> Result<T> {
    Err(Error::NodeTypeMismatch(expected, actual))
}