<commit_before>//! FIXME: write short doc here
use hir_def::{
    child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef,
    EnumVariantId, GenericDefId, LocationCtx, ModuleId, VariantId,
};
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
use ra_syntax::{
    ast::{self, AstNode, NameOwner},
    match_ast, SyntaxNode,
};

use crate::{
    db::{AstDatabase, DefDatabase, HirDatabase},
    Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local,
    MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
};

pub trait FromSource: Sized {
    type Ast;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self>;
}

impl FromSource for Struct {
    type Ast = ast::StructDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let id = from_source(db, src)?;
        Some(Struct { id })
    }
}
impl FromSource for Union {
    type Ast = ast::UnionDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let id = from_source(db, src)?;
        Some(Union { id })
    }
}
impl FromSource for Enum {
    type Ast = ast::EnumDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let id = from_source(db, src)?;
        Some(Enum { id })
    }
}
impl FromSource for Trait {
    type Ast = ast::TraitDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        // XXX: use `.parent()` to avoid finding ourselves
        let parent = src.value.syntax().parent()?;
        let container = Container::find(db, src.with_value(parent).as_ref())?;
        container.child_by_source(db)[keys::TRAIT].get(&src).copied().map(Trait::from)
    }
}
impl FromSource for Function {
    type Ast = ast::FnDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::FUNCTION]
            .get(&src)
            .copied()
            .map(Function::from)
    }
}

impl FromSource for Const {
    type Ast = ast::ConstDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::CONST]
            .get(&src)
            .copied()
            .map(Const::from)
    }
}
impl FromSource for Static {
    type Ast = ast::StaticDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::STATIC]
            .get(&src)
            .copied()
            .map(Static::from)
    }
}

impl FromSource for TypeAlias {
    type Ast = ast::TypeAliasDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)
            [keys::TYPE_ALIAS]
            .get(&src)
            .copied()
            .map(TypeAlias::from)
    }
}

impl FromSource for MacroDef {
    type Ast = ast::MacroCall;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let kind = MacroDefKind::Declarative;

        let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
        let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?;
        let krate = Some(module.krate().id);

        let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value)));

        let id: MacroDefId = MacroDefId { krate, ast_id, kind };
        Some(MacroDef { id })
    }
}

impl FromSource for ImplBlock {
    type Ast = ast::ImplBlock;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        // XXX: use `.parent()` to avoid finding ourselves
        let parent = src.value.syntax().parent()?;
        let container = Container::find(db, src.with_value(parent).as_ref())?;
        container.child_by_source(db)[keys::IMPL].get(&src).copied().map(ImplBlock::from)
    }
}

impl FromSource for EnumVariant {
    type Ast = ast::EnumVariant;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let parent_enum = src.value.parent_enum();
        let src_enum = InFile { file_id: src.file_id, value: parent_enum };
        let parent_enum = Enum::from_source(db, src_enum)?;
        parent_enum.id.child_by_source(db)[keys::ENUM_VARIANT]
            .get(&src)
            .copied()
            .map(EnumVariant::from)
    }
}

impl FromSource for StructField {
    type Ast = FieldSource;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let src = src.as_ref();

        // FIXME this is buggy
        let variant_id: VariantId = match src.value {
            FieldSource::Named(field) => {
                let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
                let src = InFile { file_id: src.file_id, value };
                let def = Struct::from_source(db, src)?;
                def.id.into()
            }
            FieldSource::Pos(field) => {
                let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
                let src = InFile { file_id: src.file_id, value };
                let def = EnumVariant::from_source(db, src)?;
                EnumVariantId::from(def).into()
            }
        };

        let dyn_map = variant_id.child_by_source(db);
        match src.value {
            FieldSource::Pos(it) => dyn_map[keys::TUPLE_FIELD].get(&src.with_value(it.clone())),
            FieldSource::Named(it) => dyn_map[keys::RECORD_FIELD].get(&src.with_value(it.clone())),
        }
        .copied()
        .map(StructField::from)
    }
}

impl Local {
    pub fn from_source(db: &impl HirDatabase, src: InFile<ast::BindPat>) -> Option<Self> {
        let file_id = src.file_id;
        let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| {
            let res = match_ast! {
                match it {
                    ast::ConstDef(value) => { Const::from_source(db, InFile { value, file_id})?.into() },
                    ast::StaticDef(value) => { Static::from_source(db, InFile { value, file_id})?.into() },
                    ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.into() },
                    _ => return None,
                }
            };
            Some(res)
        })?;
        let (_body, source_map) = db.body_with_source_map(parent.into());
        let src = src.map(ast::Pat::from);
        let pat_id = source_map.node_pat(src.as_ref())?;
        Some(Local { parent, pat_id })
    }
}

impl TypeParam {
    pub fn from_source(db: &impl HirDatabase, src: InFile<ast::TypeParam>) -> Option<Self> {
        let file_id = src.file_id;
        let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| {
            let res = match_ast! {
                match it {
                    ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::StructDef(value) => { Struct::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::EnumDef(value) => { Enum::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::TraitDef(value) => { Trait::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::TypeAliasDef(value) => { TypeAlias::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::ImplBlock(value) => { ImplBlock::from_source(db, InFile { value, file_id})?.id.into() },
                    _ => return None,
                }
            };
            Some(res)
        })?;
        let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?;
        Some(TypeParam { id })
    }
}

impl Module {
    pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> {
        let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);

        let parent_module = match parent_declaration {
            Some(parent_declaration) => {
                let src_parent = InFile { file_id: src.file_id, value: parent_declaration };
                Module::from_declaration(db, src_parent)
            }
            None => {
                let source_file = db.parse(src.file_id.original_file(db)).tree();
                let src_parent =
                    InFile { file_id: src.file_id, value: ModuleSource::SourceFile(source_file) };
                Module::from_definition(db, src_parent)
            }
        }?;

        let child_name = src.value.name()?.as_name();
        let def_map = db.crate_def_map(parent_module.id.krate);
        let child_id = def_map[parent_module.id.local_id].children.get(&child_name)?;
        Some(parent_module.with_module_id(*child_id))
    }

    pub fn from_definition(db: &impl DefDatabase, src: InFile<ModuleSource>) -> Option<Self> {
        match src.value {
            ModuleSource::Module(ref module) => {
                assert!(!module.has_semi());
                return Module::from_declaration(
                    db,
                    InFile { file_id: src.file_id, value: module.clone() },
                );
            }
            ModuleSource::SourceFile(_) => (),
        };

        let original_file = src.file_id.original_file(db);

        let (krate, local_id) = db.relevant_crates(original_file).iter().find_map(|&crate_id| {
            let crate_def_map = db.crate_def_map(crate_id);
            let local_id = crate_def_map.modules_for_file(original_file).next()?;
            Some((crate_id, local_id))
        })?;
        Some(Module { id: ModuleId { krate, local_id } })
    }
}

fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: InFile<N>) -> Option<DEF>
where
    N: AstNode,
    DEF: AstItemDef<N>,
{
    let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
    let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?;
    let ctx = LocationCtx::new(db, module.id, src.file_id);
    let items = db.ast_id_map(src.file_id);
    let item_id = items.ast_id(&src.value);
    Some(DEF::from_ast_id(ctx, item_id))
}

enum Container {
    Trait(Trait),
    ImplBlock(ImplBlock),
    Module(Module),
}

impl Container {
    fn find(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<Container> {
        // FIXME: this doesn't try to handle nested declarations
        for container in src.value.ancestors() {
            let res = match_ast! {
                match container {
                    ast::TraitDef(it) => {
                        let c = Trait::from_source(db, src.with_value(it))?;
                        Container::Trait(c)
                    },
                    ast::ImplBlock(it) => {
                        let c = ImplBlock::from_source(db, src.with_value(it))?;
                        Container::ImplBlock(c)
                     },
                    _ => { continue },
                }
            };
            return Some(res);
        }

        let module_source = ModuleSource::from_child_node(db, src);
        let c = Module::from_definition(db, src.with_value(module_source))?;
        Some(Container::Module(c))
    }
}

impl ChildBySource for Container {
    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
        match self {
            Container::Trait(it) => it.id.child_by_source(db),
            Container::ImplBlock(it) => it.id.child_by_source(db),
            Container::Module(it) => it.id.child_by_source(db),
        }
    }
}
<commit_msg>Simplify from_source<commit_after>//! FIXME: write short doc here
use hir_def::{
    child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef,
    EnumVariantId, GenericDefId, LocationCtx, ModuleId, VariantId,
};
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
use ra_syntax::{
    ast::{self, AstNode, NameOwner},
    match_ast, SyntaxNode,
};

use crate::{
    db::{AstDatabase, DefDatabase, HirDatabase},
    Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local,
    MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
};

pub trait FromSource: Sized {
    type Ast;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self>;
}

impl FromSource for Struct {
    type Ast = ast::StructDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let id = from_source(db, src)?;
        Some(Struct { id })
    }
}
impl FromSource for Union {
    type Ast = ast::UnionDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let id = from_source(db, src)?;
        Some(Union { id })
    }
}
impl FromSource for Enum {
    type Ast = ast::EnumDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let id = from_source(db, src)?;
        Some(Enum { id })
    }
}
impl FromSource for Trait {
    type Ast = ast::TraitDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TRAIT]
            .get(&src)
            .copied()
            .map(Trait::from)
    }
}
impl FromSource for Function {
    type Ast = ast::FnDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::FUNCTION]
            .get(&src)
            .copied()
            .map(Function::from)
    }
}

impl FromSource for Const {
    type Ast = ast::ConstDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::CONST]
            .get(&src)
            .copied()
            .map(Const::from)
    }
}
impl FromSource for Static {
    type Ast = ast::StaticDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STATIC]
            .get(&src)
            .copied()
            .map(Static::from)
    }
}

