<commit_before>use crate::de::{Event, Input};
use crate::error::{self, Result};
use std::collections::BTreeMap;
use std::str;
use yaml_rust::parser::{Event as YamlEvent, MarkedEventReceiver, Parser};
use yaml_rust::scanner::Marker;

pub(crate) struct Loader {
    events: Vec<(Event, Marker)>,
    /// Map from alias id to index in events.
    aliases: BTreeMap<usize, usize>,
    current_document_start: usize,
    /// Map from start index to number of events.
    document_lengths: BTreeMap<usize, usize>,
}

impl Loader {
    pub fn new(input: Input) -> Result<Self> {
        enum Input2<'a> {
            Str(&'a str),
            Slice(&'a [u8]),
        }

        let mut buffer;
        let input = match input {
            Input::Str(s) => Input2::Str(s),
            Input::Slice(bytes) => Input2::Slice(bytes),
            Input::Read(mut rdr) => {
                buffer = Vec::new();
                rdr.read_to_end(&mut buffer).map_err(error::io)?;
                Input2::Slice(&buffer)
            }
            Input::Iterable(_) | Input::Document(_) => unreachable!(),
            Input::Fail(err) => return Err(error::shared(err)),
        };

        let input = match input {
            Input2::Str(s) => s,
            Input2::Slice(bytes) => str::from_utf8(bytes).map_err(error::str_utf8)?,
        };

        let mut parser = Parser::new(input.chars());
        let mut loader = Loader {
            events: Vec::new(),
            aliases: BTreeMap::new(),
            current_document_start: 0,
            document_lengths: BTreeMap::new(),
        };
        parser.load(&mut loader, true).map_err(error::scanner)?;
        Ok(loader)
    }

    pub fn event(&self, pos: usize) -> Option<&(Event, Marker)> {
        self.events.get(pos)
    }

    pub fn alias(&self, id: usize) -> Option<usize> {
        self.aliases.get(&id).copied()
    }

    pub fn document_len(&self, start: usize) -> usize {
        *self.document_lengths.get(&start).unwrap_or(&0)
    }
}

impl MarkedEventReceiver for Loader {
    fn on_event(&mut self, event: YamlEvent, marker: Marker) {
        let event = match event {
            YamlEvent::Nothing | YamlEvent::StreamStart | YamlEvent::StreamEnd => return,
            YamlEvent::DocumentStart => {
                self.current_document_start = self.events.len();
                return;
            }
            YamlEvent::DocumentEnd => {
                let len = self.events.len() - self.current_document_start;
                self.document_lengths
                    .insert(self.current_document_start, len);
                self.current_document_start = self.events.len();
                return;
            }
            YamlEvent::Alias(id) => Event::Alias(id),
            YamlEvent::Scalar(value, style, id, tag) => {
                self.aliases.insert(id, self.events.len());
                Event::Scalar(value, style, tag)
            }
            YamlEvent::SequenceStart(id) => {
                self.aliases.insert(id, self.events.len());
                Event::SequenceStart
            }
            YamlEvent::SequenceEnd => Event::SequenceEnd,
            YamlEvent::MappingStart(id) => {
                self.aliases.insert(id, self.events.len());
                Event::MappingStart
            }
            YamlEvent::MappingEnd => Event::MappingEnd,
        };
        self.events.push((event, marker));
    }
}
<commit_msg>Switch to parser's `next` instead of `load`<commit_after>use crate::de::{Event, Input};
use crate::error::{self, Result};
use std::collections::BTreeMap;
use std::str;
use yaml_rust::parser::{Event as YamlEvent, Parser};
use yaml_rust::scanner::Marker;

pub(crate) struct Loader {
    events: Vec<(Event, Marker)>,
    /// Map from alias id to index in events.
    aliases: BTreeMap<usize, usize>,
    /// Map from start index to number of events.
    document_lengths: BTreeMap<usize, usize>,
}

impl Loader {
    pub fn new(input: Input) -> Result<Self> {
        enum Input2<'a> {
            Str(&'a str),
            Slice(&'a [u8]),
        }

        let mut buffer;
        let input = match input {
            Input::Str(s) => Input2::Str(s),
            Input::Slice(bytes) => Input2::Slice(bytes),
            Input::Read(mut rdr) => {
                buffer = Vec::new();
                rdr.read_to_end(&mut buffer).map_err(error::io)?;
                Input2::Slice(&buffer)
            }
            Input::Iterable(_) | Input::Document(_) => unreachable!(),
            Input::Fail(err) => return Err(error::shared(err)),
        };

        let input = match input {
            Input2::Str(s) => s,
            Input2::Slice(bytes) => str::from_utf8(bytes).map_err(error::str_utf8)?,
        };

        let mut parser = Parser::new(input.chars());
        let mut current_document_start = 0;
        let mut loader = Loader {
            events: Vec::new(),
            aliases: BTreeMap::new(),
            document_lengths: BTreeMap::new(),
        };

        loop {
            let (event, marker) = parser.next().map_err(error::scanner)?;
            let event = match event {
                YamlEvent::Nothing => unreachable!(),
                YamlEvent::StreamStart => continue,
                YamlEvent::StreamEnd => break,
                YamlEvent::DocumentStart => {
                    current_document_start = loader.events.len();
                    continue;
                }
                YamlEvent::DocumentEnd => {
                    let len = loader.events.len() - current_document_start;
                    loader.document_lengths.insert(current_document_start, len);
                    current_document_start = loader.events.len();
                    continue;
                }
                YamlEvent::Alias(id) => Event::Alias(id),
                YamlEvent::Scalar(value, style, id, tag) => {
                    loader.aliases.insert(id, loader.events.len());
                    Event::Scalar(value, style, tag)
                }
                YamlEvent::SequenceStart(id) => {
                    loader.aliases.insert(id, loader.events.len());
                    Event::SequenceStart
                }
                YamlEvent::SequenceEnd => Event::SequenceEnd,
                YamlEvent::MappingStart(id) => {
                    loader.aliases.insert(id, loader.events.len());
                    Event::MappingStart
                }
                YamlEvent::MappingEnd => Event::MappingEnd,
            };
            loader.events.push((event, marker));
        }

        Ok(loader)
    }

    pub fn event(&self, pos: usize) -> Option<&(Event, Marker)> {
        self.events.get(pos)
    }

    pub fn alias(&self, id: usize) -> Option<usize> {
        self.aliases.get(&id).copied()
    }

    pub fn document_len(&self, start: usize) -> usize {
        *self.document_lengths.get(&start).unwrap_or(&0)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::Write;

use rustc::hir::def_id::DefId;
use rustc_serialize::json::as_json;

use external_data::*;
use data::VariableKind;
use dump::Dump;
use super::Format;

pub struct JsonDumper<'b, W: Write + 'b> {
    output: &'b mut W,
    result: Analysis,
}

impl<'b, W: Write> JsonDumper<'b, W> {
    pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
        JsonDumper { output: writer, result: Analysis::new() }
    }
}

impl<'b, W: Write> Drop for JsonDumper<'b, W> {
    fn drop(&mut self) {
        if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
            error!("Error writing output");
        }
    }
}

macro_rules! impl_fn {
    ($fn_name: ident, $data_type: ident, $bucket: ident) => {
        fn $fn_name(&mut self, data: $data_type) {
            self.result.$bucket.push(From::from(data));
        }
    }
}

impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
    fn crate_prelude(&mut self, data: CratePreludeData) {
        self.result.prelude = Some(data)
    }

    impl_fn!(extern_crate, ExternCrateData, imports);
    impl_fn!(use_data, UseData, imports);
    impl_fn!(use_glob, UseGlobData, imports);

    impl_fn!(enum_data, EnumData, defs);
    impl_fn!(tuple_variant, TupleVariantData, defs);
    impl_fn!(struct_variant, StructVariantData, defs);
    impl_fn!(struct_data, StructData, defs);
    impl_fn!(trait_data, TraitData, defs);
    impl_fn!(function, FunctionData, defs);
    impl_fn!(method, MethodData, defs);
    impl_fn!(macro_data, MacroData, defs);
    impl_fn!(mod_data, ModData, defs);
    impl_fn!(typedef, TypeDefData, defs);
    impl_fn!(variable, VariableData, defs);

    impl_fn!(function_ref, FunctionRefData, refs);
    impl_fn!(function_call, FunctionCallData, refs);
    impl_fn!(method_call, MethodCallData, refs);
    impl_fn!(mod_ref, ModRefData, refs);
    impl_fn!(type_ref, TypeRefData, refs);
    impl_fn!(variable_ref, VariableRefData, refs);

    impl_fn!(macro_use, MacroUseData, macro_refs);