impl FromSource for TypeAlias {
    type Ast = ast::TypeAliasDef;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TYPE_ALIAS]
            .get(&src)
            .copied()
            .map(TypeAlias::from)
    }
}

impl FromSource for MacroDef {
    type Ast = ast::MacroCall;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let kind = MacroDefKind::Declarative;

        let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
        let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?;
        let krate = Some(module.krate().id);

        let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value)));

        let id: MacroDefId = MacroDefId { krate, ast_id, kind };
        Some(MacroDef { id })
    }
}

impl FromSource for ImplBlock {
    type Ast = ast::ImplBlock;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::IMPL]
            .get(&src)
            .copied()
            .map(ImplBlock::from)
    }
}

impl FromSource for EnumVariant {
    type Ast = ast::EnumVariant;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let parent_enum = src.value.parent_enum();
        let src_enum = InFile { file_id: src.file_id, value: parent_enum };
        let parent_enum = Enum::from_source(db, src_enum)?;
        parent_enum.id.child_by_source(db)[keys::ENUM_VARIANT]
            .get(&src)
            .copied()
            .map(EnumVariant::from)
    }
}

impl FromSource for StructField {
    type Ast = FieldSource;
    fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
        let src = src.as_ref();

        // FIXME this is buggy
        let variant_id: VariantId = match src.value {
            FieldSource::Named(field) => {
                let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
                let src = InFile { file_id: src.file_id, value };
                let def = Struct::from_source(db, src)?;
                def.id.into()
            }
            FieldSource::Pos(field) => {
                let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
                let src = InFile { file_id: src.file_id, value };
                let def = EnumVariant::from_source(db, src)?;
                EnumVariantId::from(def).into()
            }
        };

        let dyn_map = variant_id.child_by_source(db);
        match src.value {
            FieldSource::Pos(it) => dyn_map[keys::TUPLE_FIELD].get(&src.with_value(it.clone())),
            FieldSource::Named(it) => dyn_map[keys::RECORD_FIELD].get(&src.with_value(it.clone())),
        }
        .copied()
        .map(StructField::from)
    }
}

impl Local {
    pub fn from_source(db: &impl HirDatabase, src: InFile<ast::BindPat>) -> Option<Self> {
        let file_id = src.file_id;
        let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| {
            let res = match_ast! {
                match it {
                    ast::ConstDef(value) => { Const::from_source(db, InFile { value, file_id})?.into() },
                    ast::StaticDef(value) => { Static::from_source(db, InFile { value, file_id})?.into() },
                    ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.into() },
                    _ => return None,
                }
            };
            Some(res)
        })?;
        let (_body, source_map) = db.body_with_source_map(parent.into());
        let src = src.map(ast::Pat::from);
        let pat_id = source_map.node_pat(src.as_ref())?;
        Some(Local { parent, pat_id })
    }
}

impl TypeParam {
    pub fn from_source(db: &impl HirDatabase, src: InFile<ast::TypeParam>) -> Option<Self> {
        let file_id = src.file_id;
        let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| {
            let res = match_ast! {
                match it {
                    ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::StructDef(value) => { Struct::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::EnumDef(value) => { Enum::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::TraitDef(value) => { Trait::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::TypeAliasDef(value) => { TypeAlias::from_source(db, InFile { value, file_id})?.id.into() },
                    ast::ImplBlock(value) => { ImplBlock::from_source(db, InFile { value, file_id})?.id.into() },
                    _ => return None,
                }
            };
            Some(res)
        })?;
        let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?;
        Some(TypeParam { id })
    }
}

impl Module {
    pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> {
        let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);

        let parent_module = match parent_declaration {
            Some(parent_declaration) => {
                let src_parent = InFile { file_id: src.file_id, value: parent_declaration };
                Module::from_declaration(db, src_parent)
            }
            None => {
                let source_file = db.parse(src.file_id.original_file(db)).tree();
                let src_parent =
                    InFile { file_id: src.file_id, value: ModuleSource::SourceFile(source_file) };
                Module::from_definition(db, src_parent)
            }
        }?;

        let child_name = src.value.name()?.as_name();
        let def_map = db.crate_def_map(parent_module.id.krate);
        let child_id = def_map[parent_module.id.local_id].children.get(&child_name)?;
        Some(parent_module.with_module_id(*child_id))
    }

    pub fn from_definition(db: &impl DefDatabase, src: InFile<ModuleSource>) -> Option<Self> {
        match src.value {
            ModuleSource::Module(ref module) => {
                assert!(!module.has_semi());
                return Module::from_declaration(
                    db,
                    InFile { file_id: src.file_id, value: module.clone() },
                );
            }
            ModuleSource::SourceFile(_) => (),
        };

        let original_file = src.file_id.original_file(db);

        let (krate, local_id) = db.relevant_crates(original_file).iter().find_map(|&crate_id| {
            let crate_def_map = db.crate_def_map(crate_id);
            let local_id = crate_def_map.modules_for_file(original_file).next()?;
            Some((crate_id, local_id))
        })?;
        Some(Module { id: ModuleId { krate, local_id } })
    }
}

fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: InFile<N>) -> Option<DEF>
where
    N: AstNode,
    DEF: AstItemDef<N>,
{
    let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
    let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?;
    let ctx = LocationCtx::new(db, module.id, src.file_id);
    let items = db.ast_id_map(src.file_id);
    let item_id = items.ast_id(&src.value);
    Some(DEF::from_ast_id(ctx, item_id))
}

fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap {
    _analyze_container(db, src).unwrap_or_default()
}

fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<DynMap> {
    // FIXME: this doesn't try to handle nested declarations
    for container in src.value.ancestors().skip(1) {
        let res = match_ast! {
            match container {
                ast::TraitDef(it) => {
                    let c = Trait::from_source(db, src.with_value(it))?;
                    c.id.child_by_source(db)
                },
                ast::ImplBlock(it) => {
                    let c = ImplBlock::from_source(db, src.with_value(it))?;
                    c.id.child_by_source(db)
                 },
                _ => { continue },
            }
        };
        return Some(res);
    }

    let module_source = ModuleSource::from_child_node(db, src);
    let c = Module::from_definition(db, src.with_value(module_source))?;
    Some(c.id.child_by_source(db))
}
<|endoftext|>


<commit_before>use std::hash::{Hash};
use std::slice::{
    Items,
};
use std::fmt;
use test;

// FIXME: These aren't stable, so a public wrapper of node/edge indices
// should be lifetimed just like pointers.
#[deriving(Copy, Clone, Show, PartialEq, PartialOrd, Eq, Hash)]
pub struct NodeIndex(uint);
#[deriving(Copy, Clone, Show, PartialEq, PartialOrd, Eq, Hash)]
pub struct EdgeIndex(uint);

const EdgeEnd: EdgeIndex = EdgeIndex(::std::uint::MAX);
//const InvalidNode: NodeIndex = NodeIndex(::std::uint::MAX);

/// Index into the NodeIndex and EdgeIndex arrays
#[deriving(Copy, Clone, Show, PartialEq)]
enum Dir {
    Out = 0,
    In = 1
}

const DIRECTIONS: [Dir, ..2] = [Dir::Out, Dir::In];

#[deriving(Show)]
pub struct Node<N> {
    pub data: N,
    /// Next edge in outgoing and incoming edge lists.
    next: [EdgeIndex, ..2],
}

#[deriving(Show, Copy)]
pub struct Edge<E> {
    pub data: E,
    /// Next edge in outgoing and incoming edge lists.
    next: [EdgeIndex, ..2],
    /// Start and End node index
    node: [NodeIndex, ..2],
}

/// **OGraph\<N, E\>** is a directed graph using an adjacency list representation.
///
/// The graph maintains unique indices for nodes and edges, so both node and edge
/// data may be accessed mutably. Removing nodes or edges from the graph is expensive,
/// while adding is very cheap.
///
/// Based upon the graph implementation in rustc.
//#[deriving(Show)]
pub struct OGraph<N, E> {
    nodes: Vec<Node<N>>,
    edges: Vec<Edge<E>>,
}

impl<N: fmt::Show, E: fmt::Show> fmt::Show for OGraph<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for n in self.nodes.iter() {
            try!(writeln!(f, "{}", n));
        }
        for n in self.edges.iter() {
            try!(writeln!(f, "{}", n));
        }
        Ok(())
    }
}