    // FIXME store this instead of throwing it away.
    fn impl_data(&mut self, _data: ImplData) {}
    fn inheritance(&mut self, _data: InheritanceData) {}
}

// FIXME do we want to change ExternalData to this mode? It will break DXR.
// FIXME methods. The defs have information about possible overriding and the
// refs have decl information (e.g., a trait method where we know the required
// method, but not the supplied method). In both cases, we are currently
// ignoring it.

#[derive(Debug, RustcEncodable)]
struct Analysis {
    kind: Format,
    prelude: Option<CratePreludeData>,
    imports: Vec<Import>,
    defs: Vec<Def>,
    refs: Vec<Ref>,
    macro_refs: Vec<MacroRef>,
}

impl Analysis {
    fn new() -> Analysis {
        Analysis {
            kind: Format::Json,
            prelude: None,
            imports: vec![],
            defs: vec![],
            refs: vec![],
            macro_refs: vec![],
        }
    }
}

// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
// we use our own Id which is the same, but without the newtype.
#[derive(Debug, RustcEncodable)]
struct Id {
    krate: u32,
    index: u32,
}

impl From<DefId> for Id {
    fn from(id: DefId) -> Id {
        Id {
            krate: id.krate.as_u32(),
            index: id.index.as_u32(),
        }
    }
}

#[derive(Debug, RustcEncodable)]
struct Import {
    kind: ImportKind,
    ref_id: Option<Id>,
    span: SpanData,
    name: String,
    value: String,
}

#[derive(Debug, RustcEncodable)]
enum ImportKind {
    ExternCrate,
    Use,
    GlobUse,
}

impl From<ExternCrateData> for Import {
    fn from(data: ExternCrateData) -> Import {
        Import {
            kind: ImportKind::ExternCrate,
            ref_id: None,
            span: data.span,
            name: data.name,
            value: String::new(),
        }
    }
}
impl From<UseData> for Import {
    fn from(data: UseData) -> Import {
        Import {
            kind: ImportKind::Use,
            ref_id: data.mod_id.map(|id| From::from(id)),
            span: data.span,
            name: data.name,
            value: String::new(),
        }
    }
}
impl From<UseGlobData> for Import {
    fn from(data: UseGlobData) -> Import {
        Import {
            kind: ImportKind::GlobUse,
            ref_id: None,
            span: data.span,
            name: "*".to_owned(),
            value: data.names.join(", "),
        }
    }
}

#[derive(Debug, RustcEncodable)]
struct Def {
    kind: DefKind,
    id: Id,
    span: SpanData,
    name: String,
    qualname: String,
    value: String,
    children: Vec<Id>,
    decl_id: Option<Id>,
    docs: String,
}

#[derive(Debug, RustcEncodable)]
enum DefKind {
    // value = variant names
    Enum,
    // value = enum name + variant name + types
    Tuple,
    // value = [enum name +] name + fields
    Struct,
    // value = signature
    Trait,
    // value = type + generics
    Function,
    // value = type + generics
    Method,
    // No id, no value.
    Macro,
    // value = file_name
    Mod,
    // value = aliased type
    Type,
    // value = type and init expression (for all variable kinds).
    Local,
    Static,
    Const,
    Field,
}

impl From<EnumData> for Def {
    fn from(data: EnumData) -> Def {
        Def {
            kind: DefKind::Enum,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: data.variants.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}

impl From<TupleVariantData> for Def {
    fn from(data: TupleVariantData) -> Def {
        Def {
            kind: DefKind::Tuple,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<StructVariantData> for Def {
    fn from(data: StructVariantData) -> Def {
        Def {
            kind: DefKind::Struct,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<StructData> for Def {
    fn from(data: StructData) -> Def {
        Def {
            kind: DefKind::Struct,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: data.fields.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<TraitData> for Def {
    fn from(data: TraitData) -> Def {
        Def {
            kind: DefKind::Trait,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: data.items.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<FunctionData> for Def {
    fn from(data: FunctionData) -> Def {
        Def {
            kind: DefKind::Function,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<MethodData> for Def {
    fn from(data: MethodData) -> Def {
        Def {
            kind: DefKind::Method,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: data.decl_id.map(|id| From::from(id)),
            docs: data.docs,
        }
    }
}
impl From<MacroData> for Def {
    fn from(data: MacroData) -> Def {
        Def {
            kind: DefKind::Macro,
            id: From::from(null_def_id()),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: String::new(),
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<ModData> for Def {
    fn from(data:ModData) -> Def {
        Def {
            kind: DefKind::Mod,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.filename,
            children: data.items.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<TypeDefData> for Def {
    fn from(data: TypeDefData) -> Def {
        Def {
            kind: DefKind::Type,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: String::new(),
        }
    }
}
impl From<VariableData> for Def {
    fn from(data: VariableData) -> Def {
        Def {
            kind: match data.kind {
                VariableKind::Static => DefKind::Static,
                VariableKind::Const => DefKind::Const,
                VariableKind::Local => DefKind::Local,
                VariableKind::Field => DefKind::Field,
            },
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.type_value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}

#[derive(Debug, RustcEncodable)]
enum RefKind {
    Function,
    Mod,
    Type,
    Variable,
}

#[derive(Debug, RustcEncodable)]
struct Ref {
    kind: RefKind,
    span: SpanData,
    ref_id: Id,
}

impl From<FunctionRefData> for Ref {
    fn from(data: FunctionRefData) -> Ref {
        Ref {
            kind: RefKind::Function,
            span: data.span,
            ref_id: From::from(data.ref_id),
        }
    }
}
impl From<FunctionCallData> for Ref {
    fn from(data: FunctionCallData) -> Ref {
        Ref {
            kind: RefKind::Function,
            span: data.span,
            ref_id: From::from(data.ref_id),
        }
    }
}
impl From<MethodCallData> for Ref {
    fn from(data: MethodCallData) -> Ref {
        Ref {
            kind: RefKind::Function,
            span: data.span,
            ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())),
        }
    }
}
impl From<ModRefData> for Ref {
    fn from(data: ModRefData) -> Ref {
        Ref {
            kind: RefKind::Mod,
            span: data.span,
            ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
        }
    }
}
impl From<TypeRefData> for Ref {
    fn from(data: TypeRefData) -> Ref {
        Ref {
            kind: RefKind::Type,
            span: data.span,
            ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
        }
    }
}
impl From<VariableRefData> for Ref {
    fn from(data: VariableRefData) -> Ref {
        Ref {
            kind: RefKind::Variable,
            span: data.span,
            ref_id: From::from(data.ref_id),
        }
    }
}

#[derive(Debug, RustcEncodable)]
struct MacroRef {
    span: SpanData,
    qualname: String,
    callee_span: SpanData,
}

impl From<MacroUseData> for MacroRef {
    fn from(data: MacroUseData) -> MacroRef {
        MacroRef {
            span: data.span,
            qualname: data.qualname,
            callee_span: data.callee_span,
        }
    }
}
<commit_msg>save-analysis: redirect a module decl to the start of the defining file<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::Write;

use rustc::hir::def_id::DefId;
use rustc_serialize::json::as_json;

use external_data::*;
use data::VariableKind;
use dump::Dump;
use super::Format;

pub struct JsonDumper<'b, W: Write + 'b> {
    output: &'b mut W,
    result: Analysis,
}

impl<'b, W: Write> JsonDumper<'b, W> {
    pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
        JsonDumper { output: writer, result: Analysis::new() }
    }
}

impl<'b, W: Write> Drop for JsonDumper<'b, W> {
    fn drop(&mut self) {
        if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
            error!("Error writing output");
        }
    }
}

macro_rules! impl_fn {
    ($fn_name: ident, $data_type: ident, $bucket: ident) => {
        fn $fn_name(&mut self, data: $data_type) {
            self.result.$bucket.push(From::from(data));
        }
    }
}

impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
    fn crate_prelude(&mut self, data: CratePreludeData) {
        self.result.prelude = Some(data)
    }

    impl_fn!(extern_crate, ExternCrateData, imports);
    impl_fn!(use_data, UseData, imports);
    impl_fn!(use_glob, UseGlobData, imports);

    impl_fn!(enum_data, EnumData, defs);
    impl_fn!(tuple_variant, TupleVariantData, defs);
    impl_fn!(struct_variant, StructVariantData, defs);
    impl_fn!(struct_data, StructData, defs);
    impl_fn!(trait_data, TraitData, defs);
    impl_fn!(function, FunctionData, defs);
    impl_fn!(method, MethodData, defs);
    impl_fn!(macro_data, MacroData, defs);
    impl_fn!(typedef, TypeDefData, defs);
    impl_fn!(variable, VariableData, defs);

    impl_fn!(function_ref, FunctionRefData, refs);
    impl_fn!(function_call, FunctionCallData, refs);
    impl_fn!(method_call, MethodCallData, refs);
    impl_fn!(mod_ref, ModRefData, refs);
    impl_fn!(type_ref, TypeRefData, refs);
    impl_fn!(variable_ref, VariableRefData, refs);

    impl_fn!(macro_use, MacroUseData, macro_refs);

    fn mod_data(&mut self, data: ModData) {
        let id: Id = From::from(data.id);
        let mut def = Def {
            kind: DefKind::Mod,
            id: id,
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.filename,
            children: data.items.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        };
        if def.span.file_name != def.value {
            // If the module is an out-of-line defintion, then we'll make the
            // defintion the first character in the module's file and turn the
            // the declaration into a reference to it.
            let rf = Ref {
                kind: RefKind::Mod,
                span: def.span,
                ref_id: id,
            };
            self.result.refs.push(rf);
            def.span = SpanData {
                file_name: def.value.clone(),
                byte_start: 0,
                byte_end: 0,
                line_start: 1,
                line_end: 1,
                column_start: 1,
                column_end: 1,
            }
        }

        self.result.defs.push(def);
    }

    // FIXME store this instead of throwing it away.
    fn impl_data(&mut self, _data: ImplData) {}
    fn inheritance(&mut self, _data: InheritanceData) {}
}

// FIXME do we want to change ExternalData to this mode? It will break DXR.
// FIXME methods. The defs have information about possible overriding and the
// refs have decl information (e.g., a trait method where we know the required
// method, but not the supplied method). In both cases, we are currently
// ignoring it.

#[derive(Debug, RustcEncodable)]
struct Analysis {
    kind: Format,
    prelude: Option<CratePreludeData>,
    imports: Vec<Import>,
    defs: Vec<Def>,
    refs: Vec<Ref>,
    macro_refs: Vec<MacroRef>,
}

impl Analysis {
    fn new() -> Analysis {
        Analysis {
            kind: Format::Json,
            prelude: None,
            imports: vec![],
            defs: vec![],
            refs: vec![],
            macro_refs: vec![],
        }
    }
}

// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
// we use our own Id which is the same, but without the newtype.
#[derive(Clone, Copy, Debug, RustcEncodable)]
struct Id {
    krate: u32,
    index: u32,
}

impl From<DefId> for Id {
    fn from(id: DefId) -> Id {
        Id {
            krate: id.krate.as_u32(),
            index: id.index.as_u32(),
        }
    }
}

#[derive(Debug, RustcEncodable)]
struct Import {
    kind: ImportKind,
    ref_id: Option<Id>,
    span: SpanData,
    name: String,
    value: String,
}

#[derive(Debug, RustcEncodable)]
enum ImportKind {
    ExternCrate,
    Use,
    GlobUse,
}

impl From<ExternCrateData> for Import {
    fn from(data: ExternCrateData) -> Import {
        Import {
            kind: ImportKind::ExternCrate,
            ref_id: None,
            span: data.span,
            name: data.name,
            value: String::new(),
        }
    }
}
impl From<UseData> for Import {
    fn from(data: UseData) -> Import {
        Import {
            kind: ImportKind::Use,
            ref_id: data.mod_id.map(|id| From::from(id)),
            span: data.span,
            name: data.name,
            value: String::new(),
        }
    }
}
impl From<UseGlobData> for Import {
    fn from(data: UseGlobData) -> Import {
        Import {
            kind: ImportKind::GlobUse,
            ref_id: None,
            span: data.span,
            name: "*".to_owned(),
            value: data.names.join(", "),
        }
    }
}

#[derive(Debug, RustcEncodable)]
struct Def {
    kind: DefKind,
    id: Id,
    span: SpanData,
    name: String,
    qualname: String,
    value: String,
    children: Vec<Id>,
    decl_id: Option<Id>,
    docs: String,
}

#[derive(Debug, RustcEncodable)]
enum DefKind {
    // value = variant names
    Enum,
    // value = enum name + variant name + types
    Tuple,
    // value = [enum name +] name + fields
    Struct,
    // value = signature
    Trait,
    // value = type + generics
    Function,
    // value = type + generics
    Method,
    // No id, no value.
    Macro,
    // value = file_name
    Mod,
    // value = aliased type
    Type,
    // value = type and init expression (for all variable kinds).
    Local,
    Static,
    Const,
    Field,
}

impl From<EnumData> for Def {
    fn from(data: EnumData) -> Def {
        Def {
            kind: DefKind::Enum,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: data.variants.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}

impl From<TupleVariantData> for Def {
    fn from(data: TupleVariantData) -> Def {
        Def {
            kind: DefKind::Tuple,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<StructVariantData> for Def {
    fn from(data: StructVariantData) -> Def {
        Def {
            kind: DefKind::Struct,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<StructData> for Def {
    fn from(data: StructData) -> Def {
        Def {
            kind: DefKind::Struct,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: data.fields.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<TraitData> for Def {
    fn from(data: TraitData) -> Def {
        Def {
            kind: DefKind::Trait,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: data.items.into_iter().map(|id| From::from(id)).collect(),
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<FunctionData> for Def {
    fn from(data: FunctionData) -> Def {
        Def {
            kind: DefKind::Function,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}
impl From<MethodData> for Def {
    fn from(data: MethodData) -> Def {
        Def {
            kind: DefKind::Method,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: data.decl_id.map(|id| From::from(id)),
            docs: data.docs,
        }
    }
}
impl From<MacroData> for Def {
    fn from(data: MacroData) -> Def {
        Def {
            kind: DefKind::Macro,
            id: From::from(null_def_id()),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: String::new(),
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}

impl From<TypeDefData> for Def {
    fn from(data: TypeDefData) -> Def {
        Def {
            kind: DefKind::Type,
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.value,
            children: vec![],
            decl_id: None,
            docs: String::new(),
        }
    }
}
impl From<VariableData> for Def {
    fn from(data: VariableData) -> Def {
        Def {
            kind: match data.kind {
                VariableKind::Static => DefKind::Static,
                VariableKind::Const => DefKind::Const,
                VariableKind::Local => DefKind::Local,
                VariableKind::Field => DefKind::Field,
            },
            id: From::from(data.id),
            span: data.span,
            name: data.name,
            qualname: data.qualname,
            value: data.type_value,
            children: vec![],
            decl_id: None,
            docs: data.docs,
        }
    }
}

#[derive(Debug, RustcEncodable)]
enum RefKind {
    Function,
    Mod,
    Type,
    Variable,
}

#[derive(Debug, RustcEncodable)]
struct Ref {
    kind: RefKind,
    span: SpanData,
    ref_id: Id,
}

impl From<FunctionRefData> for Ref {
    fn from(data: FunctionRefData) -> Ref {
        Ref {
            kind: RefKind::Function,
            span: data.span,
            ref_id: From::from(data.ref_id),
        }
    }
}
impl From<FunctionCallData> for Ref {
    fn from(data: FunctionCallData) -> Ref {
        Ref {
            kind: RefKind::Function,
            span: data.span,
            ref_id: From::from(data.ref_id),
        }
    }
}
impl From<MethodCallData> for Ref {
    fn from(data: MethodCallData) -> Ref {
        Ref {
            kind: RefKind::Function,
            span: data.span,
            ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())),
        }
    }
}
impl From<ModRefData> for Ref {
    fn from(data: ModRefData) -> Ref {
        Ref {
            kind: RefKind::Mod,
            span: data.span,
            ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
        }
    }
}
impl From<TypeRefData> for Ref {
    fn from(data: TypeRefData) -> Ref {
        Ref {
            kind: RefKind::Type,
            span: data.span,
            ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
        }
    }
}
impl From<VariableRefData> for Ref {
    fn from(data: VariableRefData) -> Ref {
        Ref {
            kind: RefKind::Variable,
            span: data.span,
            ref_id: From::from(data.ref_id),
        }
    }
}

#[derive(Debug, RustcEncodable)]
struct MacroRef {
    span: SpanData,
    qualname: String,
    callee_span: SpanData,
}

impl From<MacroUseData> for MacroRef {
    fn from(data: MacroUseData) -> MacroRef {
        MacroRef {
            span: data.span,
            qualname: data.qualname,
            callee_span: data.callee_span,
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::attr::AttrValue;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{Element, HTMLImageElementTypeId};
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
use dom::virtualmethods::VirtualMethods;
use servo_net::image_cache_task;
use servo_util::geometry::to_px;
use servo_util::str::DOMString;
use string_cache::Atom;

use url::{Url, UrlParser};

use std::cell::RefCell;

#[jstraceable]
#[must_root]
pub struct HTMLImageElement {
    pub htmlelement: HTMLElement,
    image: RefCell<Option<Url>>,
}

impl HTMLImageElementDerived for EventTarget {
    fn is_htmlimageelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLImageElementTypeId))
    }
}

trait PrivateHTMLImageElementHelpers {
    fn update_image(self, value: Option<(DOMString, &Url)>);
}

impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
    /// Makes the local `image` member match the status of the `src` attribute and starts
    /// prefetching the image. This method must be called after `src` is changed.
    fn update_image(self, value: Option<(DOMString, &Url)>) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let document = node.owner_doc().root();
        let window = document.deref().window.root();
        let image_cache = &window.image_cache_task;
        match value {
            None => {
                *self.image.borrow_mut() = None;
            }
            Some((src, base_url)) => {
                let img_url = UrlParser::new().base_url(base_url).parse(src.as_slice());
                // FIXME: handle URL parse errors more gracefully.
                let img_url = img_url.unwrap();
                *self.image.borrow_mut() = Some(img_url.clone());

                // inform the image cache to load this, but don't store a
                // handle.
                //
                // TODO (Issue #84): don't prefetch if we are within a
                // <noscript> tag.
                image_cache.send(image_cache_task::Prefetch(img_url));
            }
        }
    }
}

impl HTMLImageElement {
    fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLImageElement {
        HTMLImageElement {
            htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, prefix, document),
            image: RefCell::new(None),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> Temporary<HTMLImageElement> {
        let element = HTMLImageElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
    }
}

pub trait LayoutHTMLImageElementHelpers {
    unsafe fn image(&self) -> Option<Url>;
}

impl LayoutHTMLImageElementHelpers for JS<HTMLImageElement> {
    unsafe fn image(&self) -> Option<Url> {
        (*self.unsafe_get()).image.borrow().clone()
    }
}

impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
    make_getter!(Alt)

    fn SetAlt(self, alt: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("alt", alt)
    }

    make_getter!(Src)

    fn SetSrc(self, src: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_url_attribute("src", src)
    }

    make_getter!(UseMap)

    fn SetUseMap(self, use_map: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("usemap", use_map)
    }

    make_bool_getter!(IsMap)

    fn SetIsMap(self, is_map: bool) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("ismap", is_map.to_string())
    }

    fn Width(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        to_px(rect.size.width) as u32
    }

    fn SetWidth(self, width: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute("width", width)
    }

    fn Height(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        to_px(rect.size.height) as u32
    }

    fn SetHeight(self, height: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute("height", height)
    }

    make_getter!(Name)

    fn SetName(self, name: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("name", name)
    }

    make_getter!(Align)

    fn SetAlign(self, align: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("align", align)
    }

    make_uint_getter!(Hspace)

    fn SetHspace(self, hspace: u32) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_uint_attribute("hspace", hspace)
    }

    make_uint_getter!(Vspace)

    fn SetVspace(self, vspace: u32) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_uint_attribute("vspace", vspace)
    }

    make_getter!(LongDesc)

    fn SetLongDesc(self, longdesc: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("longdesc", longdesc)
    }

    make_getter!(Border)

    fn SetBorder(self, border: DOMString) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("border", border)
    }
}

impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
    fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
        let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn after_set_attr(&self, name: &Atom, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.after_set_attr(name, value.clone()),
            _ => (),
        }

        if "src" == name.as_slice() {
            let window = window_from_node(*self).root();
            let url = window.deref().get_url();
            self.update_image(Some((value, &url)));
        }
    }

    fn before_remove_attr(&self, name: &Atom, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.before_remove_attr(name, value.clone()),
            _ => (),
        }

        if "src" == name.as_slice() {
            self.update_image(None);
        }
    }

    fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
        match name {
            "width" | "height" | "hspace" | "vspace" => AttrValue::from_u32(value, 0),
            _ => self.super_type().unwrap().parse_plain_attribute(name, value),
        }
    }
}

impl Reflectable for HTMLImageElement {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.htmlelement.reflector()
    }
}
<commit_msg>Use macro setters for <img><commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::attr::AttrValue;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{Element, HTMLImageElementTypeId};
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
use dom::virtualmethods::VirtualMethods;
use servo_net::image_cache_task;
use servo_util::geometry::to_px;
use servo_util::str::DOMString;
use string_cache::Atom;

use url::{Url, UrlParser};

use std::cell::RefCell;

#[jstraceable]
#[must_root]
pub struct HTMLImageElement {
    pub htmlelement: HTMLElement,
    image: RefCell<Option<Url>>,
}

impl HTMLImageElementDerived for EventTarget {
    fn is_htmlimageelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLImageElementTypeId))
    }
}

trait PrivateHTMLImageElementHelpers {
    fn update_image(self, value: Option<(DOMString, &Url)>);
}

impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
    /// Makes the local `image` member match the status of the `src` attribute and starts
    /// prefetching the image. This method must be called after `src` is changed.
    fn update_image(self, value: Option<(DOMString, &Url)>) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let document = node.owner_doc().root();
        let window = document.deref().window.root();
        let image_cache = &window.image_cache_task;
        match value {
            None => {
                *self.image.borrow_mut() = None;
            }
            Some((src, base_url)) => {
                let img_url = UrlParser::new().base_url(base_url).parse(src.as_slice());
                // FIXME: handle URL parse errors more gracefully.
                let img_url = img_url.unwrap();
                *self.image.borrow_mut() = Some(img_url.clone());

                // inform the image cache to load this, but don't store a
                // handle.
                //
                // TODO (Issue #84): don't prefetch if we are within a
                // <noscript> tag.
                image_cache.send(image_cache_task::Prefetch(img_url));
            }
        }
    }
}

impl HTMLImageElement {
    fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLImageElement {
        HTMLImageElement {
            htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, prefix, document),
            image: RefCell::new(None),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> Temporary<HTMLImageElement> {
        let element = HTMLImageElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
    }
}

pub trait LayoutHTMLImageElementHelpers {
    unsafe fn image(&self) -> Option<Url>;
}

impl LayoutHTMLImageElementHelpers for JS<HTMLImageElement> {
    unsafe fn image(&self) -> Option<Url> {
        (*self.unsafe_get()).image.borrow().clone()
    }
}

impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
    make_getter!(Alt)

    make_setter!(SetAlt, "alt")

    make_getter!(Src)

    make_setter!(SetSrc, "src")

    make_getter!(UseMap)

    make_bool_setter!(SetUseMap, "usemap")

    make_bool_getter!(IsMap)

    fn SetIsMap(self, is_map: bool) {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        element.set_string_attribute("ismap", is_map.to_string())
    }

    fn Width(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        to_px(rect.size.width) as u32
    }

    fn SetWidth(self, width: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute("width", width)
    }

    fn Height(self) -> u32 {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        let rect = node.get_bounding_content_box();
        to_px(rect.size.height) as u32
    }

    fn SetHeight(self, height: u32) {
        let elem: JSRef<Element> = ElementCast::from_ref(self);
        elem.set_uint_attribute("height", height)
    }

    make_getter!(Name)

    make_setter!(SetName, "name")

    make_getter!(Align)

    make_setter!(SetAlign, "align")

    make_uint_getter!(Hspace)

    make_uint_setter!(SetHspace, "hspace")

    make_uint_getter!(Vspace)

    make_uint_setter!(SetVspace, "Vspace")

    make_getter!(LongDesc)

    make_setter!(SetLongDesc, "longdesc")

    make_getter!(Border)

    make_setter!(SetBorder, "border")
}

impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
    fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
        let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn after_set_attr(&self, name: &Atom, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.after_set_attr(name, value.clone()),
            _ => (),
        }

        if "src" == name.as_slice() {
            let window = window_from_node(*self).root();
            let url = window.deref().get_url();
            self.update_image(Some((value, &url)));
        }
    }

    fn before_remove_attr(&self, name: &Atom, value: DOMString) {
        match self.super_type() {
            Some(ref s) => s.before_remove_attr(name, value.clone()),
            _ => (),
        }

        if "src" == name.as_slice() {
            self.update_image(None);
        }
    }

    fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
        match name {
            "width" | "height" | "hspace" | "vspace" => AttrValue::from_u32(value, 0),
            _ => self.super_type().unwrap().parse_plain_attribute(name, value),
        }
    }
}

impl Reflectable for HTMLImageElement {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.htmlelement.reflector()
    }
}
<|endoftext|>


<commit_before>use character;
use action;
use graphics;
use graphics::*;
use Gl = piston::gl::Gl;
use settings;
use spring::Spring;
use bar::Bar;
use player;
use player::Player;
use snake;
use snake::Snake;
use graphics::interpolation::{lerp_4};

pub enum ObjectData {
    PlayerData(Player),
    SnakeData(Snake),
    BarData(Bar),
    BarBackgroundData,
}

/// All objects are of same kind.
/// Makes it easier to write game logic.
pub struct Object {
    pub layer: uint,
    pub pos: [f64, ..2],
    pub vel: [f64, ..2],
    pub acc: [f64, ..2],
    pub acceleration_h: [f64, ..2],
    pub acceleration_v: [f64, ..2],
    pub radius: f64,
    pub test_color: [f32, ..4],
    pub data: ObjectData,
}

impl Object {
    pub fn bar_background() -> Object {
        Object {
            pos: [0.0, 0.0],
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            layer: 1,
            radius: 0.0,
            test_color: [0.0, 0.0, 0.0, 0.0],
            acceleration_h: [0.0, 0.0],
            acceleration_v: [0.0, 0.0],
            data: BarBackgroundData,
        }
    }

    pub fn player(
        pos: [f64, ..2],
        test_color: [f32, ..4],
        blood: f64,
        air: f64,
        acceleration_h: [f64, ..2],
        acceleration_v: [f64, ..2]) -> Object {
        Object {
            layer: 0,
            pos: pos,
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            acceleration_h: acceleration_h,
            acceleration_v: acceleration_v,
            radius: settings::PLAYER_RADIUS,
            test_color: test_color,
            data: PlayerData(Player {
                blood: blood,
                air: air,
                tween_factor: settings::PLAYER_INITIAL_TWEEN_FACTOR,
                state: settings::PLAYER_INITIAL_STATE,
            }),
        }
    }

    pub fn snake(
        pos: [f64, ..2],
        settings: settings::SnakeSettings
    ) -> Object {

        let mut tail = [0.0, ..256];
        let n = tail.len() / 2;
        for i in range(0, n) {
            tail[i * 2] = pos[0];
            tail[i * 2 + 1] = pos[1];
        }
        Object {
            layer: 0,
            pos: pos,
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            acceleration_h: [settings.acceleration_left, settings.acceleration_right],
            acceleration_v: [settings.acceleration_up, settings.acceleration_down],
            radius: settings.radius,
            test_color: settings.test_color,
            data: SnakeData(Snake {
                sensor_distance: settings.sensor_distance,
                state: settings.initial_state,
                bite_damage: settings.bite_damage,
                attack_distance: settings.attack_distance,
                tail: tail,
                wait_seconds_before_initial_attack: settings.wait_seconds_before_initial_attack,
                wait_seconds_before_repeat_attack: settings.wait_seconds_before_repeat_attack,
            }),
        }
    }

    pub fn bar(
        pos: [f64, ..2],
        text: &'static str,
        text_color: [f32, ..4],
        background_color: [f32, ..4],
        bar_color: [f32, ..4],
        value: f64
    ) -> Object {

       Object {
            layer: 2,
            pos: pos,
            radius: 0.0,
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            acceleration_h: [0.0, 0.0],
            acceleration_v: [0.0, 0.0],
            test_color: settings::BLACK,
            data: BarData(Bar {
                text: text,
                value: value,
                text_color: text_color,
                background_color: background_color,
                bar_color: bar_color,
            }),
        }
    }

    pub fn blood(&self) -> Option<f64> {
        match self.data {
            PlayerData(player) => Some(player.blood),
            _ => None,
        }
    }

    pub fn blood_mut<'a>(&'a mut self) -> Option<&'a mut f64> {
        match self.data {
            PlayerData(ref mut player) => Some(&mut player.blood),
            _ => None,
        }
    }

    pub fn air(&self) -> Option<f64> {
        match self.data {
            PlayerData(player) => Some(player.air),
            _ => None,
        }
    }

    pub fn air_mut<'a>(&'a mut self) -> Option<&'a mut f64> {
        match self.data {
            PlayerData(ref mut player) => Some(&mut player.air),
            _ => None,
        }
    }

    pub fn player_mut<'a>(&'a mut self) -> Option<&'a mut Player> {
        match self.data {
            PlayerData(ref mut player) => Some(player),
            _ => None,
        }
    }

    pub fn render(&self, cam: &graphics::Context, c: &graphics::Context, gl: &mut Gl) {
        let x = self.pos[0];
        let y = self.pos[1];
        let rad = self.radius;

        match self.data {
            SnakeData(ref snake) => {
                // cam.square_centered(x, y, rad).color(self.test_color).fill(gl);
                cam.circle_centered(x, y, rad).color(self.test_color).fill(gl);
                let n = snake.tail.len() / 2;
                for i in range(0, n) {
                    let x = snake.tail[i * 2];
                    let y = snake.tail[i * 2 + 1];
                    cam.circle_centered(x, y, rad).color(settings::SNAKE_TAIL_COLOR).fill(gl);
                }
            },
            PlayerData(ref player) => {
                // cam.square_centered(x, y, rad).color(self.test_color).fill(gl);
                match player.state {
                    player::Normal => {
                        character::draw_character(player.tween_factor,
                        &cam.trans_local(x, y).zoom_local(0.002).color(settings::PLAYER_COLOR), gl);
                    },
                    player::Bitten(sec) => {
                        let t = (1.0 - sec / settings::PLAYER_BITTEN_FADE_OUT_SECONDS);
                        let color = lerp_4(&settings::PLAYER_BITTEN_COLOR, &settings::PLAYER_COLOR, &(t as f32));
                        character::draw_character(player.tween_factor,
                        &cam.trans_local(x, y).zoom_local(0.002).color(color), gl);
                    },
                }
            },
            BarData(bar) => {
                bar.render(&c.trans_local(x, y), gl);
            },
            BarBackgroundData => {
                // Render round rectangle around bars.
                let bar_bgh = settings::BAR_BACKGROUND_HEIGHT;
                let bar_color = settings::BAR_BACKGROUND_COLOR;
                let bar_color_2 = settings::BAR_BACKGROUND_COLOR_2;
                let margin = settings::BAR_BACKGROUND_MARGIN;
                let margin_2 = settings::BAR_BACKGROUND_MARGIN_2;
                c.rect(-1.0, 1.0 - bar_bgh, 2.0, bar_bgh).margin(margin).round(0.1).color(bar_color).fill(gl);
                c.rect(-1.0, 1.0 - bar_bgh, 2.0, bar_bgh).margin(margin_2).round(0.1).color(bar_color_2).fill(gl);
            }
        };
    }

    fn move_snake(&mut self, state: snake::SnakeState, player_dx: f64, player_dy: f64) {
        match state {
            snake::ChasingPlayer => {
                if player_dx > 0.0 { self.move_right(); }
                else { self.move_left(); }

                if player_dy > 0.0 { self.move_up(); }
                else { self.move_down(); }
            },
            _ => {},
       }
    }

    pub fn update(&mut self, dt: f64, player_pos: [f64, ..2]) -> action::Action {
        self.pos = [
            self.pos[0] + 0.5 * self.vel[0] * dt,
            self.pos[1] + 0.5 * self.vel[1] * dt
        ];
        self.vel = [
            self.vel[0] + self.acc[0] * dt,
            self.vel[1] + self.acc[1] * dt
        ];
        let vel_len = self.vel[0] * self.vel[0] + self.vel[1] * self.vel[1];
        let friction = settings::WATER_FRICTION;
        let drag = 1.0 / (vel_len * friction).exp();
        self.vel = [
            self.vel[0] * drag,
            self.vel[1] * drag
        ];
        self.pos = [
            self.pos[0] + 0.5 * self.vel[0] * dt,
            self.pos[1] + 0.5 * self.vel[1] * dt
        ];

        let mut action = action::Passive;
        // Update object state.
        let (player_dx, player_dy) = (player_pos[0] - self.pos[0], player_pos[1] - self.pos[1]);
        match self.data {
            SnakeData(ref mut shark) => {
                action = shark.update(dt, player_pos, self.pos);
            },
            PlayerData(ref mut player) => {
                player.update(dt);
            },
            _ => {},
        }

        // Move object.
        match self.data {
            SnakeData(Snake { state: state, ..}) => {
                self.move_snake(state, player_dx, player_dy);
            },
            _ => {},
        }

        action
    }

    pub fn move_right(&mut self) {
        let acc_right = self.acceleration_h[1];
        self.acc = [acc_right, self.acc[1]];
    }

    pub fn move_left(&mut self) {
        let acc_left = self.acceleration_h[0];
        self.acc = [-acc_left, self.acc[1]];
    }

    pub fn move_up(&mut self) {
        let acc_up = self.acceleration_v[0];
        self.acc = [self.acc[0], acc_up];
    }

    pub fn move_down(&mut self) {
        let acc_down = self.acceleration_v[1];
        self.acc = [self.acc[0], -acc_down];
    }
}

<commit_msg>Refactoring<commit_after>use character;
use action;
use graphics;
use graphics::*;
use Gl = piston::gl::Gl;
use settings;
use spring::Spring;
use bar::Bar;
use player;
use player::Player;
use snake;
use snake::Snake;
use graphics::interpolation::{lerp_4};

pub enum ObjectData {
    PlayerData(Player),
    SnakeData(Snake),
    BarData(Bar),
    BarBackgroundData,
}

/// All objects are of same kind.
/// Makes it easier to write game logic.
pub struct Object {
    pub layer: uint,
    pub pos: [f64, ..2],
    pub vel: [f64, ..2],
    pub acc: [f64, ..2],
    pub acceleration_h: [f64, ..2],
    pub acceleration_v: [f64, ..2],
    pub radius: f64,
    pub test_color: [f32, ..4],
    pub data: ObjectData,
}

impl Object {
    pub fn bar_background() -> Object {
        Object {
            pos: [0.0, 0.0],
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            layer: 1,
            radius: 0.0,
            test_color: [0.0, 0.0, 0.0, 0.0],
            acceleration_h: [0.0, 0.0],
            acceleration_v: [0.0, 0.0],
            data: BarBackgroundData,
        }
    }

    pub fn player(
        pos: [f64, ..2],
        test_color: [f32, ..4],
        blood: f64,
        air: f64,
        acceleration_h: [f64, ..2],
        acceleration_v: [f64, ..2]) -> Object {
        Object {
            layer: 0,
            pos: pos,
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            acceleration_h: acceleration_h,
            acceleration_v: acceleration_v,
            radius: settings::PLAYER_RADIUS,
            test_color: test_color,
            data: PlayerData(Player {
                blood: blood,
                air: air,
                tween_factor: settings::PLAYER_INITIAL_TWEEN_FACTOR,
                state: settings::PLAYER_INITIAL_STATE,
            }),
        }
    }

    pub fn snake(
        pos: [f64, ..2],
        settings: settings::SnakeSettings
    ) -> Object {

        let mut tail = [0.0, ..256];
        let n = tail.len() / 2;
        for i in range(0, n) {
            tail[i * 2] = pos[0];
            tail[i * 2 + 1] = pos[1];
        }
        Object {
            layer: 0,
            pos: pos,
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            acceleration_h: [settings.acceleration_left, settings.acceleration_right],
            acceleration_v: [settings.acceleration_up, settings.acceleration_down],
            radius: settings.radius,
            test_color: settings.test_color,
            data: SnakeData(Snake {
                sensor_distance: settings.sensor_distance,
                state: settings.initial_state,
                bite_damage: settings.bite_damage,
                attack_distance: settings.attack_distance,
                tail: tail,
                wait_seconds_before_initial_attack: settings.wait_seconds_before_initial_attack,
                wait_seconds_before_repeat_attack: settings.wait_seconds_before_repeat_attack,
            }),
        }
    }

    pub fn bar(
        pos: [f64, ..2],
        text: &'static str,
        text_color: [f32, ..4],
        background_color: [f32, ..4],
        bar_color: [f32, ..4],
        value: f64
    ) -> Object {

       Object {
            layer: 2,
            pos: pos,
            radius: 0.0,
            vel: [0.0, 0.0],
            acc: [0.0, 0.0],
            acceleration_h: [0.0, 0.0],
            acceleration_v: [0.0, 0.0],
            test_color: settings::BLACK,
            data: BarData(Bar {
                text: text,
                value: value,
                text_color: text_color,
                background_color: background_color,
                bar_color: bar_color,
            }),
        }
    }

    pub fn blood(&self) -> Option<f64> {
        match self.data {
            PlayerData(player) => Some(player.blood),
            _ => None,
        }
    }

    pub fn blood_mut<'a>(&'a mut self) -> Option<&'a mut f64> {
        match self.data {
            PlayerData(ref mut player) => Some(&mut player.blood),
            _ => None,
        }
    }

    pub fn air(&self) -> Option<f64> {
        match self.data {
            PlayerData(player) => Some(player.air),
            _ => None,
        }
    }

    pub fn air_mut<'a>(&'a mut self) -> Option<&'a mut f64> {
        match self.data {
            PlayerData(ref mut player) => Some(&mut player.air),
            _ => None,
        }
    }

    pub fn player_mut<'a>(&'a mut self) -> Option<&'a mut Player> {
        match self.data {
            PlayerData(ref mut player) => Some(player),
            _ => None,
        }
    }

    fn render_snake(&self, snake: &Snake, x: f64, y: f64, rad: f64, cam: &graphics::Context, c: &graphics::Context, gl: &mut Gl) {
        // cam.square_centered(x, y, rad).color(self.test_color).fill(gl);
        cam.circle_centered(x, y, rad).color(self.test_color).fill(gl);
        let n = snake.tail.len() / 2;
        for i in range(0, n) {
            let x = snake.tail[i * 2];
            let y = snake.tail[i * 2 + 1];
            cam.circle_centered(x, y, rad).color(settings::SNAKE_TAIL_COLOR).fill(gl);
        }
    }

    fn render_player(&self, player: &Player, x: f64, y: f64, cam: &graphics::Context, c: &graphics::Context, gl: &mut Gl) {
        // cam.square_centered(x, y, rad).color(self.test_color).fill(gl);
        match player.state {
            player::Normal => {
                character::draw_character(player.tween_factor,
                &cam.trans_local(x, y).zoom_local(0.002).color(settings::PLAYER_COLOR), gl);
            },
            player::Bitten(sec) => {
                let t = (1.0 - sec / settings::PLAYER_BITTEN_FADE_OUT_SECONDS);
                let color = lerp_4(&settings::PLAYER_BITTEN_COLOR, &settings::PLAYER_COLOR, &(t as f32));
                character::draw_character(player.tween_factor,
                &cam.trans_local(x, y).zoom_local(0.002).color(color), gl);
            },
        }
    }

    pub fn render(&self, cam: &graphics::Context, c: &graphics::Context, gl: &mut Gl) {
        let x = self.pos[0];
        let y = self.pos[1];
        let rad = self.radius;

        match self.data {
            SnakeData(ref snake) => self.render_snake(snake, x, y, rad, cam, c, gl),
            PlayerData(ref player) => self.render_player(player, x, y, cam, c, gl),
            BarData(bar) => {
                bar.render(&c.trans_local(x, y), gl);
            },
            BarBackgroundData => {
                // Render round rectangle around bars.
                let bar_bgh = settings::BAR_BACKGROUND_HEIGHT;
                let bar_color = settings::BAR_BACKGROUND_COLOR;
                let bar_color_2 = settings::BAR_BACKGROUND_COLOR_2;
                let margin = settings::BAR_BACKGROUND_MARGIN;
                let margin_2 = settings::BAR_BACKGROUND_MARGIN_2;
                c.rect(-1.0, 1.0 - bar_bgh, 2.0, bar_bgh).margin(margin).round(0.1).color(bar_color).fill(gl);
                c.rect(-1.0, 1.0 - bar_bgh, 2.0, bar_bgh).margin(margin_2).round(0.1).color(bar_color_2).fill(gl);
            }
        };
    }

    fn move_snake(&mut self, state: snake::SnakeState, player_dx: f64, player_dy: f64) {
        match state {
            snake::ChasingPlayer => {
                if player_dx > 0.0 { self.move_right(); }
                else { self.move_left(); }

                if player_dy > 0.0 { self.move_up(); }
                else { self.move_down(); }
            },
            _ => {},
       }
    }

    pub fn update(&mut self, dt: f64, player_pos: [f64, ..2]) -> action::Action {
        self.pos = [
            self.pos[0] + 0.5 * self.vel[0] * dt,
            self.pos[1] + 0.5 * self.vel[1] * dt
        ];
        self.vel = [
            self.vel[0] + self.acc[0] * dt,
            self.vel[1] + self.acc[1] * dt
        ];
        let vel_len = self.vel[0] * self.vel[0] + self.vel[1] * self.vel[1];
        let friction = settings::WATER_FRICTION;
        let drag = 1.0 / (vel_len * friction).exp();
        self.vel = [
            self.vel[0] * drag,
            self.vel[1] * drag
        ];
        self.pos = [
            self.pos[0] + 0.5 * self.vel[0] * dt,
            self.pos[1] + 0.5 * self.vel[1] * dt
        ];

        let mut action = action::Passive;
        // Update object state.
        let (player_dx, player_dy) = (player_pos[0] - self.pos[0], player_pos[1] - self.pos[1]);
        match self.data {
            SnakeData(ref mut shark) => {
                action = shark.update(dt, player_pos, self.pos);
            },
            PlayerData(ref mut player) => {
                player.update(dt);
            },
            _ => {},
        }

        // Move object.
        match self.data {
            SnakeData(Snake { state: state, ..}) => {
                self.move_snake(state, player_dx, player_dy);
            },
            _ => {},
        }

        action
    }

    pub fn move_right(&mut self) {
        let acc_right = self.acceleration_h[1];
        self.acc = [acc_right, self.acc[1]];
    }

    pub fn move_left(&mut self) {
        let acc_left = self.acceleration_h[0];
        self.acc = [-acc_left, self.acc[1]];
    }

    pub fn move_up(&mut self) {
        let acc_up = self.acceleration_v[0];
        self.acc = [self.acc[0], acc_up];
    }

    pub fn move_down(&mut self) {
        let acc_down = self.acceleration_v[1];
        self.acc = [self.acc[0], -acc_down];
    }
}

<|endoftext|>


<commit_before>use std;
use std::ops::{Deref, DerefMut};
use std::ops::Index;
use std::ptr;

use class::Class;
use gc::Gc;
use mem;
use mem::ptr::Ptr;

pub struct Header<'a, 'ast: 'a> {
    // ptr to class
    class: &'a Class<'ast>,

    // additional information (e.g. gc marked flag)
    word: usize,
}

impl<'a, 'ast> Header<'a, 'ast> {
    pub fn unmark(&mut self) {
        self.word = self.word & (~1);
    }

    pub fn mark(&mut self) {
        self.word = self.word | 1;
    }

    pub fn is_marked(&self) -> bool {
        if (self.word & 1) != 0 {
            true
        } else {
            false
        }
    }
}

// is used to reference any object
pub struct Obj<'a, 'ast: 'a> {
    header: Header<'a, 'ast>,
}

// String in Dora is immutable
// length + string content is stored in one contiguous memory
pub struct Str {
    ptr: Ptr
}

impl Str {
    pub fn len(&self) -> usize {
        unsafe {
            *(self.ptr.raw() as *const usize)
        }
    }

    pub fn ptr(&self) -> Ptr {
        self.ptr
    }

    pub fn set_len(&self, len: usize) {
        unsafe {
            *(self.ptr.raw() as *mut usize) = len;
        }
    }

    pub fn data(&self) -> *mut u8 {
        unsafe {
            self.ptr.raw().offset(mem::ptr_width() as isize) as *mut u8
        }
    }
}

impl Str {
    pub fn from_buffer(gc: &mut Gc, buf: &[u8]) -> Str {
        let string = Str::new(gc, buf.len());

        unsafe {
            // write len of Str (excluding 0 at end)
            string.set_len(buf.len());

            // copy buffer content into Str
            ptr::copy_nonoverlapping(buf.as_ptr(), string.data(), buf.len());

            // string should end with 0 for C compatibility
            *(string.data().offset(buf.len() as isize)) = 0;
        }

        string
    }

    pub fn new(gc: &mut Gc, len: usize) -> Str {
        let size = mem::ptr_width() as usize + len + 1;

        Str { ptr: gc.alloc(size) }
    }

    pub fn concat(gc: &mut Gc, lhs: Str, rhs: Str) -> Str {
        let len = lhs.len() + rhs.len();
        let string = Str::new(gc, len);

        unsafe {
            string.set_len(len);

            ptr::copy_nonoverlapping(lhs.data(), string.data(), lhs.len());
            ptr::copy_nonoverlapping(rhs.data(),
                string.data().offset(lhs.len() as isize), rhs.len());

            *(string.data().offset(len as isize)) = 0;
        }

        string
    }
}

pub struct Handle<T> {
    ptr: *const T
}

impl<T> Deref for Handle<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.ptr }
    }
}