pub enum Pair<'a, T: 'a> {
    Both(&'a mut T, &'a mut T),
    One(&'a mut T),
    None,
}

pub fn index_twice<T>(slc: &mut [T], a: uint, b: uint) -> Pair<T>
{
    if a == b {
        slc.get_mut(a).map_or(Pair::None, Pair::One)
    } else {
        if a >= slc.len() || b >= slc.len() {
            Pair::None
        } else {
            // safe because a, b are in bounds and distinct
            unsafe {
                let ar = &mut *(slc.unsafe_mut(a) as *mut _);
                let br = &mut *(slc.unsafe_mut(b) as *mut _);
                Pair::Both(ar, br)
            }
        }
    }
}

/// Iterate over an edge list.
fn walk_edge_list<E, F: FnMut(EdgeIndex, &mut Edge<E>) -> bool>(
    fst: EdgeIndex, edges: &mut [Edge<E>], d: Dir, mut f: F)
{
    let k = d as uint;
    let mut cur = fst;
    loop {
        match edges.get_mut(cur.0) {
            None => {
                debug_assert!(cur == EdgeEnd);
                break;
            }
            Some(curedge) => {
                if !f(cur, curedge) {
                    break;
                }
                cur = curedge.next[k];
            }
        }
    }
}

impl<N, E> OGraph<N, E>
//where N: fmt::Show
{
    pub fn new() -> OGraph<N, E>
    {
        OGraph{nodes: Vec::new(), edges: Vec::new()}
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex
    {
        let node = Node{data: data, next: [EdgeEnd, EdgeEnd]};
        let node_idx = NodeIndex(self.nodes.len());
        self.nodes.push(node);
        node_idx
    }

    pub fn node(&self, a: NodeIndex) -> Option<&N>
    {
        self.nodes.get(a.0).map(|n| &n.data)
    }

    pub fn node_mut(&mut self, a: NodeIndex) -> Option<&mut N>
    {
        self.nodes.get_mut(a.0).map(|n| &mut n.data)
    }

    pub fn neighbors(&self, a: NodeIndex) -> Neighbors<N, E>
    {
        Neighbors{
            graph: self,
            next: match self.nodes.get(a.0) {
                None => EdgeEnd,
                Some(n) => n.next[0],
            }
        }
    }

    pub fn edges(&self, a: NodeIndex) -> Edges<N, E>
    {
        Edges{
            graph: self,
            next: match self.nodes.get(a.0) {
                None => EdgeEnd,
                Some(n) => n.next[0],
            }
        }
    }

    pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, data: E) -> EdgeIndex
    {
        let edge_idx = EdgeIndex(self.edges.len());
        match index_twice(self.nodes[mut], a.0, b.0) {
            Pair::None => panic!("NodeIndices out of bounds"),
            Pair::One(an) => {
                let edge = Edge {
                    data: data,
                    node: [a, b],
                    next: an.next,
                };
                an.next[0] = edge_idx;
                an.next[1] = edge_idx;
                self.edges.push(edge);
            }
            Pair::Both(an, bn) => {
                // a and b are different indices
                let edge = Edge {
                    data: data,
                    node: [a, b],
                    next: [an.next[0], bn.next[1]],
                };
                an.next[0] = edge_idx;
                bn.next[1] = edge_idx;
                self.edges.push(edge);
            }
        }
        edge_idx
    }

    pub fn remove_node(&mut self, a: NodeIndex) -> Option<N>
    {
        match self.nodes.get(a.0) {
            None => return None,
            _ => {}
        }
        for d in DIRECTIONS.iter() {
            let k = *d as uint;
            /*
            println!("Starting edge removal for k={}, node={}", k, a);
            for (i, n) in self.nodes.iter().enumerate() {
                println!("Node {}: Edges={}", i, n.next);
            }
            for (i, ed) in self.edges.iter().enumerate() {
                println!("Edge {}: {}", i, ed);
            }
            */
            // Remove all edges from and to this node.
            loop {
                let next = self.nodes[a.0].next[k];
                if next == EdgeEnd {
                    break
                }
                let ret = self.remove_edge(next);
                debug_assert!(ret.is_some());
                let _ = ret;
            }
        }

        // Use swap_remove -- only the swapped-in node is going to change
        // NodeIndex, so we only have to walk its edges and update them.

        let node = match self.nodes.swap_remove(a.0) {
            None => return None,
            Some(node) => node,
        };

        // Find the edge lists of the node that had to relocate.
        // It may be that no node had to relocate, then we are done already.
        let swap_edges = match self.nodes.get(a.0) {
            None => return Some(node.data),
            Some(ed) => ed.next,
        };

        // The swapped element's old index
        let old_index = NodeIndex(self.nodes.len());
        let new_index = a;

        // Adjust the starts of the out edges, and ends of the in edges.
        for &d in DIRECTIONS.iter() {
            let k = d as uint;
            walk_edge_list(swap_edges[k], self.edges[mut], d, |_, curedge| {
                debug_assert!(curedge.node[k] == old_index);
                curedge.node[k] = new_index;
                true
            });
        }
        Some(node.data)
    }

    pub fn edge_mut(&mut self, e: EdgeIndex) -> &mut Edge<E>
    {
        &mut self.edges[e.0]
    }

    /// Remove an edge and return its edge weight, or None if it didn't exist.
    pub fn remove_edge(&mut self, e: EdgeIndex) -> Option<E>
    {
        // every edge is part of two lists,
        // outgoing and incoming edges.
        // Remove it from both
        //debug_assert!(self.edges.get(e.0).is_some(), "No such edge: {}", e);
        let (edge_node, edge_next) = match self.edges.get(e.0) {
            None => return None,
            Some(x) => (x.node, x.next),
        };
        // List out from A
        // List in from B
        for &d in DIRECTIONS.iter() {
            let k = d as uint;
            let node = match self.nodes.get_mut(edge_node[k].0) {
                Some(r) => r,
                None => {
                    debug_assert!(false, "Edge's endpoint dir={} index={} not found",
                                  k, edge_node[k]);
                    return None
                }
            };
            let fst = node.next[k];
            if fst == e {
                //println!("Updating first edge 0 for node {}, set to {}", edge_node[0], edge_next[0]);
                node.next[k] = edge_next[k];
            } else {
                walk_edge_list(fst, self.edges[mut], d, |eidx, curedge| {
                    if curedge.next[k] == e {
                        curedge.next[k] = edge_next[k];
                        false
                    } else { true }
                });
            }
        }
        self.remove_edge_adjust_indices(e)
    }

    fn remove_edge_adjust_indices(&mut self, e: EdgeIndex) -> Option<E>
    {
        // swap_remove the edge -- only the removed edge
        // and the edge swapped into place are affected and need updating
        // indices.
        let edge = self.edges.swap_remove(e.0).unwrap();
        let swap = match self.edges.get(e.0) {
            // no elment needed to be swapped.
            None => return Some(edge.data),
            Some(ed) => ed.node,
        };
        let swapped_e = EdgeIndex(self.edges.len());

        // List out from A
        // List in to B
        for &d in DIRECTIONS.iter() {
            let k = d as uint;
            let node = &mut self.nodes[swap[k].0];
            let fst = node.next[k];
            if fst == swapped_e {
                node.next[k] = e;
            } else {
                walk_edge_list(fst, self.edges[mut], d, |eidx, curedge| {
                    if curedge.next[k] == swapped_e {
                        curedge.next[k] = e;
                        false
                    } else { true }
                });
            }
        }
        let edge_data = edge.data;
        Some(edge_data)
    }
}

pub struct Neighbors<'a, N: 'a, E: 'a> {
    graph: &'a OGraph<N, E>,
    next: EdgeIndex,
}

impl<'a, N, E> Iterator<NodeIndex> for Neighbors<'a, N, E>
{
    fn next(&mut self) -> Option<NodeIndex>
    {
        match self.graph.edges.get(self.next.0) {
            None => None,
            Some(edge) => {
                self.next = edge.next[0];
                Some(edge.node[1])
            }
        }
    }
}

pub struct Edges<'a, N: 'a, E: 'a> {
    graph: &'a OGraph<N, E>,
    next: EdgeIndex,
}

impl<'a, N, E> Iterator<(NodeIndex, &'a E)> for Edges<'a, N, E>
{
    fn next(&mut self) -> Option<(NodeIndex, &'a E)>
    {
        match self.graph.edges.get(self.next.0) {
            None => None,
            Some(edge) => {
                self.next = edge.next[0];
                Some((edge.node[1], &edge.data))
            }
        }
    }
}
#[bench]
fn bench_inser(b: &mut test::Bencher) {
    let mut og = OGraph::new();
    let fst = og.add_node(0i);
    for x in range(1, 125) {
        let n = og.add_node(x);
        og.add_edge(fst, n, ());
    }
    b.iter(|| {
        og.add_node(1)
    })
}

#[bench]
fn bench_remove(b: &mut test::Bencher) {
    // removal is very slow in a big graph.
    // and this one doesn't even have many nodes.
    let mut og = OGraph::new();
    let fst = og.add_node(0i);
    let mut prev = fst;
    for x in range(1, 1250) {
        let n = og.add_node(x);
        og.add_edge(prev, n, ());
        prev = n;
    }
    //println!("{}", og);
    b.iter(|| {
        for _ in range(0, 100i) {
            og.remove_node(fst);
        }
    })
}
<commit_msg>Update OGraph doc<commit_after>use std::hash::{Hash};
use std::slice::{
    Items,
};
use std::fmt;
use test;

// FIXME: These aren't stable, so a public wrapper of node/edge indices
// should be lifetimed just like pointers.
#[deriving(Copy, Clone, Show, PartialEq, PartialOrd, Eq, Hash)]
pub struct NodeIndex(uint);
#[deriving(Copy, Clone, Show, PartialEq, PartialOrd, Eq, Hash)]
pub struct EdgeIndex(uint);

const EdgeEnd: EdgeIndex = EdgeIndex(::std::uint::MAX);
//const InvalidNode: NodeIndex = NodeIndex(::std::uint::MAX);

/// Index into the NodeIndex and EdgeIndex arrays
#[deriving(Copy, Clone, Show, PartialEq)]
enum Dir {
    Out = 0,
    In = 1
}

const DIRECTIONS: [Dir, ..2] = [Dir::Out, Dir::In];

#[deriving(Show)]
pub struct Node<N> {
    pub data: N,
    /// Next edge in outgoing and incoming edge lists.
    next: [EdgeIndex, ..2],
}

#[deriving(Show, Copy)]
pub struct Edge<E> {
    pub data: E,
    /// Next edge in outgoing and incoming edge lists.
    next: [EdgeIndex, ..2],
    /// Start and End node index
    node: [NodeIndex, ..2],
}

/// **OGraph\<N, E\>** is a directed graph using an adjacency list representation.
///
/// The graph maintains unique indices for nodes and edges, so both node and edge
/// data may be accessed mutably.
///
/// Based upon the graph implementation in rustc.
//#[deriving(Show)]
pub struct OGraph<N, E> {
    nodes: Vec<Node<N>>,
    edges: Vec<Edge<E>>,
}

impl<N: fmt::Show, E: fmt::Show> fmt::Show for OGraph<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for n in self.nodes.iter() {
            try!(writeln!(f, "{}", n));
        }
        for n in self.edges.iter() {
            try!(writeln!(f, "{}", n));
        }
        Ok(())
    }
}