impl<T> DerefMut for Handle<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *(self.ptr as *mut T) }
    }
}

pub struct IntArray {
    ptr: *mut i32,
    length: usize,
}

impl IntArray {
    pub fn empty() -> IntArray {
        IntArray {
            ptr: ptr::null_mut(),
            length: 0,
        }
    }

    pub fn with_element(gc: &mut Gc, length: usize, elem: isize) -> IntArray {
        if length < 0 {
            panic!("length needs to be greater or equal to 0.");
        }

        let ptr = if length > 0 {
            gc.alloc(std::mem::size_of::<i32>() * length).raw() as *mut i32
        } else {
            ptr::null_mut()
        };

        for i in 0..length {
            unsafe {
                *ptr.offset(i as isize) = elem as i32;
            }
        }

        IntArray {
            ptr: ptr,
            length: length,
        }
    }

    pub fn size() -> usize {
        std::mem::size_of::<IntArray>()
    }

    pub fn len(&self) -> usize {
        self.length
    }

    pub fn get(&self, ind: i32) -> i32 {
        if ind < 0 || ind as usize >= self.length {
            panic!("index out of bounds");
        }

        unsafe {
            *self.ptr.offset(ind as isize)
        }
    }

    pub fn set(&self, ind: i32, value: i32) {
        if ind < 0 || ind as usize >= self.length {
            panic!("index out of bounds");
        }

        unsafe {
            *self.ptr.offset(ind as isize) = value;
        }
    }
}

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

    use gc::Gc;
    use libc;

    #[test]
    pub fn test_create_string() {
        let mut gc = Gc::new();
        let string = Str::from_buffer(&mut gc, "hello world!".as_bytes());

        unsafe {
            assert_eq!(12, string.len());

            let expected = "hello world!".as_ptr() as *const i8;
            let value = string.data() as *const i8;
            assert_eq!(0, libc::strncmp(expected, value, string.len()));
        }
    }
}
<commit_msg>renamed word to info, fixed syntax error<commit_after>use std;
use std::ops::{Deref, DerefMut};
use std::ops::Index;
use std::ptr;