pub enum Pair<'a, T: 'a> {
    Both(&'a mut T, &'a mut T),
    One(&'a mut T),
    None,
}

pub fn index_twice<T>(slc: &mut [T], a: uint, b: uint) -> Pair<T>
{
    if a == b {
        slc.get_mut(a).map_or(Pair::None, Pair::One)
    } else {
        if a >= slc.len() || b >= slc.len() {
            Pair::None
        } else {
            // safe because a, b are in bounds and distinct
            unsafe {
                let ar = &mut *(slc.unsafe_mut(a) as *mut _);
                let br = &mut *(slc.unsafe_mut(b) as *mut _);
                Pair::Both(ar, br)
            }
        }
    }
}

/// Iterate over an edge list.
fn walk_edge_list<E, F: FnMut(EdgeIndex, &mut Edge<E>) -> bool>(
    fst: EdgeIndex, edges: &mut [Edge<E>], d: Dir, mut f: F)
{
    let k = d as uint;
    let mut cur = fst;
    loop {
        match edges.get_mut(cur.0) {
            None => {
                debug_assert!(cur == EdgeEnd);
                break;
            }
            Some(curedge) => {
                if !f(cur, curedge) {
                    break;
                }
                cur = curedge.next[k];
            }
        }
    }
}

impl<N, E> OGraph<N, E>
//where N: fmt::Show
{
    pub fn new() -> OGraph<N, E>
    {
        OGraph{nodes: Vec::new(), edges: Vec::new()}
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex
    {
        let node = Node{data: data, next: [EdgeEnd, EdgeEnd]};
        let node_idx = NodeIndex(self.nodes.len());
        self.nodes.push(node);
        node_idx
    }

    pub fn node(&self, a: NodeIndex) -> Option<&N>
    {
        self.nodes.get(a.0).map(|n| &n.data)
    }

    pub fn node_mut(&mut self, a: NodeIndex) -> Option<&mut N>
    {
        self.nodes.get_mut(a.0).map(|n| &mut n.data)
    }

    pub fn neighbors(&self, a: NodeIndex) -> Neighbors<N, E>
    {
        Neighbors{
            graph: self,
            next: match self.nodes.get(a.0) {
                None => EdgeEnd,
                Some(n) => n.next[0],
            }
        }
    }

    pub fn edges(&self, a: NodeIndex) -> Edges<N, E>
    {
        Edges{
            graph: self,
            next: match self.nodes.get(a.0) {
                None => EdgeEnd,
                Some(n) => n.next[0],
            }
        }
    }

    pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, data: E) -> EdgeIndex
    {
        let edge_idx = EdgeIndex(self.edges.len());
        match index_twice(self.nodes[mut], a.0, b.0) {
            Pair::None => panic!("NodeIndices out of bounds"),
            Pair::One(an) => {
                let edge = Edge {
                    data: data,
                    node: [a, b],
                    next: an.next,
                };
                an.next[0] = edge_idx;
                an.next[1] = edge_idx;
                self.edges.push(edge);
            }
            Pair::Both(an, bn) => {
                // a and b are different indices
                let edge = Edge {
                    data: data,
                    node: [a, b],
                    next: [an.next[0], bn.next[1]],
                };
                an.next[0] = edge_idx;
                bn.next[1] = edge_idx;
                self.edges.push(edge);
            }
        }
        edge_idx
    }

    pub fn remove_node(&mut self, a: NodeIndex) -> Option<N>
    {
        match self.nodes.get(a.0) {
            None => return None,
            _ => {}
        }
        for d in DIRECTIONS.iter() {
            let k = *d as uint;
            /*
            println!("Starting edge removal for k={}, node={}", k, a);
            for (i, n) in self.nodes.iter().enumerate() {
                println!("Node {}: Edges={}", i, n.next);
            }
            for (i, ed) in self.edges.iter().enumerate() {
                println!("Edge {}: {}", i, ed);
            }
            */
            // Remove all edges from and to this node.
            loop {
                let next = self.nodes[a.0].next[k];
                if next == EdgeEnd {
                    break
                }
                let ret = self.remove_edge(next);
                debug_assert!(ret.is_some());
                let _ = ret;
            }
        }

        // Use swap_remove -- only the swapped-in node is going to change
        // NodeIndex, so we only have to walk its edges and update them.

        let node = match self.nodes.swap_remove(a.0) {
            None => return None,
            Some(node) => node,
        };

        // Find the edge lists of the node that had to relocate.
        // It may be that no node had to relocate, then we are done already.
        let swap_edges = match self.nodes.get(a.0) {
            None => return Some(node.data),
            Some(ed) => ed.next,
        };

        // The swapped element's old index
        let old_index = NodeIndex(self.nodes.len());
        let new_index = a;

        // Adjust the starts of the out edges, and ends of the in edges.
        for &d in DIRECTIONS.iter() {
            let k = d as uint;
            walk_edge_list(swap_edges[k], self.edges[mut], d, |_, curedge| {
                debug_assert!(curedge.node[k] == old_index);
                curedge.node[k] = new_index;
                true
            });
        }
        Some(node.data)
    }

    pub fn edge_mut(&mut self, e: EdgeIndex) -> &mut Edge<E>
    {
        &mut self.edges[e.0]
    }

    /// Remove an edge and return its edge weight, or None if it didn't exist.
    pub fn remove_edge(&mut self, e: EdgeIndex) -> Option<E>
    {
        // every edge is part of two lists,
        // outgoing and incoming edges.
        // Remove it from both
        //debug_assert!(self.edges.get(e.0).is_some(), "No such edge: {}", e);
        let (edge_node, edge_next) = match self.edges.get(e.0) {
            None => return None,
            Some(x) => (x.node, x.next),
        };
        // List out from A
        // List in from B
        for &d in DIRECTIONS.iter() {
            let k = d as uint;
            let node = match self.nodes.get_mut(edge_node[k].0) {
                Some(r) => r,
                None => {
                    debug_assert!(false, "Edge's endpoint dir={} index={} not found",
                                  k, edge_node[k]);
                    return None
                }
            };
            let fst = node.next[k];
            if fst == e {
                //println!("Updating first edge 0 for node {}, set to {}", edge_node[0], edge_next[0]);
                node.next[k] = edge_next[k];
            } else {
                walk_edge_list(fst, self.edges[mut], d, |eidx, curedge| {
                    if curedge.next[k] == e {
                        curedge.next[k] = edge_next[k];
                        false
                    } else { true }
                });
            }
        }
        self.remove_edge_adjust_indices(e)
    }

    fn remove_edge_adjust_indices(&mut self, e: EdgeIndex) -> Option<E>
    {
        // swap_remove the edge -- only the removed edge
        // and the edge swapped into place are affected and need updating
        // indices.
        let edge = self.edges.swap_remove(e.0).unwrap();
        let swap = match self.edges.get(e.0) {
            // no elment needed to be swapped.
            None => return Some(edge.data),
            Some(ed) => ed.node,
        };
        let swapped_e = EdgeIndex(self.edges.len());

        // List out from A
        // List in to B
        for &d in DIRECTIONS.iter() {
            let k = d as uint;
            let node = &mut self.nodes[swap[k].0];
            let fst = node.next[k];
            if fst == swapped_e {
                node.next[k] = e;
            } else {
                walk_edge_list(fst, self.edges[mut], d, |eidx, curedge| {
                    if curedge.next[k] == swapped_e {
                        curedge.next[k] = e;
                        false
                    } else { true }
                });
            }
        }
        let edge_data = edge.data;
        Some(edge_data)
    }
}

pub struct Neighbors<'a, N: 'a, E: 'a> {
    graph: &'a OGraph<N, E>,
    next: EdgeIndex,
}

impl<'a, N, E> Iterator<NodeIndex> for Neighbors<'a, N, E>
{
    fn next(&mut self) -> Option<NodeIndex>
    {
        match self.graph.edges.get(self.next.0) {
            None => None,
            Some(edge) => {
                self.next = edge.next[0];
                Some(edge.node[1])
            }
        }
    }
}

pub struct Edges<'a, N: 'a, E: 'a> {
    graph: &'a OGraph<N, E>,
    next: EdgeIndex,
}

impl<'a, N, E> Iterator<(NodeIndex, &'a E)> for Edges<'a, N, E>
{
    fn next(&mut self) -> Option<(NodeIndex, &'a E)>
    {
        match self.graph.edges.get(self.next.0) {
            None => None,
            Some(edge) => {
                self.next = edge.next[0];
                Some((edge.node[1], &edge.data))
            }
        }
    }
}
#[bench]
fn bench_inser(b: &mut test::Bencher) {
    let mut og = OGraph::new();
    let fst = og.add_node(0i);
    for x in range(1, 125) {
        let n = og.add_node(x);
        og.add_edge(fst, n, ());
    }
    b.iter(|| {
        og.add_node(1)
    })
}

#[bench]
fn bench_remove(b: &mut test::Bencher) {
    // removal is very slow in a big graph.
    // and this one doesn't even have many nodes.
    let mut og = OGraph::new();
    let fst = og.add_node(0i);
    let mut prev = fst;
    for x in range(1, 1250) {
        let n = og.add_node(x);
        og.add_edge(prev, n, ());
        prev = n;
    }
    //println!("{}", og);
    b.iter(|| {
        for _ in range(0, 100i) {
            og.remove_node(fst);
        }
    })
}
<|endoftext|>


<commit_before>//! XML-RPC response parser.

use {Value, Response, Fault};
use error::ParseError;

use base64;
use xml::reader::{XmlEvent, EventReader};
use xml::name::OwnedName;
use xml::common::Position;
use xml::ParserConfig;
use iso8601::datetime;
use std::io::{self, ErrorKind, Read};
use std::collections::BTreeMap;

pub type ParseResult<T> = Result<T, ParseError>;

pub struct Parser<'a, R: Read + 'a> {
    reader: EventReader<&'a mut R>,
}

impl<'a, R: Read> Parser<'a, R> {
    pub fn new(reader: &'a mut R) -> Self {
        Parser {
            reader: EventReader::new_with_config(reader, ParserConfig {
                cdata_to_characters: true,
                ..Default::default()
            }),
        }
    }

    /// Reads an `XmlEvent` from a reader, disposing events we want to ignore.
    fn pull_event(&mut self) -> ParseResult<XmlEvent> {
        loop {
            let event = try!(self.reader.next());
            match event {
                XmlEvent::StartDocument { .. }
                | XmlEvent::Comment(_)
                | XmlEvent::Whitespace(_)
                | XmlEvent::ProcessingInstruction { .. } => {},
                XmlEvent::StartElement { .. }
                | XmlEvent::EndElement { .. }
                | XmlEvent::EndDocument
                | XmlEvent::CData(_)
                | XmlEvent::Characters(_) => {
                    return Ok(event);
                }
            }
        }
    }

    /// Expects an opening tag like `<tag>` without attributes (and a local name without namespaces).
    fn expect_open(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. }
            if name == &OwnedName::local(tag) => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", tag));
                }

                Ok(())
            }
            _ => return self.unexpected(format!("expected <{}>", tag)),
        }
    }

    /// Expects a closing tag like `</tag>` with a local name without namespaces.
    fn expect_close(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::EndElement { ref name } if name == &OwnedName::local(tag) => {
                Ok(())
            }
            _ => self.unexpected(format!("expected </{}>", tag)),
        }
    }

    /// Builds and returns an `Err(UnexpectedXml)`.
    fn unexpected<T, E: ToString>(&self, expected: E) -> ParseResult<T> {
        let expected = expected.to_string();
        let position = self.reader.position();

        Err(ParseError::UnexpectedXml {
            expected: expected,
            position: position,
        })
    }

    fn parse_response(&mut self) -> ParseResult<Response> {
        let response: Response;

        // <methodResponse>
        try!(self.expect_open("methodResponse"));

        // <fault> / <params>
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected("unexpected attributes");
                }

                if name == &OwnedName::local("fault") {
                    let value = try!(self.parse_value());
                    let fault = try!(Fault::from_value(&value).ok_or_else(|| {
                        io::Error::new(ErrorKind::Other, "malformed <fault>")
                    }));
                    response = Err(fault);
                } else if name == &OwnedName::local("params") {
                    // <param>
                    try!(self.expect_open("param"));

                    let value = try!(self.parse_value());
                    response = Ok(value);

                    // </param>
                    try!(self.expect_close("param"));
                } else {
                    return self.unexpected(format!("expected <fault> or <params>, got {}", name));
                }
            }
            _ => return self.unexpected("expected <fault> or <params>"),
        }

        Ok(response)
    }

    pub fn parse_value(&mut self) -> ParseResult<Value> {
        // <value>
        try!(self.expect_open("value"));

        let value = try!(self.parse_value_inner());

        // </value>
        try!(self.expect_close("value"));

        Ok(value)
    }

    fn parse_value_inner(&mut self) -> ParseResult<Value> {
        let value: Value;

        // Raw string or specific type tag
        value = match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                }

                if name == &OwnedName::local("struct") {
                    let mut members = BTreeMap::new();
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("struct") => break,
                            XmlEvent::StartElement { ref name, ref attributes, .. } if name == &OwnedName::local("member") => {
                                // <member>
                                if !attributes.is_empty() {
                                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                                }

                                // <name>NAME</name>
                                try!(self.expect_open("name"));
                                let name = match try!(self.pull_event()) {
                                    XmlEvent::Characters(string) => string,
                                    _ => return self.unexpected("expected CDATA"),
                                };
                                try!(self.expect_close("name"));

                                // Value
                                let value = try!(self.parse_value());

                                // </member>
                                try!(self.expect_close("member"));

                                members.insert(name, value);
                            }
                            _ => return self.unexpected("expected </struct> or <member>"),
                        }
                    }

                    Value::Struct(members)
                } else if name == &OwnedName::local("array") {
                    let mut elements: Vec<Value> = Vec::new();
                    try!(self.expect_open("data"));
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("data") => break,
                            XmlEvent::StartElement { ref name, .. } if name == &OwnedName::local("value") => {
                                elements.push(try!(self.parse_value_inner()));
                                try!(self.expect_close("value"));
                            }
                            _event => return self.unexpected("expected </data> or <value>")
                        }
                    }
                    try!(self.expect_close("array"));
                    Value::Array(elements)
                } else if name == &OwnedName::local("nil") {
                    try!(self.expect_close("nil"));
                    Value::Nil
                } else {
                    // All other types expect raw characters...
                    let data = match try!(self.pull_event()) {
                        XmlEvent::Characters(string) => string,
                        _ => return self.unexpected("expected characters"),
                    };

                    // ...and a corresponding close tag
                    try!(self.expect_close(&name.local_name));

                    if name == &OwnedName::local("i4") || name == &OwnedName::local("int") {
                        Value::Int(try!(data.parse::<i32>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("i8") {
                        Value::Int64(try!(data.parse::<i64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for 64-bit integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("boolean") {
                        let val = match data.trim() {
                            "0" => false,
                            "1" => true,
                            _ => return Err(io::Error::new(ErrorKind::Other, format!("invalid value for <boolean>: {}", data)).into())
                        };

                        Value::Bool(val)
                    } else if name == &OwnedName::local("string") {
                        Value::String(data.clone())
                    } else if name == &OwnedName::local("double") {
                        Value::Double(try!(data.parse::<f64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for double: {}", data))
                        })))
                    } else if name == &OwnedName::local("dateTime.iso8601") {
                        Value::DateTime(try!(datetime(&data).map_err(|e| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for dateTime.iso8601: {} ({})", data, e))
                        })))
                    } else if name == &OwnedName::local("base64") {
                        Value::Base64(try!(base64::decode(&data).map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for base64: {}", data))
                        })))
                    } else {
                        return self.unexpected("invalid <value> content");
                    }
                }
            }
            XmlEvent::Characters(string) => {
                Value::String(string)
            }
            _ => return self.unexpected("invalid <value> content"),
        };

        Ok(value)
    }
}

/// Parses a response from an XML reader.
pub fn parse_response<R: Read>(reader: &mut R) -> ParseResult<Response> {
    Parser::new(reader).parse_response()
}

#[cfg(test)]
mod tests {
    use super::*;

    use {Response, Value};
    use error::Fault;
    use std::fmt::Debug;

    fn read_response(xml: &str) -> ParseResult<Response> {
        parse_response(&mut xml.as_bytes())
    }

    fn read_value(xml: &str) -> ParseResult<Value> {
        Parser::new(&mut xml.as_bytes()).parse_value()
    }