use class::Class;
use gc::Gc;
use mem;
use mem::ptr::Ptr;

pub struct Header<'a, 'ast: 'a> {
    // ptr to class
    class: &'a Class<'ast>,

    // additional information (e.g. gc marked flag)
    info: usize,
}

impl<'a, 'ast> Header<'a, 'ast> {
    pub fn unmark(&mut self) {
        self.info = self.info & (!1);
    }

    pub fn mark(&mut self) {
        self.info = self.info | 1;
    }

    pub fn is_marked(&self) -> bool {
        if (self.info & 1) != 0 {
            true
        } else {
            false
        }
    }
}

// is used to reference any object
pub struct Obj<'a, 'ast: 'a> {
    header: Header<'a, 'ast>,
}

// String in Dora is immutable
// length + string content is stored in one contiguous memory
pub struct Str {
    ptr: Ptr
}

impl Str {
    pub fn len(&self) -> usize {
        unsafe {
            *(self.ptr.raw() as *const usize)
        }
    }

    pub fn ptr(&self) -> Ptr {
        self.ptr
    }

    pub fn set_len(&self, len: usize) {
        unsafe {
            *(self.ptr.raw() as *mut usize) = len;
        }
    }

    pub fn data(&self) -> *mut u8 {
        unsafe {
            self.ptr.raw().offset(mem::ptr_width() as isize) as *mut u8
        }
    }
}