    fn assert_ok<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => println!("assert_ok successful on Ok: {:?}", t),
            Err(e) => panic!("assert_ok called on Err value: {:?}", e),
        }
    }

    fn assert_err<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => panic!("assert_err called on Ok value: {:?}", t),
            Err(e) => println!("assert_err successful on Err: {:?}", e),
        }
    }

    #[test]
    fn parses_fault() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn ignores_additional_fault_fields() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            <member>
               <name>unnecessaryParameter</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn rejects_invalid_faults() {
        // Make sure to reject type errors in <fault>s - They're specified to contain specifically
        // typed fields.
        assert!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><string>I'm not an int!</string></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##).is_err());
    }

    #[test]
    fn parses_string_value_with_whitespace() {
        assert_eq!(read_value("<value><string>  I'm a string!  </string></value>"),
            Ok(Value::String("  I'm a string!  ".into())));
    }

    #[test]
    fn parses_64bit_int() {
        assert_eq!(read_value("<value><i8>12345</i8></value>"),
            Ok(Value::Int64(12345)));
        assert_eq!(read_value("<value><i8>-100100100100</i8></value>"),
            Ok(Value::Int64(-100100100100)));
    }

    #[test]
    fn parses_date_values() {
        assert_ok(read_value("<value><dateTime.iso8601>2015-02-18T23:16:09Z</dateTime.iso8601></value>"));
        assert_ok(read_value("<value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>"));
    }

    #[test]
    fn parses_array_values() {
        assert_eq!(read_value(r#"
                <value><array><data>
                    <value><i4>5</i4></value>
                    <value><string>a</string></value>
                </data></array></value>"#),
            Ok(Value::Array(vec![Value::Int(5), Value::String("a".into())])));
    }

    #[test]
    fn parses_raw_value_as_string() {
        assert_eq!(read_value("<value>\t  I'm a string!  </value>"),
            Ok(Value::String("\t  I'm a string!  ".into())));
    }

    #[test]
    fn parses_nil_values() {
        assert_eq!(read_value("<value><nil/></value>"), Ok(Value::Nil));
        assert_eq!(read_value("<value><nil></nil></value>"), Ok(Value::Nil));
    }

    #[test]
    fn unescapes_values() {
        assert_eq!(read_value("<value><string>abc<abc&abc</string></value>"),
            Ok(Value::String("abc<abc&abc".into())));
    }

    #[test]
    fn rejects_value_with_attributes() {
        // XXX we *should* reject everything with attributes
        assert_err(read_value(r#"<value name="ble">\t  I'm a string!  </value>"#));
    }
}
<commit_msg>Not sure how attributes are supposed to behave<commit_after>//! XML-RPC response parser.

use {Value, Response, Fault};
use error::ParseError;

use base64;
use xml::reader::{XmlEvent, EventReader};
use xml::name::OwnedName;
use xml::common::Position;
use xml::ParserConfig;
use iso8601::datetime;
use std::io::{self, ErrorKind, Read};
use std::collections::BTreeMap;

pub type ParseResult<T> = Result<T, ParseError>;

pub struct Parser<'a, R: Read + 'a> {
    reader: EventReader<&'a mut R>,
}

impl<'a, R: Read> Parser<'a, R> {
    pub fn new(reader: &'a mut R) -> Self {
        Parser {
            reader: EventReader::new_with_config(reader, ParserConfig {
                cdata_to_characters: true,
                ..Default::default()
            }),
        }
    }

    /// Reads an `XmlEvent` from a reader, disposing events we want to ignore.
    fn pull_event(&mut self) -> ParseResult<XmlEvent> {
        loop {
            let event = try!(self.reader.next());
            match event {
                XmlEvent::StartDocument { .. }
                | XmlEvent::Comment(_)
                | XmlEvent::Whitespace(_)
                | XmlEvent::ProcessingInstruction { .. } => {},
                XmlEvent::StartElement { .. }
                | XmlEvent::EndElement { .. }
                | XmlEvent::EndDocument
                | XmlEvent::CData(_)
                | XmlEvent::Characters(_) => {
                    return Ok(event);
                }
            }
        }
    }

    /// Expects an opening tag like `<tag>` without attributes (and a local name without namespaces).
    fn expect_open(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. }
            if name == &OwnedName::local(tag) => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", tag));
                }

                Ok(())
            }
            _ => return self.unexpected(format!("expected <{}>", tag)),
        }
    }

    /// Expects a closing tag like `</tag>` with a local name without namespaces.
    fn expect_close(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::EndElement { ref name } if name == &OwnedName::local(tag) => {
                Ok(())
            }
            _ => self.unexpected(format!("expected </{}>", tag)),
        }
    }

    /// Builds and returns an `Err(UnexpectedXml)`.
    fn unexpected<T, E: ToString>(&self, expected: E) -> ParseResult<T> {
        let expected = expected.to_string();
        let position = self.reader.position();

        Err(ParseError::UnexpectedXml {
            expected: expected,
            position: position,
        })
    }

    fn parse_response(&mut self) -> ParseResult<Response> {
        let response: Response;

        // <methodResponse>
        try!(self.expect_open("methodResponse"));

        // <fault> / <params>
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected("unexpected attributes");
                }

                if name == &OwnedName::local("fault") {
                    let value = try!(self.parse_value());
                    let fault = try!(Fault::from_value(&value).ok_or_else(|| {
                        io::Error::new(ErrorKind::Other, "malformed <fault>")
                    }));
                    response = Err(fault);
                } else if name == &OwnedName::local("params") {
                    // <param>
                    try!(self.expect_open("param"));

                    let value = try!(self.parse_value());
                    response = Ok(value);

                    // </param>
                    try!(self.expect_close("param"));
                } else {
                    return self.unexpected(format!("expected <fault> or <params>, got {}", name));
                }
            }
            _ => return self.unexpected("expected <fault> or <params>"),
        }

        Ok(response)
    }

    pub fn parse_value(&mut self) -> ParseResult<Value> {
        // <value>
        try!(self.expect_open("value"));

        let value = try!(self.parse_value_inner());

        // </value>
        try!(self.expect_close("value"));

        Ok(value)
    }

    fn parse_value_inner(&mut self) -> ParseResult<Value> {
        let value: Value;

        // Raw string or specific type tag
        value = match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                }

                if name == &OwnedName::local("struct") {
                    let mut members = BTreeMap::new();
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("struct") => break,
                            XmlEvent::StartElement { ref name, ref attributes, .. } if name == &OwnedName::local("member") => {
                                // <member>
                                if !attributes.is_empty() {
                                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                                }

                                // <name>NAME</name>
                                try!(self.expect_open("name"));
                                let name = match try!(self.pull_event()) {
                                    XmlEvent::Characters(string) => string,
                                    _ => return self.unexpected("expected CDATA"),
                                };
                                try!(self.expect_close("name"));

                                // Value
                                let value = try!(self.parse_value());

                                // </member>
                                try!(self.expect_close("member"));

                                members.insert(name, value);
                            }
                            _ => return self.unexpected("expected </struct> or <member>"),
                        }
                    }

                    Value::Struct(members)
                } else if name == &OwnedName::local("array") {
                    let mut elements: Vec<Value> = Vec::new();
                    try!(self.expect_open("data"));
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("data") => break,
                            XmlEvent::StartElement { ref name, .. } if name == &OwnedName::local("value") => {
                                elements.push(try!(self.parse_value_inner()));
                                try!(self.expect_close("value"));
                            }
                            _event => return self.unexpected("expected </data> or <value>")
                        }
                    }
                    try!(self.expect_close("array"));
                    Value::Array(elements)
                } else if name == &OwnedName::local("nil") {
                    try!(self.expect_close("nil"));
                    Value::Nil
                } else {
                    // All other types expect raw characters...
                    let data = match try!(self.pull_event()) {
                        XmlEvent::Characters(string) => string,
                        _ => return self.unexpected("expected characters"),
                    };

                    // ...and a corresponding close tag
                    try!(self.expect_close(&name.local_name));

                    if name == &OwnedName::local("i4") || name == &OwnedName::local("int") {
                        Value::Int(try!(data.parse::<i32>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("i8") {
                        Value::Int64(try!(data.parse::<i64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for 64-bit integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("boolean") {
                        let val = match data.trim() {
                            "0" => false,
                            "1" => true,
                            _ => return Err(io::Error::new(ErrorKind::Other, format!("invalid value for <boolean>: {}", data)).into())
                        };

                        Value::Bool(val)
                    } else if name == &OwnedName::local("string") {
                        Value::String(data.clone())
                    } else if name == &OwnedName::local("double") {
                        Value::Double(try!(data.parse::<f64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for double: {}", data))
                        })))
                    } else if name == &OwnedName::local("dateTime.iso8601") {
                        Value::DateTime(try!(datetime(&data).map_err(|e| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for dateTime.iso8601: {} ({})", data, e))
                        })))
                    } else if name == &OwnedName::local("base64") {
                        Value::Base64(try!(base64::decode(&data).map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for base64: {}", data))
                        })))
                    } else {
                        return self.unexpected("invalid <value> content");
                    }
                }
            }
            XmlEvent::Characters(string) => {
                Value::String(string)
            }
            _ => return self.unexpected("invalid <value> content"),
        };

        Ok(value)
    }
}

/// Parses a response from an XML reader.
pub fn parse_response<R: Read>(reader: &mut R) -> ParseResult<Response> {
    Parser::new(reader).parse_response()
}

#[cfg(test)]
mod tests {
    use super::*;

    use {Response, Value};
    use error::Fault;
    use std::fmt::Debug;

    fn read_response(xml: &str) -> ParseResult<Response> {
        parse_response(&mut xml.as_bytes())
    }

    fn read_value(xml: &str) -> ParseResult<Value> {
        Parser::new(&mut xml.as_bytes()).parse_value()
    }

    fn assert_ok<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => println!("assert_ok successful on Ok: {:?}", t),
            Err(e) => panic!("assert_ok called on Err value: {:?}", e),
        }
    }

    fn assert_err<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => panic!("assert_err called on Ok value: {:?}", t),
            Err(e) => println!("assert_err successful on Err: {:?}", e),
        }
    }

    #[test]
    fn parses_fault() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn ignores_additional_fault_fields() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            <member>
               <name>unnecessaryParameter</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn rejects_invalid_faults() {
        // Make sure to reject type errors in <fault>s - They're specified to contain specifically
        // typed fields.
        assert!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><string>I'm not an int!</string></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##).is_err());
    }

    #[test]
    fn parses_string_value_with_whitespace() {
        assert_eq!(read_value("<value><string>  I'm a string!  </string></value>"),
            Ok(Value::String("  I'm a string!  ".into())));
    }

    #[test]
    fn parses_64bit_int() {
        assert_eq!(read_value("<value><i8>12345</i8></value>"),
            Ok(Value::Int64(12345)));
        assert_eq!(read_value("<value><i8>-100100100100</i8></value>"),
            Ok(Value::Int64(-100100100100)));
    }

    #[test]
    fn parses_date_values() {
        assert_ok(read_value("<value><dateTime.iso8601>2015-02-18T23:16:09Z</dateTime.iso8601></value>"));
        assert_ok(read_value("<value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>"));
    }

    #[test]
    fn parses_array_values() {
        assert_eq!(read_value(r#"
                <value><array><data>
                    <value><i4>5</i4></value>
                    <value><string>a</string></value>
                </data></array></value>"#),
            Ok(Value::Array(vec![Value::Int(5), Value::String("a".into())])));
    }

    #[test]
    fn parses_raw_value_as_string() {
        assert_eq!(read_value("<value>\t  I'm a string!  </value>"),
            Ok(Value::String("\t  I'm a string!  ".into())));
    }

    #[test]
    fn parses_nil_values() {
        assert_eq!(read_value("<value><nil/></value>"), Ok(Value::Nil));
        assert_eq!(read_value("<value><nil></nil></value>"), Ok(Value::Nil));
    }

    #[test]
    fn unescapes_values() {
        assert_eq!(read_value("<value><string>abc<abc&abc</string></value>"),
            Ok(Value::String("abc<abc&abc".into())));
    }

    #[test]
    fn rejects_value_with_attributes() {
        // XXX we *should* reject everything with attributes (right?)
        assert_err(read_value(r#"<value name="ble">\t  I'm a string!  </value>"#));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use lexer::Tokens;
use error::ParsingError;
use constants::KEYWORDS;

// for keyword in KEYWORDS {
//     if keyword.to_string() == variable.to_lowercase() {
//         return Err(LexerError::KeywordError(variable));
//     }
// }

pub type Variables = HashMap<String, String>;
pub type Operators = HashMap<&'static str, Operator>;

// Refs: stackoverflow.com/questions/930486/what-is-associativity-of-operators-and-why-is-it-important
pub enum Associativity {
    LeftToRight,
    RightToLeft,
}

pub struct Operator(u8, Associativity);

/// Operator Precedence
/// | Precedence | Operator | Symbol | Associativity |
/// |:----------:|:--------:|:------:|---------------|
/// |1           |Brackets  |()      |Left-to-Right  |
/// |2           |NOT       |~       |Right-to-Left  |
/// |3           |Shift     |<< >>   |Left-to-Right  |
/// |4           |Equality  |==      |Left-to-Right  |
/// |5           |AND       |&       |Left-to-Right  |
/// |6           |XOR       |^       |Left-to-Right  |
/// |7           |OR        ||       |Left-to-Right  |
/// |8           |Assignment|=       |Right-to-Left  |
impl Operator {
    pub fn new(precedence: u8, associativity: Associativity) -> Operator {
        Operator(precedence, associativity)
    }
}

pub struct Parser {
    operators: Operators, // output: TokenList,
    variables: Variables,
}

impl Parser {
    pub fn new() -> Parser {
        Parser {
            operators: Operators::new(),
            variables: Variables::new(), // output: TokenList,
        }
    }

    pub fn init(&mut self) {
        self.operators.insert("(", Operator::new(1, Associativity::LeftToRight));
        self.operators.insert(")", Operator::new(1, Associativity::LeftToRight));
        self.operators.insert("~", Operator::new(2, Associativity::RightToLeft));
        self.operators.insert(">>", Operator::new(3, Associativity::LeftToRight));
        self.operators.insert("<<", Operator::new(3, Associativity::LeftToRight));
        self.operators.insert("==", Operator::new(4, Associativity::LeftToRight));
        self.operators.insert("&", Operator::new(5, Associativity::LeftToRight));
        self.operators.insert("^", Operator::new(6, Associativity::LeftToRight));
        self.operators.insert("|", Operator::new(7, Associativity::LeftToRight));
        self.operators.insert("=", Operator::new(8, Associativity::RightToLeft));
    }

    pub fn parse(&mut self, tokens: Tokens) -> Result<Tokens, ParsingError> {
        let mut operator_stack = Tokens::with_capacity(10);
        Ok((tokens))
    }
}
<commit_msg>More refactoring and better identification of the start position of characters in the Lexer<commit_after>use std::collections::HashMap;
use lexer::Tokens;
use error::ParsingError;
// use constants::KEYWORDS;

// for keyword in KEYWORDS {
//     if keyword.to_string() == variable.to_lowercase() {
//         return Err(LexerError::KeywordError(variable));
//     }
// }

pub type Variables = HashMap<String, String>;
pub type Operators = HashMap<&'static str, Operator>;

// Refs: stackoverflow.com/questions/930486/what-is-associativity-of-operators-and-why-is-it-important
pub enum Associativity {
    LeftToRight,
    RightToLeft,
}

pub struct Operator(u8, Associativity);

/// Operator Precedence
/// | Precedence | Operator | Symbol | Associativity |
/// |:----------:|:--------:|:------:|---------------|
/// |1           |Brackets  |()      |Left-to-Right  |
/// |2           |NOT       |~       |Right-to-Left  |
/// |3           |Shift     |<< >>   |Left-to-Right  |
/// |4           |Equality  |==      |Left-to-Right  |
/// |5           |AND       |&       |Left-to-Right  |
/// |6           |XOR       |^       |Left-to-Right  |
/// |7           |OR        ||       |Left-to-Right  |
/// |8           |Assignment|=       |Right-to-Left  |
impl Operator {
    pub fn new(precedence: u8, associativity: Associativity) -> Operator {
        Operator(precedence, associativity)
    }
}

pub struct Parser {
    operators: Operators, /* output: TokenList,
                           * variables: Variables, */
}

impl Parser {
    pub fn new() -> Parser {
        Parser {
            operators: Operators::new(), // variables: Variables::new(), // output: TokenList,
        }
    }

    pub fn init(&mut self) {
        self.operators.insert("(", Operator::new(1, Associativity::LeftToRight));
        self.operators.insert(")", Operator::new(1, Associativity::LeftToRight));
        self.operators.insert("~", Operator::new(2, Associativity::RightToLeft));
        self.operators.insert(">>", Operator::new(3, Associativity::LeftToRight));
        self.operators.insert("<<", Operator::new(3, Associativity::LeftToRight));
        self.operators.insert("==", Operator::new(4, Associativity::LeftToRight));
        self.operators.insert("&", Operator::new(5, Associativity::LeftToRight));
        self.operators.insert("^", Operator::new(6, Associativity::LeftToRight));
        self.operators.insert("|", Operator::new(7, Associativity::LeftToRight));
        self.operators.insert("=", Operator::new(8, Associativity::RightToLeft));
    }

    pub fn parse(&mut self, tokens: Tokens) -> Result<Tokens, ParsingError> {
        // let mut operator_stack = Tokens::with_capacity(10);
        Ok((tokens))
    }
}
<|endoftext|>


<commit_before>extern crate nom;
use nom::*;
use std::str;
use std::collections::HashMap;
use std::hash::Hash;

#[derive(PartialEq,Debug)]
enum JsonValue<'a> {
    Float(f64),
    Int(i64),
    Str(&'a str),
    Bool(bool),
    Object(HashMap<&'a str, JsonValue<'a>>),
    Vec(Vec<JsonValue<'a>>),
    Null,
}

named!(quoted_str<&str>,
       map_res!(delimited!(char!('"'),
                           escaped!(call!(alpha), '\\',
                                    is_a_bytes!(&b"\"n\\"[..])),
                           char!('"')),
                str::from_utf8));

named!(quoted_str_val<JsonValue>,
       map!(quoted_str,
            |x: &'a str| { JsonValue::Str(x) }));

named!(json_int<JsonValue>,
       map!(
           map_res!(
               map_res!(
                   digit,
                   str::from_utf8
               ),
               |x: &str| { x.parse::<i64>() }
           ),
           |x: i64| { JsonValue::Int(x) }
       ));

named!(json_float<JsonValue>,
       map!(
           map_res!(
               map_res!(
                   recognize!(separated_pair!(digit, char!('.'), digit)),
                   str::from_utf8
               ),
               |x: &str| { x.parse::<f64>() }
           ),
           |x: f64| { JsonValue::Float(x) }
       ));

named!(json_boolean<JsonValue>,
       alt!(value!(JsonValue::Bool(true), tag!("true")) |
            value!(JsonValue::Bool(false), tag!("false"))));

named!(json_null<JsonValue>,
       value!(JsonValue::Null, tag!("null")));

named!(keypair<(&str,JsonValue)>,
       separated_pair!(quoted_str, char!(':'), json_value));

named!(object< Vec<(&str,JsonValue)> >,
       delimited!(char!('{'), separated_list!(char!(','),keypair), char!('}')));

fn pairs_to_map<K: Hash + Eq, V>(v: Vec<(K, V)>) -> HashMap<K, V> {
    v.into_iter().fold(HashMap::new(), |mut m, (k, v)| {
        m.insert(k, v);
        m
    })
}

named!(object_map<JsonValue>,
       delimited!(char!('{'),
                  map!(separated_list!(char!(','),keypair),
                       |x| { JsonValue::Object(pairs_to_map(x)) }),
                  char!('}')));

named!(json_value<JsonValue>,
       alt!(json_null |
            json_float |
            json_int |
            quoted_str_val |
            json_boolean |
            object_map |
            json_array));

named!(json_array<JsonValue>,
       delimited!(char!('['),
                  map!(separated_list!(char!(','), json_value),
                       JsonValue::Vec),
                  char!(']')));

#[test]
fn check_quoted_str() {
    let empty = &b""[..];

    assert_eq!(quoted_str(&b"\"foo\""[..]),
               IResult::Done(empty,"foo"));

    assert_eq!(quoted_str_val(&b"\"foo\""[..]),
               IResult::Done(empty,JsonValue::Str("foo")));

    assert_eq!(quoted_str(&b"\"f\\\"o\\\"o\""[..]),
               IResult::Done(empty,"f\\\"o\\\"o"));

    assert_eq!(quoted_str_val(&b"\"f\\\"o\\\"o\""[..]),
               IResult::Done(empty,JsonValue::Str("f\\\"o\\\"o")));
}

#[test]
fn check_int() {
    assert_eq!(json_int(&b"123"[..]),
               IResult::Done(&b""[..],JsonValue::Int(123)));
}

#[test]
fn check_float() {
    assert_eq!(json_float(&b"123.123"[..]),
               IResult::Done(&b""[..],JsonValue::Float(123.123)));
}

#[test]
fn check_pairs_to_map() {
    let mut res = HashMap::with_capacity(3);
    res.insert("a", JsonValue::Int(1));
    res.insert("b", JsonValue::Int(2));
    res.insert("c", JsonValue::Int(3));
    assert_eq!(res,
               pairs_to_map(vec![("a",JsonValue::Int(1)),
                                 ("b",JsonValue::Int(2)),
                                 ("c",JsonValue::Int(3))]));
}

#[test]
fn check_object() {
    assert_eq!(object(&b"{\"foo\":\"bar\"}"[..]),
               IResult::Done(&b""[..],vec![("foo",JsonValue::Str("bar"))]));
    assert_eq!(object(&b"{\"foo\":123}"[..]),
               IResult::Done(&b""[..],vec![("foo",JsonValue::Int(123))]));
    assert_eq!(object(&b"{\"foo\":123.123}"[..]),
               IResult::Done(&b""[..],vec![("foo",JsonValue::Float(123.123))]));
    assert_eq!(object(&b"{\"foo\":true}"[..]),
               IResult::Done(&b""[..],vec![("foo",JsonValue::Bool(true))]));
    assert_eq!(object(&b"{\"foo\":true,\"bar\":\"with\\\"quotes\",\"baz\":123,\"withafloat\":123.123}"[..]),
               IResult::Done(&b""[..],
                             vec![("foo",JsonValue::Bool(true)),
                                  ("bar",JsonValue::Str("with\\\"quotes")),
                                  ("baz",JsonValue::Int(123)),
                                  ("withafloat",JsonValue::Float(123.123))]));

    let mut res = HashMap::new();
    res.insert("foo", JsonValue::Bool(true));
    res.insert("bar", JsonValue::Str("with\\\"quotes"));
    res.insert("baz", JsonValue::Int(123));
    res.insert("withafloat", JsonValue::Float(123.123));
    assert_eq!(object_map(&b"{\"foo\":true,\"bar\":\"with\\\"quotes\",\"baz\":123,\"withafloat\":123.123}"[..]),
               IResult::Done(&b""[..],JsonValue::Object(res)));

    let mut res = HashMap::new();
    let mut nested_res = HashMap::new();

    nested_res.insert("nestedfoo", JsonValue::Bool(true));
    nested_res.insert("bar", JsonValue::Str("with\\\"quotes"));
    nested_res.insert("baz", JsonValue::Int(123));
    nested_res.insert("withafloat", JsonValue::Float(123.123));
    res.insert("foo", JsonValue::Object(nested_res));
    assert_eq!(object_map(&b"{\"foo\":{\"nestedfoo\":true,\"bar\":\"with\\\"quotes\",\"baz\":123,\"withafloat\":123.123}}"[..]),
               IResult::Done(&b""[..],JsonValue::Object(res)));
}

#[test]
fn check_array() {

    assert_eq!(json_value(&b"[1,2,null,4]"[..]),
               IResult::Done(&b""[..],
                             JsonValue::Vec(vec![JsonValue::Int(1),
                                                 JsonValue::Int(2),
                                                 JsonValue::Null,
                                                 JsonValue::Int(4)])));
    let mut res = HashMap::new();
    res.insert("foo", JsonValue::Bool(true));
    res.insert("bar", JsonValue::Str("with\\\"quotes"));
    res.insert("baz", JsonValue::Int(123));
    res.insert("withafloat", JsonValue::Float(123.123));

    assert_eq!(json_value(&b"[{\"foo\":true,\"bar\":\"with\\\"quotes\",\"baz\":123,\"withafloat\":123.123}]"[..]),
               IResult::Done(&b""[..],
                             JsonValue::Vec(vec![JsonValue::Object(res)])))

}
<commit_msg>(maint) Tolerate spaces in JSON where applicable<commit_after>extern crate nom;
use nom::*;
use std::str;
use std::collections::HashMap;
use std::hash::Hash;

#[derive(PartialEq,Debug)]
pub enum JsonValue<'a> {
    Float(f64),
    Int(i64),
    Str(&'a str),
    Bool(bool),
    Object(HashMap<&'a str, JsonValue<'a>>),
    Vec(Vec<JsonValue<'a>>),
    Null,
}

named!(quoted_str<&str>,
       map_res!(delimited!(char!('"'),
                           escaped!(call!(alpha), '\\',
                                    is_a_bytes!(&b"\"n\\"[..])),
                           char!('"')),
                str::from_utf8));

named!(quoted_str_val<JsonValue>,
       map!(quoted_str,
            |x: &'a str| { JsonValue::Str(x) }));

named!(json_int<JsonValue>,
       map!(
           map_res!(
               map_res!(
                   digit,
                   str::from_utf8
               ),
               |x: &str| { x.parse::<i64>() }
           ),
           |x: i64| { JsonValue::Int(x) }
       ));

named!(json_float<JsonValue>,
       map!(
           map_res!(
               map_res!(
                   recognize!(separated_pair!(digit, char!('.'), digit)),
                   str::from_utf8
               ),
               |x: &str| { x.parse::<f64>() }
           ),
           |x: f64| { JsonValue::Float(x) }
       ));

named!(json_boolean<JsonValue>,
       alt!(value!(JsonValue::Bool(true), tag!("true")) |
            value!(JsonValue::Bool(false), tag!("false"))));

named!(json_null<JsonValue>,
       value!(JsonValue::Null, tag!("null")));

named!(keypair<(&str,JsonValue)>,
       separated_pair!(quoted_str,
                       chain!(
                           multispace? ~
                           char!(':') ~
                           multispace? ,

                           ||{}
                       ),
                       json_value));

fn pairs_to_map<K: Hash + Eq, V>(v: Vec<(K, V)>) -> HashMap<K, V> {
    v.into_iter().fold(HashMap::new(), |mut m, (k, v)| {
        m.insert(k, v);
        m
    })
}

named!(object_map<JsonValue>,
       delimited!(char!('{'),
                  map!(
                      separated_list!(
                          chain!(multispace? ~
                                 char!(',') ~
                                 multispace? ,

                                 ||{}
                          ),
                          keypair
                      ),
                      |x| { JsonValue::Object(pairs_to_map(x)) }),
                  char!('}')));

named!(json_array<JsonValue>,
       delimited!(char!('['),
                  map!(
                      separated_list!(
                          chain!(multispace? ~
                                 char!(',') ~
                                 multispace? ,

                                 ||{}
                          ),
                          json_value
                      ),
                      JsonValue::Vec),
                  char!(']')));

named!(json_value<JsonValue>,
       alt!(json_null |
            json_float |
            json_int |
            quoted_str_val |
            json_boolean |
            object_map |
            json_array));

#[test]
fn check_quoted_str() {
    let empty = &b""[..];

    assert_eq!(quoted_str(&b"\"foo\""[..]),
               IResult::Done(empty,"foo"));

    assert_eq!(quoted_str_val(&b"\"foo\""[..]),
               IResult::Done(empty,JsonValue::Str("foo")));

    assert_eq!(quoted_str(&b"\"f\\\"o\\\"o\""[..]),
               IResult::Done(empty,"f\\\"o\\\"o"));

    assert_eq!(quoted_str_val(&b"\"f\\\"o\\\"o\""[..]),
               IResult::Done(empty,JsonValue::Str("f\\\"o\\\"o")));
}

#[test]
fn check_int() {
    assert_eq!(json_int(&b"123"[..]),
               IResult::Done(&b""[..],JsonValue::Int(123)));
}

#[test]
fn check_float() {
    assert_eq!(json_float(&b"123.123"[..]),
               IResult::Done(&b""[..],JsonValue::Float(123.123)));
}

#[test]
fn check_pairs_to_map() {
    let mut res = HashMap::with_capacity(3);
    res.insert("a", JsonValue::Int(1));
    res.insert("b", JsonValue::Int(2));
    res.insert("c", JsonValue::Int(3));
    assert_eq!(res,
               pairs_to_map(vec![("a",JsonValue::Int(1)),
                                 ("b",JsonValue::Int(2)),
                                 ("c",JsonValue::Int(3))]));
}

#[test]
fn check_object_map() {
    let mut res = HashMap::new();
    res.insert("foo", JsonValue::Bool(true));
    res.insert("bar", JsonValue::Str("with\\\"quotes"));
    res.insert("baz", JsonValue::Int(123));
    res.insert("withafloat", JsonValue::Float(123.123));
    assert_eq!(object_map(&b"{\"foo\" : true,\"bar\":\n\"with\\\"quotes\",\"baz\":123,\n\"withafloat\":123.123}"[..]),
               IResult::Done(&b""[..],JsonValue::Object(res)));

    let mut res = HashMap::new();
    let mut nested_res = HashMap::new();

    nested_res.insert("nestedfoo", JsonValue::Bool(true));
    nested_res.insert("bar", JsonValue::Str("with\\\"quotes"));
    nested_res.insert("baz", JsonValue::Int(123));
    nested_res.insert("withafloat", JsonValue::Float(123.123));
    res.insert("foo", JsonValue::Object(nested_res));
    assert_eq!(object_map(&b"{\"foo\":{\"nestedfoo\":true,\"bar\":\"with\\\"quotes\",\"baz\":123,\"withafloat\":123.123}}"[..]),
               IResult::Done(&b""[..],JsonValue::Object(res)));
}

#[test]
fn check_array() {

    assert_eq!(json_value(&b"[1,2,null,4]"[..]),
               IResult::Done(&b""[..],
                             JsonValue::Vec(vec![JsonValue::Int(1),
                                                 JsonValue::Int(2),
                                                 JsonValue::Null,
                                                 JsonValue::Int(4)])));
    let mut res = HashMap::new();
    res.insert("foo", JsonValue::Bool(true));
    res.insert("bar", JsonValue::Str("with\\\"quotes"));
    res.insert("baz", JsonValue::Int(123));
    res.insert("withafloat", JsonValue::Float(123.123));

    assert_eq!(json_value(&b"[{\"foo\":true,\n\"bar\":\"with\\\"quotes\"  ,\"baz\":123,\"withafloat\":123.123}]"[..]),
               IResult::Done(&b""[..],
                             JsonValue::Vec(vec![JsonValue::Object(res)])))

}
<|endoftext|>