impl Str {
    pub fn from_buffer(gc: &mut Gc, buf: &[u8]) -> Str {
        let string = Str::new(gc, buf.len());

        unsafe {
            // write len of Str (excluding 0 at end)
            string.set_len(buf.len());

            // copy buffer content into Str
            ptr::copy_nonoverlapping(buf.as_ptr(), string.data(), buf.len());

            // string should end with 0 for C compatibility
            *(string.data().offset(buf.len() as isize)) = 0;
        }

        string
    }

    pub fn new(gc: &mut Gc, len: usize) -> Str {
        let size = mem::ptr_width() as usize + len + 1;

        Str { ptr: gc.alloc(size) }
    }

    pub fn concat(gc: &mut Gc, lhs: Str, rhs: Str) -> Str {
        let len = lhs.len() + rhs.len();
        let string = Str::new(gc, len);

        unsafe {
            string.set_len(len);

            ptr::copy_nonoverlapping(lhs.data(), string.data(), lhs.len());
            ptr::copy_nonoverlapping(rhs.data(),
                string.data().offset(lhs.len() as isize), rhs.len());

            *(string.data().offset(len as isize)) = 0;
        }

        string
    }
}

pub struct Handle<T> {
    ptr: *const T
}

impl<T> Deref for Handle<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.ptr }
    }
}

impl<T> DerefMut for Handle<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *(self.ptr as *mut T) }
    }
}

pub struct IntArray {
    ptr: *mut i32,
    length: usize,
}

impl IntArray {
    pub fn empty() -> IntArray {
        IntArray {
            ptr: ptr::null_mut(),
            length: 0,
        }
    }

    pub fn with_element(gc: &mut Gc, length: usize, elem: isize) -> IntArray {
        if length < 0 {
            panic!("length needs to be greater or equal to 0.");
        }

        let ptr = if length > 0 {
            gc.alloc(std::mem::size_of::<i32>() * length).raw() as *mut i32
        } else {
            ptr::null_mut()
        };

        for i in 0..length {
            unsafe {
                *ptr.offset(i as isize) = elem as i32;
            }
        }

        IntArray {
            ptr: ptr,
            length: length,
        }
    }

    pub fn size() -> usize {
        std::mem::size_of::<IntArray>()
    }

    pub fn len(&self) -> usize {
        self.length
    }

    pub fn get(&self, ind: i32) -> i32 {
        if ind < 0 || ind as usize >= self.length {
            panic!("index out of bounds");
        }

        unsafe {
            *self.ptr.offset(ind as isize)
        }
    }

    pub fn set(&self, ind: i32, value: i32) {
        if ind < 0 || ind as usize >= self.length {
            panic!("index out of bounds");
        }

        unsafe {
            *self.ptr.offset(ind as isize) = value;
        }
    }
}

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

    use gc::Gc;
    use libc;

    #[test]
    pub fn test_create_string() {
        let mut gc = Gc::new();
        let string = Str::from_buffer(&mut gc, "hello world!".as_bytes());

        unsafe {
            assert_eq!(12, string.len());

            let expected = "hello world!".as_ptr() as *const i8;
            let value = string.data() as *const i8;
            assert_eq!(0, libc::strncmp(expected, value, string.len()));
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.
extern crate hyper;
#[macro_use] extern crate nickel;
extern crate cortex;
extern crate rustc_serialize;

use std::collections::HashMap;
use std::path::Path;
use std::fs;
// use std::io::Read;
use std::io::Error;
use nickel::{Nickel, HttpRouter}; //, MediaType, JsonBody
use hyper::header::Location;
use nickel::status::StatusCode;
use nickel::QueryString;
// use nickel::status::StatusCode;
// use hyper::header::Location;

use cortex::sysinfo;
use cortex::backend::{Backend};
use cortex::data::{Corpus};

#[derive(RustcDecodable, RustcEncodable)]
struct Person {
    firstname: String,
    lastname:  String,
}

// fn slurp_file (path : &'static str) -> Result<String, Error> {
//   let mut f = try!(File::open(path));
//   let mut content = String::new();
//   try!(f.read_to_string(&mut content));
//   Ok(content)
// }

fn main() {
    let mut server = Nickel::new();

    //middleware function logs each request to console
    server.utilize(middleware! { |request|
        println!("logging request: {:?}", request.origin.uri);
    });
    // Root greeter
    server.get("/", middleware! { |_, response|
        let mut data = HashMap::new();
        data.insert("title", "Framework Overview".to_string());
        return response.render("examples/assets/cortex-overview.html", &data);
    });
    server.get("/overview", middleware! { |_, response|
        let mut data = HashMap::new();
        data.insert("title", "Framework Overview".to_string());
        return response.render("examples/assets/cortex-overview.html", &data);
    });

    // Admin interface
    server.get("/admin", middleware! { |_, response|
      let mut data = HashMap::new();
      data.insert("title", "Admin Interface".to_string());
      match sysinfo::report(&mut data) {
        Ok(_) => {},
        Err(e) => println!("Sys report failed: {:?}", e)
      };
      return response.render("examples/assets/cortex-admin.html", &data);
    });

    server.get("/add_corpus", middleware! { |request, mut response|
      let backend = Backend::default();
      let mut data = HashMap::new();
      let mut message : String ;
      // let mut corpus_path;
      let query = request.query();
      if let Some(p) = query.get("path") {
        corpus_path = p.to_string();
      } else {
        data.insert("message", "Error: Please provide a path!".to_string());
        return response.render("examples/assets/cortex-admin.html", &data);
      }
      println!("Adding Path: {:?}", corpus_path);
      let complex : bool = query.get("setup") != Some("canonical");
      let path = Path::new(&corpus_path);
      match fs::metadata(path) {
        Ok(_) => {},
        Err(_) => {
          message = "Error: Path ".to_string() + &corpus_path + " does not exist, aborting!";

          response.set(Location("/admin".into()));
          response.set(StatusCode::TemporaryRedirect);
          return response.send("")
        }
      };
      let corpus_name = path.file_stem().unwrap().to_str().unwrap().to_string();

      // Queue the corpus for import using the task database:
      let input_corpus = Corpus {
        id : None,
        name : corpus_name,
        path : corpus_path.clone(),
        complex : complex,
      };
      message = match backend.add(input_corpus) {
        Ok(_) => "Successfully Queued ".to_string() + &corpus_path+ " for Import.",
        Err(_) => "Failed to add corpus, please retry!".to_string()
      };
      data.insert("message", message);
      return response.render("examples/assets/cortex-admin.html", &data);
    });

    server.get("/corpus-report", middleware! { |_, response|
      let mut data = HashMap::new();
      data.insert("title", "Corpus Report".to_string());
      return response.render("examples/assets/cortex-report.html", &data);
    });

    server.listen("127.0.0.1:6767");
}<commit_msg>silly oversight<commit_after>// Copyright 2015 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.
extern crate hyper;
#[macro_use] extern crate nickel;
extern crate cortex;
extern crate rustc_serialize;

use std::collections::HashMap;
use std::path::Path;
use std::fs;
// use std::io::Read;
use std::io::Error;
use nickel::{Nickel, HttpRouter}; //, MediaType, JsonBody
use hyper::header::Location;
use nickel::status::StatusCode;
use nickel::QueryString;
// use nickel::status::StatusCode;
// use hyper::header::Location;

use cortex::sysinfo;
use cortex::backend::{Backend};
use cortex::data::{Corpus};

#[derive(RustcDecodable, RustcEncodable)]
struct Person {
    firstname: String,
    lastname:  String,
}

// fn slurp_file (path : &'static str) -> Result<String, Error> {
//   let mut f = try!(File::open(path));
//   let mut content = String::new();
//   try!(f.read_to_string(&mut content));
//   Ok(content)
// }

fn main() {
    let mut server = Nickel::new();

    //middleware function logs each request to console
    server.utilize(middleware! { |request|
        println!("logging request: {:?}", request.origin.uri);
    });
    // Root greeter
    server.get("/", middleware! { |_, response|
        let mut data = HashMap::new();
        data.insert("title", "Framework Overview".to_string());
        return response.render("examples/assets/cortex-overview.html", &data);
    });
    server.get("/overview", middleware! { |_, response|
        let mut data = HashMap::new();
        data.insert("title", "Framework Overview".to_string());
        return response.render("examples/assets/cortex-overview.html", &data);
    });

    // Admin interface
    server.get("/admin", middleware! { |_, response|
      let mut data = HashMap::new();
      data.insert("title", "Admin Interface".to_string());
      match sysinfo::report(&mut data) {
        Ok(_) => {},
        Err(e) => println!("Sys report failed: {:?}", e)
      };
      return response.render("examples/assets/cortex-admin.html", &data);
    });

    server.get("/add_corpus", middleware! { |request, mut response|
      let backend = Backend::default();
      let mut data = HashMap::new();
      let mut message : String ;
      let mut corpus_path;
      let query = request.query();
      if let Some(p) = query.get("path") {
        corpus_path = p.to_string();
      } else {
        data.insert("message", "Error: Please provide a path!".to_string());
        return response.render("examples/assets/cortex-admin.html", &data);
      }
      println!("Adding Path: {:?}", corpus_path);
      let complex : bool = query.get("setup") != Some("canonical");
      let path = Path::new(&corpus_path);
      match fs::metadata(path) {
        Ok(_) => {},
        Err(_) => {
          message = "Error: Path ".to_string() + &corpus_path + " does not exist, aborting!";

          response.set(Location("/admin".into()));
          response.set(StatusCode::TemporaryRedirect);
          return response.send("")
        }
      };
      let corpus_name = path.file_stem().unwrap().to_str().unwrap().to_string();

      // Queue the corpus for import using the task database:
      let input_corpus = Corpus {
        id : None,
        name : corpus_name,
        path : corpus_path.clone(),
        complex : complex,
      };
      message = match backend.add(input_corpus) {
        Ok(_) => "Successfully Queued ".to_string() + &corpus_path+ " for Import.",
        Err(_) => "Failed to add corpus, please retry!".to_string()
      };
      data.insert("message", message);
      return response.render("examples/assets/cortex-admin.html", &data);
    });

    server.get("/corpus-report", middleware! { |_, response|
      let mut data = HashMap::new();
      data.insert("title", "Corpus Report".to_string());
      return response.render("examples/assets/cortex-report.html", &data);
    });

    server.listen("127.0.0.1:6767");
}<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata;
use flac::metadata::VorbisComment;

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <input>
       metadata comments [options] <input>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let mut index = 1;
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    println!("Vendor String: {}", vorbis_comment.vendor_string);
  }

  if no_flags {
    println!("Number of Comments: {}", vorbis_comment.comments.len());
  }

  for comment in &vorbis_comment.comments {
    let is_name = if let Some(ref name) = args.flag_name {
      name == comment.0
    } else {
      false
    };

    if no_flags || is_name {
      println!("  {}: \"{}\" = {}", index, comment.0, comment.1);
    }

    index += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          print_vorbis_comments(v, &args)
        }
      }
      _                                    => continue,
    }
  }
}
<commit_msg>Change to use `format_print!` macro for comments<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata;
use flac::metadata::VorbisComment;

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <input>
       metadata comments [options] <input>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let mut index = 1;
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    println!("Number of Comments: {}", vorbis_comment.comments.len());
  }

  for comment in &vorbis_comment.comments {
    let is_name = if let Some(ref name) = args.flag_name {
      name == comment.0
    } else {
      false
    };

    if no_flags || is_name {
      println!("  {}: \"{}\" = {}", index, comment.0, comment.1);
    }

    index += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          print_vorbis_comments(v, &args)
        }
      }
      _                                    => continue,
    }
  }
}
<|endoftext|>