<commit_before>use std::rc::Rc;
use std::collections::{VecDeque, HashMap};

use parser::Identifier;
use memory::{StaticAllocator, MemoryBlock};

use super::OperationsResult;
use super::item_type::ItemType;

pub type TypeId = usize;

/// The arguments that will get passed to a function
/// Arguments are guaranteed by static analysis to match the type defined for the function
pub type FuncArgs = Vec<ScopeItem>;

/// Represents a single item in a scope
pub enum ScopeItem {
    /// A type, not associated with any memory
    /// Used for a struct/type declaration, not the declaration
    /// of a variable with a type (TypedBlock should be used for that)
    Type(TypeId),

    /// A constant set of bytes inlined whenever used
    /// These items have no memory address
    /// The bytes of the constant are stored directly
    Constant {
        type_id: TypeId,
        /// Size of bytes must match the required size of type_id
        bytes: Vec<u8>,
    },

    /// A typed block of memory
    TypedBlock {
        type_id: TypeId,
        memory: MemoryBlock,
    },

    /// A built-in function definition
    BuiltInFunction {
        /// The ID of the type associated with this function
        id: TypeId,
        /// Generates operations that represent calling the
        /// function with the given arguments
        operations: Rc<Fn(&mut ScopeStack, FuncArgs) -> OperationsResult>,
    },
}

/// Represents a single level of scope
pub type Scope = HashMap<Identifier, ScopeItem>;

pub struct ScopeStack {
    stack: VecDeque<Scope>,
    allocator: StaticAllocator,
    /// A vector of all the declared types used to produce unique identities
    /// for all types so that types are static and not dependent on the context
    /// in which they are used.
    /// Basically, if we declare a type Foo and a variable with that type,
    /// we don't want a later declaration of Foo change the type of the variable
    /// Also used in functions/closures to uniquely refer to types in that context
    types: Vec<ItemType>,

    /// The TypeId that corresponds with the bool type
    bool_type_id: Option<TypeId>,
    array_type_id: Option<TypeId>,
}

impl ScopeStack {
    pub fn new() -> ScopeStack {
        ScopeStack {
            stack: {
                let mut queue = VecDeque::new();
                queue.push_back(Scope::new());
                queue
            },
            allocator: StaticAllocator::new(),
            types: vec![ItemType::Unit],
            bool_type_id: None,
            array_type_id: None,
        }
    }

    /// Pushes a new level of scope onto the stack
    /// This scope will become the current scope
    pub fn push_scope(&mut self) {
        self.stack.push_back(Scope::new());
    }

    /// Removes and returns the top level scope (current scope)
    ///
    /// # Panics
    /// Panics if there is no scope in the stack
    pub fn pop_scope(&mut self) -> Scope {
        self.stack.pop_back().unwrap()
    }

    /// Returns the type associated with the given TypeId
    pub fn get_type(&self, type_id: TypeId) -> &ItemType {
        // We just unwrap here because this isn't an error that can be generated by the user's
        // mistake. If this fails, it has to be a bug in the compiler.
        self.types.get(type_id).expect("Invalid TypeId used to lookup type")
    }

    /// Returns the TypeId of the Unit `()` type
    pub fn unit_type_id(&self) -> TypeId {
        0
    }

    /// Returns the TypeId of the bool type
    pub fn bool_type_id(&self) -> TypeId {
        // NOTE: The unit type, the bool type and the array type are "special primitives". These
        // types are fundamentally required for the compiler to function and so we need to provide
        // special access to them in the scope. We want a stronger guarantee than just relying on
        // names like "bool".
        // We don't want to couple the types' implementation with this module, so we simply add a
        // hatch for the implementing modules to define which TypeId should be associated with bool

        self.bool_type_id.expect("Expected a bool TypeId to be defined in the scope")
    }

    /// Set the TypeId for the primitive bool type
    pub fn set_bool_type_id(&mut self, type_id: TypeId) {
        // NOTE: See note in bool_type_id

        // This should only be called once
        debug_assert!(self.bool_type_id.is_none(), "Redefined bool TypeId in scope");

        debug_assert!(type_id != self.unit_type_id(), "Declared bool TypeId with the same TypeId as Unit");

        self.bool_type_id = Some(type_id)
    }

    /// Returns the TypeId of the array type
    pub fn array_type_id(&self) -> TypeId {
        // NOTE: See note in bool_type_id

        self.array_type_id.expect("Expected a array TypeId to be defined in the scope")
    }

    /// Set the TypeId for the primitive array type
    pub fn set_array_type_id(&mut self, type_id: TypeId) {
        // NOTE: See note in bool_type_id

        // This should only be called once
        debug_assert!(self.array_type_id.is_none(), "Redefined array TypeId in scope");

        debug_assert!(type_id != self.unit_type_id(), "Declared array TypeId with the same TypeId as Unit");

        self.array_type_id = Some(type_id)
    }

    /// Looks up a name starting at the current scope
    /// Returns ALL matches so that the caller can determine which definition is
    /// the correct one
    /// Definitions are returned in order from latest definition to oldest
    /// Always use the first definition that matches the type you are looking for
    pub fn lookup(&self, name: &Identifier) -> Vec<&ScopeItem> {
        self.stack.iter().rev().map(|sc| sc.get(name)).fold(Vec::new(), |mut acc, r| match r {
            Some(def) => {
                acc.push(def);
                acc
            },
            None => acc,
        })
    }

    /// Declares a type with the given name
    /// Returns the unique identifier of that type
    pub fn declare_type(&mut self, name: Identifier, typ: ItemType) -> TypeId {
        let type_id = self.insert_type(typ);
        self.insert_current(name, ScopeItem::Type(type_id));

        type_id
    }

    /// Declares a constant with the given name
    pub fn declare_constant(&mut self, name: Identifier, type_id: TypeId, value: Vec<u8>) {
        debug_assert!({
            let size = self.get_type(type_id).required_size(self);
            value.len() == size
        });

        self.insert_current(name, ScopeItem::Constant {
            type_id: type_id,
            bytes: value,
        });
    }

    /// Declares a name with the given type and allocates enough space for that type
    /// The name is declared in the "current" scope which is at the top of the stack
    /// Returns the allocated memory block
    pub fn declare(&mut self, name: Identifier, type_id: TypeId) -> MemoryBlock {
        let mem = self.allocate(type_id);
        self.insert_current(name, ScopeItem::TypedBlock {
            type_id: type_id,
            memory: mem,
        });

        mem
    }

    /// Allocate a memory block that is large enough for the given type
    /// Does not associate memory block with a name which means it cannot be looked up later
    /// Returns the allocated memory block
    pub fn allocate(&mut self, type_id: TypeId) -> MemoryBlock {
        let size = self.get_type(type_id).required_size(self);
        self.allocator.allocate(size)
    }

    /// Declares a built in function with the given name and type definition
    /// The name is declared in the "current" scope which is at the top of the stack
    /// The function is guaranteed to be called with arguments that match its given type signature
    pub fn declare_builtin_function<F: 'static>(&mut self, name: Identifier, typ: ItemType, f: F)
        where F: Fn(&mut ScopeStack, FuncArgs) -> OperationsResult {

        // Make sure we are declaring the function as a function type
        debug_assert!(match typ {
            ItemType::Function { .. } => true,
            _ => false,
        });

        let type_id = self.insert_type(typ);
        self.insert_current(name, ScopeItem::BuiltInFunction {
            id: type_id,
            operations: Rc::new(f),
        });
    }

    /// Inserts a ScopeItem into the current scope
    fn insert_current(&mut self, name: Identifier, item: ScopeItem) {
        // Notice that we insert directly without caring about whether the name already exists
        // It's OK to overwrite existing names because we support rebinding
        if let Some(scope) = self.stack.back_mut() {
            scope.insert(name, item);
        }
        else {
            panic!("Attempt to declare name despite having no current scope");
        }
    }

    /// Inserts a type defintion into the types field and returns its new TypeId
    fn insert_type(&mut self, typ: ItemType) -> TypeId {
        self.types.push(typ);

        self.types.len() - 1
    }
}

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

    use parser::Identifier;
    use operations::item_type::ItemType;

    #[test]
    fn unit_type_id() {
        let scope = ScopeStack::new();

        assert!(match *scope.get_type(scope.unit_type_id()) {
            ItemType::Unit => true,
            _ => false,
        });
    }

    #[test]
    fn bool_type_id() {
        const BOOL_TYPE_ID: TypeId = 1;

        let mut scope = ScopeStack::new();
        scope.set_bool_type_id(BOOL_TYPE_ID);

        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);
    }

    #[test]
    #[should_panic(expected = "Declared bool TypeId with the same TypeId as Unit")]
    fn bool_type_id_is_unit() {
        let mut scope = ScopeStack::new();

        let unit_id = scope.unit_type_id();
        scope.set_bool_type_id(unit_id);
    }

    #[test]
    #[should_panic(expected = "Expected a bool TypeId to be defined in the scope")]
    fn access_bool_type_id_without_declaration() {
        let scope = ScopeStack::new();

        scope.bool_type_id();
    }

    #[test]
    #[should_panic(expected = "Redefined bool TypeId in scope")]
    fn redefine_bool_type_id() {
        let mut scope = ScopeStack::new();

        scope.set_bool_type_id(1);
        scope.set_bool_type_id(2);
    }

    #[test]
    fn array_type_id() {
        const ARRAY_TYPE_ID: TypeId = 2;

        let mut scope = ScopeStack::new();
        scope.set_array_type_id(ARRAY_TYPE_ID);

        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);
    }

    #[test]
    #[should_panic(expected = "Declared array TypeId with the same TypeId as Unit")]
    fn array_type_id_is_unit() {
        let mut scope = ScopeStack::new();

        let unit_id = scope.unit_type_id();
        scope.set_array_type_id(unit_id);
    }

    #[test]
    #[should_panic(expected = "Expected a array TypeId to be defined in the scope")]
    fn access_array_type_id_without_declaration() {
        let scope = ScopeStack::new();

        scope.array_type_id();
    }

    #[test]
    #[should_panic(expected = "Redefined array TypeId in scope")]
    fn redefine_array_type_id() {
        let mut scope = ScopeStack::new();

        scope.set_array_type_id(2);
        scope.set_array_type_id(3);
    }

    #[test]
    fn bool_array_types_different() {
        // Make sure we are setting the right fields in the setter methods
        const BOOL_TYPE_ID: TypeId = 1;
        const ARRAY_TYPE_ID: TypeId = 2;

        let mut scope = ScopeStack::new();
        scope.set_array_type_id(ARRAY_TYPE_ID);
        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);
        scope.set_bool_type_id(BOOL_TYPE_ID);
        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);

        // Should not change
        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);

        assert!(scope.bool_type_id() != scope.array_type_id());

        let mut scope = ScopeStack::new();
        scope.set_bool_type_id(BOOL_TYPE_ID);
        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);
        scope.set_array_type_id(ARRAY_TYPE_ID);
        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);

        // Should not change
        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);

        assert!(scope.bool_type_id() != scope.array_type_id());
    }

    #[test]
    fn multiple_definitions() {
        let mut scope = ScopeStack::new();
        let type_id = scope.declare_type(Identifier::from("FooType"), ItemType::Primitive(1));
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 0);

        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 1);

        // Declaring the same name in the same scope should overwrite the
        // definition
        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 1);

        scope.push_scope();
        // Declaring foo in another scope should add a definition
        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 2);

        // Declaring the same name in the same scope should overwrite the
        // definition
        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 2);
    }
}
<commit_msg>Making it possible to lookup the type name associated with a given TypeId<commit_after>use std::rc::Rc;
use std::collections::{VecDeque, HashMap};

use parser::Identifier;
use memory::{StaticAllocator, MemoryBlock};

use super::OperationsResult;
use super::item_type::ItemType;

pub type TypeId = usize;

/// The arguments that will get passed to a function
/// Arguments are guaranteed by static analysis to match the type defined for the function
pub type FuncArgs = Vec<ScopeItem>;

/// Represents a single item in a scope
pub enum ScopeItem {
    /// A type, not associated with any memory
    /// Used for a struct/type declaration, not the declaration
    /// of a variable with a type (TypedBlock should be used for that)
    Type(TypeId),

    /// A constant set of bytes inlined whenever used
    /// These items have no memory address
    /// The bytes of the constant are stored directly
    Constant {
        type_id: TypeId,
        /// Size of bytes must match the required size of type_id
        bytes: Vec<u8>,
    },

    /// A typed block of memory
    TypedBlock {
        type_id: TypeId,
        memory: MemoryBlock,
    },

    /// A built-in function definition
    BuiltInFunction {
        /// The ID of the type associated with this function
        id: TypeId,
        /// Generates operations that represent calling the
        /// function with the given arguments
        operations: Rc<Fn(&mut ScopeStack, FuncArgs) -> OperationsResult>,
    },
}

/// Represents a single level of scope
pub type Scope = HashMap<Identifier, ScopeItem>;

pub struct ScopeStack {
    stack: VecDeque<Scope>,
    allocator: StaticAllocator,
    /// A vector of all the declared types used to produce unique identities
    /// for all types so that types are static and not dependent on the context
    /// in which they are used.
    /// Basically, if we declare a type Foo and a variable with that type,
    /// we don't want a later declaration of Foo change the type of the variable
    /// Also used in functions/closures to uniquely refer to types in that context
    types: Vec<(Identifier, ItemType)>,

    /// The TypeId that corresponds with the bool type
    bool_type_id: Option<TypeId>,
    array_type_id: Option<TypeId>,
}

impl ScopeStack {
    pub fn new() -> ScopeStack {
        ScopeStack {
            stack: {
                let mut queue = VecDeque::new();
                queue.push_back(Scope::new());
                queue
            },
            allocator: StaticAllocator::new(),
            types: vec![(Identifier::from("()"), ItemType::Unit)],
            bool_type_id: None,
            array_type_id: None,
        }
    }

    /// Pushes a new level of scope onto the stack
    /// This scope will become the current scope
    pub fn push_scope(&mut self) {
        self.stack.push_back(Scope::new());
    }

    /// Removes and returns the top level scope (current scope)
    ///
    /// # Panics
    /// Panics if there is no scope in the stack
    pub fn pop_scope(&mut self) -> Scope {
        self.stack.pop_back().unwrap()
    }

    /// Returns the type name associated with the given TypeId
    pub fn get_type_name(&self, type_id: TypeId) -> &Identifier {
        // We just unwrap here because this isn't an error that can be generated by the user's
        // mistake. If this fails, it has to be a bug in the compiler.
        &self.types.get(type_id).expect("Invalid TypeId used to lookup type").0
    }

    /// Returns the type associated with the given TypeId
    pub fn get_type(&self, type_id: TypeId) -> &ItemType {
        // We just unwrap here because this isn't an error that can be generated by the user's
        // mistake. If this fails, it has to be a bug in the compiler.
        &self.types.get(type_id).expect("Invalid TypeId used to lookup type").1
    }

    /// Returns the TypeId of the Unit `()` type
    pub fn unit_type_id(&self) -> TypeId {
        0
    }

    /// Returns the TypeId of the bool type
    pub fn bool_type_id(&self) -> TypeId {
        // NOTE: The unit type, the bool type and the array type are "special primitives". These
        // types are fundamentally required for the compiler to function and so we need to provide
        // special access to them in the scope. We want a stronger guarantee than just relying on
        // names like "bool".
        // We don't want to couple the types' implementation with this module, so we simply add a
        // hatch for the implementing modules to define which TypeId should be associated with bool

        self.bool_type_id.expect("Expected a bool TypeId to be defined in the scope")
    }

    /// Set the TypeId for the primitive bool type
    pub fn set_bool_type_id(&mut self, type_id: TypeId) {
        // NOTE: See note in bool_type_id

        // This should only be called once
        debug_assert!(self.bool_type_id.is_none(), "Redefined bool TypeId in scope");

        debug_assert!(type_id != self.unit_type_id(), "Declared bool TypeId with the same TypeId as Unit");

        self.bool_type_id = Some(type_id)
    }

    /// Returns the TypeId of the array type
    pub fn array_type_id(&self) -> TypeId {
        // NOTE: See note in bool_type_id

        self.array_type_id.expect("Expected a array TypeId to be defined in the scope")
    }

    /// Set the TypeId for the primitive array type
    pub fn set_array_type_id(&mut self, type_id: TypeId) {
        // NOTE: See note in bool_type_id

        // This should only be called once
        debug_assert!(self.array_type_id.is_none(), "Redefined array TypeId in scope");

        debug_assert!(type_id != self.unit_type_id(), "Declared array TypeId with the same TypeId as Unit");

        self.array_type_id = Some(type_id)
    }

    /// Looks up a name starting at the current scope
    /// Returns ALL matches so that the caller can determine which definition is
    /// the correct one
    /// Definitions are returned in order from latest definition to oldest
    /// Always use the first definition that matches the type you are looking for
    pub fn lookup(&self, name: &Identifier) -> Vec<&ScopeItem> {
        self.stack.iter().rev().map(|sc| sc.get(name)).fold(Vec::new(), |mut acc, r| match r {
            Some(def) => {
                acc.push(def);
                acc
            },
            None => acc,
        })
    }

    /// Declares a type with the given name
    /// Returns the unique identifier of that type
    pub fn declare_type(&mut self, name: Identifier, typ: ItemType) -> TypeId {
        let type_id = self.insert_type(&name, typ);
        self.insert_current(name, ScopeItem::Type(type_id));

        type_id
    }

    /// Declares a constant with the given name
    pub fn declare_constant(&mut self, name: Identifier, type_id: TypeId, value: Vec<u8>) {
        debug_assert!({
            let size = self.get_type(type_id).required_size(self);
            value.len() == size
        });

        self.insert_current(name, ScopeItem::Constant {
            type_id: type_id,
            bytes: value,
        });
    }

    /// Declares a name with the given type and allocates enough space for that type
    /// The name is declared in the "current" scope which is at the top of the stack
    /// Returns the allocated memory block
    pub fn declare(&mut self, name: Identifier, type_id: TypeId) -> MemoryBlock {
        let mem = self.allocate(type_id);
        self.insert_current(name, ScopeItem::TypedBlock {
            type_id: type_id,
            memory: mem,
        });

        mem
    }

    /// Allocate a memory block that is large enough for the given type
    /// Does not associate memory block with a name which means it cannot be looked up later
    /// Returns the allocated memory block
    pub fn allocate(&mut self, type_id: TypeId) -> MemoryBlock {
        let size = self.get_type(type_id).required_size(self);
        self.allocator.allocate(size)
    }

    /// Declares a built in function with the given name and type definition
    /// The name is declared in the "current" scope which is at the top of the stack
    /// The function is guaranteed to be called with arguments that match its given type signature
    pub fn declare_builtin_function<F: 'static>(&mut self, name: Identifier, typ: ItemType, f: F)
        where F: Fn(&mut ScopeStack, FuncArgs) -> OperationsResult {

        // Make sure we are declaring the function as a function type
        debug_assert!(match typ {
            ItemType::Function { .. } => true,
            _ => false,
        });

        let type_id = self.insert_type(&name, typ);
        self.insert_current(name, ScopeItem::BuiltInFunction {
            id: type_id,
            operations: Rc::new(f),
        });
    }

    /// Inserts a ScopeItem into the current scope
    fn insert_current(&mut self, name: Identifier, item: ScopeItem) {
        // Notice that we insert directly without caring about whether the name already exists
        // It's OK to overwrite existing names because we support rebinding
        if let Some(scope) = self.stack.back_mut() {
            scope.insert(name, item);
        }
        else {
            panic!("Attempt to declare name despite having no current scope");
        }
    }

    /// Inserts a type defintion into the types field and returns its new TypeId
    fn insert_type(&mut self, name: &Identifier, typ: ItemType) -> TypeId {
        self.types.push((name.clone(), typ));

        self.types.len() - 1
    }
}

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

    use parser::Identifier;
    use operations::item_type::ItemType;

    #[test]
    fn unit_type_id() {
        let scope = ScopeStack::new();

        assert!(match *scope.get_type(scope.unit_type_id()) {
            ItemType::Unit => true,
            _ => false,
        });
    }

    #[test]
    fn bool_type_id() {
        const BOOL_TYPE_ID: TypeId = 1;

        let mut scope = ScopeStack::new();
        scope.set_bool_type_id(BOOL_TYPE_ID);

        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);
    }

    #[test]
    #[should_panic(expected = "Declared bool TypeId with the same TypeId as Unit")]
    fn bool_type_id_is_unit() {
        let mut scope = ScopeStack::new();

        let unit_id = scope.unit_type_id();
        scope.set_bool_type_id(unit_id);
    }

    #[test]
    #[should_panic(expected = "Expected a bool TypeId to be defined in the scope")]
    fn access_bool_type_id_without_declaration() {
        let scope = ScopeStack::new();

        scope.bool_type_id();
    }

    #[test]
    #[should_panic(expected = "Redefined bool TypeId in scope")]
    fn redefine_bool_type_id() {
        let mut scope = ScopeStack::new();

        scope.set_bool_type_id(1);
        scope.set_bool_type_id(2);
    }

    #[test]
    fn array_type_id() {
        const ARRAY_TYPE_ID: TypeId = 2;

        let mut scope = ScopeStack::new();
        scope.set_array_type_id(ARRAY_TYPE_ID);

        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);
    }

    #[test]
    #[should_panic(expected = "Declared array TypeId with the same TypeId as Unit")]
    fn array_type_id_is_unit() {
        let mut scope = ScopeStack::new();

        let unit_id = scope.unit_type_id();
        scope.set_array_type_id(unit_id);
    }

    #[test]
    #[should_panic(expected = "Expected a array TypeId to be defined in the scope")]
    fn access_array_type_id_without_declaration() {
        let scope = ScopeStack::new();

        scope.array_type_id();
    }

    #[test]
    #[should_panic(expected = "Redefined array TypeId in scope")]
    fn redefine_array_type_id() {
        let mut scope = ScopeStack::new();

        scope.set_array_type_id(2);
        scope.set_array_type_id(3);
    }

    #[test]
    fn bool_array_types_different() {
        // Make sure we are setting the right fields in the setter methods
        const BOOL_TYPE_ID: TypeId = 1;
        const ARRAY_TYPE_ID: TypeId = 2;

        let mut scope = ScopeStack::new();
        scope.set_array_type_id(ARRAY_TYPE_ID);
        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);
        scope.set_bool_type_id(BOOL_TYPE_ID);
        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);

        // Should not change
        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);

        assert!(scope.bool_type_id() != scope.array_type_id());

        let mut scope = ScopeStack::new();
        scope.set_bool_type_id(BOOL_TYPE_ID);
        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);
        scope.set_array_type_id(ARRAY_TYPE_ID);
        assert_eq!(scope.array_type_id(), ARRAY_TYPE_ID);

        // Should not change
        assert_eq!(scope.bool_type_id(), BOOL_TYPE_ID);

        assert!(scope.bool_type_id() != scope.array_type_id());
    }

    #[test]
    fn multiple_definitions() {
        let mut scope = ScopeStack::new();
        let type_id = scope.declare_type(Identifier::from("FooType"), ItemType::Primitive(1));
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 0);

        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 1);

        // Declaring the same name in the same scope should overwrite the
        // definition
        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 1);

        scope.push_scope();
        // Declaring foo in another scope should add a definition
        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 2);

        // Declaring the same name in the same scope should overwrite the
        // definition
        scope.declare(Identifier::from("foo"), type_id);
        assert_eq!(scope.lookup(&Identifier::from("foo")).len(), 2);
    }
}
<|endoftext|>


<commit_before>use super::{PluginConfig, PluginMode};
use crate::config::ServerAddr;
use log::trace;
use std::{net::SocketAddr, process::Stdio};
use tokio::process::Command;

pub fn plugin_cmd(plugin: &PluginConfig, remote: &ServerAddr, local: &SocketAddr, _mode: PluginMode) -> Command {
    trace!(
        "Starting plugin \"{}\", opt: {:?} remote: {}, local: {}",
        plugin.plugin,
        plugin.plugin_opt,
        remote,
        local
    );

    let mut cmd = Command::new(&plugin.plugin);
    cmd.env("SS_REMOTE_HOST", remote.host())
        .env("SS_REMOTE_PORT", remote.port().to_string())
        .env("SS_LOCAL_HOST", local.ip().to_string())
        .env("SS_LOCAL_PORT", local.port().to_string())
        .stdin(Stdio::null());

    if let Some(ref opt) = plugin.plugin_opt {
        cmd.env("SS_PLUGIN_OPTIONS", opt);
        #[cfg(target_os = "android")]
        {
            // Add VPN flags to the commandline as well
            if opt.contains(";V") {
                cmd.arg("-V");
            }
        }
    }

    cmd
}
<commit_msg>Remove the VPN option hack<commit_after>use super::{PluginConfig, PluginMode};
use crate::config::ServerAddr;
use log::trace;
use std::{net::SocketAddr, process::Stdio};
use tokio::process::Command;

pub fn plugin_cmd(plugin: &PluginConfig, remote: &ServerAddr, local: &SocketAddr, _mode: PluginMode) -> Command {
    trace!(
        "Starting plugin \"{}\", opt: {:?} remote: {}, local: {}",
        plugin.plugin,
        plugin.plugin_opt,
        remote,
        local
    );

    let mut cmd = Command::new(&plugin.plugin);
    cmd.env("SS_REMOTE_HOST", remote.host())
        .env("SS_REMOTE_PORT", remote.port().to_string())
        .env("SS_LOCAL_HOST", local.ip().to_string())
        .env("SS_LOCAL_PORT", local.port().to_string())
        .stdin(Stdio::null());

    if let Some(ref opt) = plugin.plugin_opt {
        cmd.env("SS_PLUGIN_OPTIONS", opt);
    }

    cmd
}
<|endoftext|>


<commit_before>use crusty_chip::{decode, VirtualMachine, DISPLAY_HEIGHT, DISPLAY_WIDTH};
use egui_sfml::egui;
use getopts::Options;
use sfml::graphics::{RenderTarget, RenderWindow, Sprite, Texture, Transformable};
use sfml::system::Clock;
use sfml::window::{ContextSettings, Event, Key, Style, VideoMode};
use std::fs::File;
use std::io::Read;

fn sfml_key_to_ch8(code: Key) -> Option<u8> {
    Some(match code {
        Key::Num1 => 1,
        Key::Num2 => 2,
        Key::Num3 => 3,
        Key::Num4 => 0xC,
        Key::Q => 4,
        Key::W => 5,
        Key::E => 6,
        Key::R => 0xD,
        Key::A => 7,
        Key::S => 8,
        Key::D => 9,
        Key::F => 0xE,
        Key::Z => 0xA,
        Key::X => 0,
        Key::C => 0xB,
        Key::V => 0xF,
        _ => return None,
    })
}

fn usage(progname: &str, opts: &Options) -> String {
    let brief = format!("{} rom_file", progname);
    format!("Usage: {}", opts.usage(&brief))
}

fn run() -> i32 {
    let mut args = std::env::args();
    let progname = args.next().expect("Missing program name?");
    let mut opts = Options::new();
    opts.optflag("", "pause", "Start in a paused state");

    let matches = match opts.parse(args) {
        Ok(matches) => matches,
        Err(e) => {
            eprintln!("{}\n\n{}", e, usage(&progname, &opts));
            return 1;
        }
    };

    let mut paused = matches.opt_present("pause");

    let filename = match matches.free.get(0) {
        Some(filename) => filename,
        None => {
            eprintln!("Required filename as first positional argument.\n");
            eprintln!("{}", usage(&progname, &opts));
            return 1;
        }
    };

    let mut log_open = false;

    let mut clock = Clock::start();

    let file = match File::open(filename) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Failed to open \"{}\": {}", filename, e);
            return 1;
        }
    };

    let mut data = Vec::new();
    file.take(crusty_chip::MEM_SIZE as u64)
        .read_to_end(&mut data)
        .unwrap_or_else(|e| panic!("Failed to read rom: {}", e));

    let scale = 10;

    let mut ch8 = VirtualMachine::new();
    ch8.load_rom(&data);

    let ctx = ContextSettings::default();
    let mut win = RenderWindow::new(
        VideoMode::new(
            DISPLAY_WIDTH as u32 * scale,
            DISPLAY_HEIGHT as u32 * scale,
            32,
        ),
        "CrustyChip",
        Style::CLOSE,
        &ctx,
    );
    win.set_vertical_sync_enabled(true);

    let mut sf_egui = egui_sfml::SfEgui::new(&win);

    let mut tex = Texture::new().unwrap();
    if !tex.create(DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32) {
        panic!("Couldn't create texture");
    }
    let mut saved_states: [Option<VirtualMachine>; 10] = std::array::from_fn(|_idx| None);
    let mut printed_info = false;
    let mut cycles_made: u64 = 0;

    loop {
        let mut advance = false;
        while let Some(event) = win.poll_event() {
            sf_egui.add_event(&event);
            match event {
                Event::Closed => return 0,
                Event::KeyPressed {
                    code, ctrl, shift, ..
                } => {
                    if code == Key::P {
                        paused = !paused;
                    } else if code == Key::R && ctrl {
                        ch8 = VirtualMachine::new();
                        ch8.load_rom(&data);
                    } else if code == Key::Period {
                        advance = true;
                    } else if code == Key::F11 {
                        log_open ^= true;
                    } else if let Some(key) = sfml_key_to_ch8(code) {
                        ch8.press_key(key);
                    }
                    macro_rules! state_key (
                        ($s: expr, $k: ident) => (
                            if code == Key::$k {
                                if shift {
                                    saved_states[$s] = Some(ch8.clone());
                                    eprintln!("Saved state {}.", $s);
                                } else if let Some(state) = saved_states[$s].clone() {
                                    ch8 = state;
                                    eprintln!("Loaded state {}.", $s);
                                }
                            }
                        )
                    );
                    state_key!(0, F1);
                    state_key!(1, F2);
                    state_key!(2, F3);
                    state_key!(3, F4);
                    state_key!(4, F5);
                    state_key!(5, F6);
                    state_key!(6, F7);
                    state_key!(7, F8);
                    state_key!(8, F9);
                    state_key!(9, F10);
                }
                Event::KeyReleased { code, .. } => {
                    if let Some(key) = sfml_key_to_ch8(code) {
                        ch8.release_key(key);
                    }
                }
                _ => {}
            }
        }
        let mut cycles = 0;
        while !(ch8.display_updated() || ch8.waiting_for_key()) {
            do_emulation_cycle(
                &mut clock,
                &mut ch8,
                paused,
                &mut printed_info,
                &mut cycles_made,
                advance,
            );
            cycles += 1;
            // Take a little break and render if the machine takes too long
            // to respond
            if cycles > 50_000 {
                break;
            }
        }
        sf_egui.do_frame(|ctx| {
            egui::Window::new("Log (F11)")
                .open(&mut log_open)
                .show(ctx, |ui| {
                    egui::ScrollArea::vertical()
                        .stick_to_bottom(true)
                        .max_height(200.)
                        .show(ui, |ui| {
                            let log_size = 5000;
                            if ch8.log.len() > log_size {
                                ch8.log = ch8.log[ch8.log.len() - log_size..].to_owned();
                            }
                            ui.label(&ch8.log);
                        });
                });
        });
        render_screen(&mut win, &mut tex, &ch8, scale as f32);
        ch8.clear_du_flag();
        sf_egui.draw(&mut win, None);
        win.display();
    }
}

fn do_emulation_cycle(
    clock: &mut Clock,
    ch8: &mut VirtualMachine,
    paused: bool,
    printed_info: &mut bool,
    cycles_made: &mut u64,
    advance: bool,
) {
    if clock.elapsed_time().as_seconds() >= 1.0 / 60.0 {
        ch8.decrement_timers();
        clock.restart();
    }

    if paused && !*printed_info {
        let raw_ins = ch8.get_ins();
        println!(
            "Cycle {}, pc @ {:#x}, ins: {:#x?} raw: {:#x}",
            cycles_made,
            ch8.pc(),
            decode(raw_ins),
            raw_ins
        );
        *printed_info = true;
    }

    if !paused || advance {
        ch8.do_cycle();
        *cycles_made += 1;
        *printed_info = false;
    }
}

fn render_screen(win: &mut RenderWindow, tex: &mut Texture, ch8: &VirtualMachine, scale: f32) {
    let mut pixels = [255u8; DISPLAY_WIDTH * DISPLAY_HEIGHT * 4];

    for (i, b) in ch8.display().iter().enumerate() {
        let idx = i * 4;
        if *b == 0u8 {
            for p in pixels[idx..idx + 3].iter_mut() {
                *p = 0;
            }
        }
    }

    unsafe {
        tex.update_from_pixels(&pixels, DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32, 0, 0);
    }
    let mut sprite = Sprite::with_texture(tex);
    sprite.set_scale((scale, scale));
    win.draw(&sprite);
}

fn main() {
    std::process::exit(run());
}
<commit_msg>Log instead of println where possible<commit_after>use crusty_chip::{decode, VirtualMachine, DISPLAY_HEIGHT, DISPLAY_WIDTH};
use egui_sfml::egui;
use getopts::Options;
use sfml::graphics::{RenderTarget, RenderWindow, Sprite, Texture, Transformable};
use sfml::system::Clock;
use sfml::window::{ContextSettings, Event, Key, Style, VideoMode};
use std::fmt::Write;
use std::fs::File;
use std::io::Read;

fn sfml_key_to_ch8(code: Key) -> Option<u8> {
    Some(match code {
        Key::Num1 => 1,
        Key::Num2 => 2,
        Key::Num3 => 3,
        Key::Num4 => 0xC,
        Key::Q => 4,
        Key::W => 5,
        Key::E => 6,
        Key::R => 0xD,
        Key::A => 7,
        Key::S => 8,
        Key::D => 9,
        Key::F => 0xE,
        Key::Z => 0xA,
        Key::X => 0,
        Key::C => 0xB,
        Key::V => 0xF,
        _ => return None,
    })
}

fn usage(progname: &str, opts: &Options) -> String {
    let brief = format!("{} rom_file", progname);
    format!("Usage: {}", opts.usage(&brief))
}

fn run() -> i32 {
    let mut args = std::env::args();
    let progname = args.next().expect("Missing program name?");
    let mut opts = Options::new();
    opts.optflag("", "pause", "Start in a paused state");

    let matches = match opts.parse(args) {
        Ok(matches) => matches,
        Err(e) => {
            eprintln!("{}\n\n{}", e, usage(&progname, &opts));
            return 1;
        }
    };

    let mut paused = matches.opt_present("pause");

    let filename = match matches.free.get(0) {
        Some(filename) => filename,
        None => {
            eprintln!("Required filename as first positional argument.\n");
            eprintln!("{}", usage(&progname, &opts));
            return 1;
        }
    };

    let mut log_open = false;

    let mut clock = Clock::start();

    let file = match File::open(filename) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Failed to open \"{}\": {}", filename, e);
            return 1;
        }
    };

    let mut data = Vec::new();
    file.take(crusty_chip::MEM_SIZE as u64)
        .read_to_end(&mut data)
        .unwrap_or_else(|e| panic!("Failed to read rom: {}", e));

    let scale = 10;

    let mut ch8 = VirtualMachine::new();
    ch8.load_rom(&data);

    let ctx = ContextSettings::default();
    let mut win = RenderWindow::new(
        VideoMode::new(
            DISPLAY_WIDTH as u32 * scale,
            DISPLAY_HEIGHT as u32 * scale,
            32,
        ),
        "CrustyChip",
        Style::CLOSE,
        &ctx,
    );
    win.set_vertical_sync_enabled(true);

    let mut sf_egui = egui_sfml::SfEgui::new(&win);

    let mut tex = Texture::new().unwrap();
    if !tex.create(DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32) {
        panic!("Couldn't create texture");
    }
    let mut saved_states: [Option<VirtualMachine>; 10] = std::array::from_fn(|_idx| None);
    let mut printed_info = false;
    let mut cycles_made: u64 = 0;

    loop {
        let mut advance = false;
        while let Some(event) = win.poll_event() {
            sf_egui.add_event(&event);
            match event {
                Event::Closed => return 0,
                Event::KeyPressed {
                    code, ctrl, shift, ..
                } => {
                    if code == Key::P {
                        paused = !paused;
                    } else if code == Key::R && ctrl {
                        ch8 = VirtualMachine::new();
                        ch8.load_rom(&data);
                    } else if code == Key::Period {
                        advance = true;
                    } else if code == Key::F11 {
                        log_open ^= true;
                    } else if let Some(key) = sfml_key_to_ch8(code) {
                        ch8.press_key(key);
                    }
                    macro_rules! state_key (
                        ($s: expr, $k: ident) => (
                            if code == Key::$k {
                                if shift {
                                    saved_states[$s] = Some(ch8.clone());
                                    writeln!(ch8.log, "Saved state {}.", $s).unwrap();
                                } else if let Some(state) = saved_states[$s].clone() {
                                    ch8 = state;
                                    writeln!(ch8.log, "Loaded state {}.", $s).unwrap();
                                }
                            }
                        )
                    );
                    state_key!(0, F1);
                    state_key!(1, F2);
                    state_key!(2, F3);
                    state_key!(3, F4);
                    state_key!(4, F5);
                    state_key!(5, F6);
                    state_key!(6, F7);
                    state_key!(7, F8);
                    state_key!(8, F9);
                    state_key!(9, F10);
                }
                Event::KeyReleased { code, .. } => {
                    if let Some(key) = sfml_key_to_ch8(code) {
                        ch8.release_key(key);
                    }
                }
                _ => {}
            }
        }
        let mut cycles = 0;
        while !(ch8.display_updated() || ch8.waiting_for_key()) {
            do_emulation_cycle(
                &mut clock,
                &mut ch8,
                paused,
                &mut printed_info,
                &mut cycles_made,
                advance,
            );
            cycles += 1;
            // Take a little break and render if the machine takes too long
            // to respond
            if cycles > 50_000 {
                break;
            }
        }
        sf_egui.do_frame(|ctx| {
            egui::Window::new("Log (F11)")
                .open(&mut log_open)
                .show(ctx, |ui| {
                    egui::ScrollArea::vertical()
                        .stick_to_bottom(true)
                        .max_height(200.)
                        .show(ui, |ui| {
                            let log_size = 5000;
                            if ch8.log.len() > log_size {
                                ch8.log = ch8.log[ch8.log.len() - log_size..].to_owned();
                            }
                            ui.label(&ch8.log);
                        });
                });
        });
        render_screen(&mut win, &mut tex, &ch8, scale as f32);
        ch8.clear_du_flag();
        sf_egui.draw(&mut win, None);
        win.display();
    }
}

fn do_emulation_cycle(
    clock: &mut Clock,
    ch8: &mut VirtualMachine,
    paused: bool,
    printed_info: &mut bool,
    cycles_made: &mut u64,
    advance: bool,
) {
    if clock.elapsed_time().as_seconds() >= 1.0 / 60.0 {
        ch8.decrement_timers();
        clock.restart();
    }

    if paused && !*printed_info {
        let raw_ins = ch8.get_ins();
        writeln!(
            ch8.log,
            "Cycle {}, pc @ {:#x}, ins: {:#x?} raw: {:#x}",
            cycles_made,
            ch8.pc(),
            decode(raw_ins),
            raw_ins
        )
        .unwrap();
        *printed_info = true;
    }

    if !paused || advance {
        ch8.do_cycle();
        *cycles_made += 1;
        *printed_info = false;
    }
}

fn render_screen(win: &mut RenderWindow, tex: &mut Texture, ch8: &VirtualMachine, scale: f32) {
    let mut pixels = [255u8; DISPLAY_WIDTH * DISPLAY_HEIGHT * 4];

    for (i, b) in ch8.display().iter().enumerate() {
        let idx = i * 4;
        if *b == 0u8 {
            for p in pixels[idx..idx + 3].iter_mut() {
                *p = 0;
            }
        }
    }

    unsafe {
        tex.update_from_pixels(&pixels, DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32, 0, 0);
    }
    let mut sprite = Sprite::with_texture(tex);
    sprite.set_scale((scale, scale));
    win.draw(&sprite);
}

fn main() {
    std::process::exit(run());
}
<|endoftext|>


<commit_before><commit_msg>qlog: fmt<commit_after><|endoftext|>


<commit_before>// Copyright 2014-2016 Johannes Köster, Martin Larralde.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! One-way orf finder algorithm.
//!
//! Complexity: O(n).
//!
//! # Example
//!
//! ```
//! use bio::seq_analysis::orf::{Finder, Orf};
//! let start_codons = vec!(b"ATG");
//! let stop_codons  = vec!(b"TGA", b"TAG", b"TAA");
//! let min_len:usize = 50;
//! let finder = Finder::new(start_codons, stop_codons, min_len);
//!
//! let sequence = b"ACGGCTAGAAAAGGCTAGAAAA";
//!
//! for Orf{start, end, offset} in finder.find_all(sequence) {
//!    let orf = &sequence[start..end];
//!    //...do something with orf sequence...
//! }
//! ```
//!
//! Right now the only way to check the reverse strand for orf is to use
//! the alphabet::dna::RevComp struct and to check for both sequences.
//! But that's not so performance friendly, as the reverse complementation and the orf research
//! could go on at the same time.

use utils::{TextIterator, IntoTextIterator};
use std::collections::VecDeque;
use std::iter;

/// An implementation of a naive algorithm finder
pub struct Finder {
    start_codons: Vec<VecDeque<u8>>,
    stop_codons: Vec<VecDeque<u8>>,
    min_len: usize,
}

impl Finder {
    /// Create a new instance of a finder for the given start and stop codons and a particular length
    pub fn new<'a>(start_codons: Vec<&'a [u8; 3]>,
                   stop_codons: Vec<&'a [u8; 3]>,
                   min_len: usize)
                   -> Self {
        Finder {
            start_codons: start_codons.into_iter()                          // Convert start_ and
                                      .map(|x| {                            // stop_codons from
                                          x.into_iter()                     // Vec<&[u8;3]> to
                                           .map(|&x| x as u8)               // Vec<VecDeque<u8>>
                                           .collect::<VecDeque<u8>>()       // so they can be
                                      })                                    // easily compared
                                      .collect(), // with codon built
            stop_codons: stop_codons.into_iter()                            // from IntoTextIterator
                                    .map(|x| {                              // object.
                                        x.into_iter()
                                         .map(|&x| x as u8)
                                         .collect::<VecDeque<u8>>()
                                    })
                                    .collect(),
            min_len: min_len,
        }
    }

    /// Find all orfs in the given sequence
    pub fn find_all<'a, I: IntoTextIterator<'a>>(&'a self, seq: I) -> Matches<I::IntoIter> {
        Matches {
            finder: self,
            state: State::new(),
            seq: seq.into_iter().enumerate(),
        }
    }
}

/// An orf representation with start and end position of said orf,
/// as well as offset of the reading frame (1,2,3) and strand location
// (current: +, reverse complementary: -).
pub struct Orf {
    pub start: usize,
    pub end: usize,
    pub offset: i8,
}

/// The current algorithm state.
struct State {
    start_pos: [usize; 3],
    in_orf: [bool; 3],
    codon: VecDeque<u8>,
}

impl State {
    /// Create new state.
    pub fn new() -> Self {
        State {
            start_pos: [0, 0, 0],
            in_orf: [false, false, false],
            codon: VecDeque::new(),
        }
    }
}

/// Iterator over offset, start position, end position and sequence of matched orfs.
pub struct Matches<'a, I: TextIterator<'a>> {
    finder: &'a Finder,
    state: State,
    seq: iter::Enumerate<I>,
}

impl<'a, I: Iterator<Item = &'a u8>> Iterator for Matches<'a, I> {
    type Item = Orf;

    fn next(&mut self) -> Option<Orf> {

        let mut result: Option<Orf> = None;
        let mut offset: usize;

        for (index, &nuc) in self.seq.by_ref() {

            // update the codon
            if self.state.codon.len() >= 3 {
                self.state.codon.pop_front();
            }
            self.state.codon.push_back(nuc);
            offset = (index + 1) % 3;

            // inside orf
            if self.state.in_orf[offset] {
                // check if leaving orf
                if self.finder.stop_codons.contains(&self.state.codon) {
                    // check if length is sufficient
                    if index + 1 - self.state.start_pos[offset] > self.finder.min_len {
                        // build results
                        result = Some(Orf {
                            start: self.state.start_pos[offset] - 2,
                            end: index + 1,
                            offset: offset as i8,
                        });
                    }
                    // reinitialize
                    self.state.in_orf[offset] = false;
                    self.state.start_pos[offset] = 0;
                }
            } else {
                // check if entering orf
                if self.finder.start_codons.contains(&self.state.codon) {
                    self.state.in_orf[offset] = true;
                    self.state.start_pos[offset] = index;
                }
            }
            if result.is_some() {
                return result;
            }
        }
        None
    }
}
<commit_msg>changed start_pos elements to Option<usize><commit_after>// Copyright 2014-2016 Johannes Köster, Martin Larralde.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! One-way orf finder algorithm.
//!
//! Complexity: O(n).
//!
//! # Example
//!
//! ```
//! use bio::seq_analysis::orf::{Finder, Orf};
//! let start_codons = vec!(b"ATG");
//! let stop_codons  = vec!(b"TGA", b"TAG", b"TAA");
//! let min_len:usize = 50;
//! let finder = Finder::new(start_codons, stop_codons, min_len);
//!
//! let sequence = b"ACGGCTAGAAAAGGCTAGAAAA";
//!
//! for Orf{start, end, offset} in finder.find_all(sequence) {
//!    let orf = &sequence[start..end];
//!    //...do something with orf sequence...
//! }
//! ```
//!
//! Right now the only way to check the reverse strand for orf is to use
//! the alphabet::dna::RevComp struct and to check for both sequences.
//! But that's not so performance friendly, as the reverse complementation and the orf research
//! could go on at the same time.

use utils::{TextIterator, IntoTextIterator};
use std::collections::VecDeque;
use std::iter;

/// An implementation of a naive algorithm finder
pub struct Finder {
    start_codons: Vec<VecDeque<u8>>,
    stop_codons: Vec<VecDeque<u8>>,
    min_len: usize,
}

impl Finder {
    /// Create a new instance of a finder for the given start and stop codons and a particular length
    pub fn new<'a>(start_codons: Vec<&'a [u8; 3]>,
                   stop_codons: Vec<&'a [u8; 3]>,
                   min_len: usize)
                   -> Self {
        Finder {
            start_codons: start_codons.into_iter()                          // Convert start_ and
                                      .map(|x| {                            // stop_codons from
                                          x.into_iter()                     // Vec<&[u8;3]> to
                                           .map(|&x| x as u8)               // Vec<VecDeque<u8>>
                                           .collect::<VecDeque<u8>>()       // so they can be
                                      })                                    // easily compared
                                      .collect(), // with codon built
            stop_codons: stop_codons.into_iter()                            // from IntoTextIterator
                                    .map(|x| {                              // object.
                                        x.into_iter()
                                         .map(|&x| x as u8)
                                         .collect::<VecDeque<u8>>()
                                    })
                                    .collect(),
            min_len: min_len,
        }
    }

    /// Find all orfs in the given sequence
    pub fn find_all<'a, I: IntoTextIterator<'a>>(&'a self, seq: I) -> Matches<I::IntoIter> {
        Matches {
            finder: self,
            state: State::new(),
            seq: seq.into_iter().enumerate(),
        }
    }
}

/// An orf representation with start and end position of said orf,
/// as well as offset of the reading frame (1,2,3) and strand location
// (current: +, reverse complementary: -).
pub struct Orf {
    pub start: usize,
    pub end: usize,
    pub offset: i8,
}

/// The current algorithm state.
struct State {
    start_pos: [Option<usize>; 3],
    in_orf: [bool; 3],
    codon: VecDeque<u8>,
}

impl State {
    /// Create new state.
    pub fn new() -> Self {
        State {
            start_pos: [None, None, None],
            in_orf: [false, false, false],
            codon: VecDeque::new(),
        }
    }
}

/// Iterator over offset, start position, end position and sequence of matched orfs.
pub struct Matches<'a, I: TextIterator<'a>> {
    finder: &'a Finder,
    state: State,
    seq: iter::Enumerate<I>,
}

impl<'a, I: Iterator<Item = &'a u8>> Iterator for Matches<'a, I> {
    type Item = Orf;

    fn next(&mut self) -> Option<Orf> {

        let mut result: Option<Orf> = None;
        let mut offset: usize;

        for (index, &nuc) in self.seq.by_ref() {

            // update the codon
            if self.state.codon.len() >= 3 {
                self.state.codon.pop_front();
            }
            self.state.codon.push_back(nuc);
            offset = (index + 1) % 3;

            // inside orf
            if self.state.in_orf[offset] {
                // check if leaving orf
                if self.finder.stop_codons.contains(&self.state.codon) {
                    // check if length is sufficient
                    if index + 1 - self.state.start_pos[offset].unwrap() > self.finder.min_len {
                        // build results
                        result = Some(Orf {
                            start: self.state.start_pos[offset].unwrap() - 2,
                            end: index + 1,
                            offset: offset as i8,
                        });
                    }
                    // reinitialize
                    self.state.in_orf[offset] = false;
                    self.state.start_pos[offset] = None;
                }
            } else {
                // check if entering orf
                if self.finder.start_codons.contains(&self.state.codon) {
                    self.state.in_orf[offset] = true;
                    self.state.start_pos[offset] = Some(index);
                }
            }
            if result.is_some() {
                return result;
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>//! Monitor progress at a `Stream`.

use std::rc::Rc;
use std::cell::RefCell;

use progress::{Timestamp, Operate, Antichain};
use progress::frontier::MutableAntichain;
use progress::nested::subgraph::{Source, Target};
use progress::count_map::CountMap;

use dataflow::channels::pushers::Tee;
use dataflow::channels::pushers::Counter as PushCounter;
use dataflow::channels::pushers::buffer::Buffer as PushBuffer;
use dataflow::channels::pact::{ParallelizationContract, Pipeline};
use dataflow::channels::pullers::Counter as PullCounter;

use Data;
use dataflow::{Stream, Scope};

/// Monitors progress at a `Stream`.
pub trait Probe<G: Scope, D: Data> {
    /// Constructs a progress probe which indicates which timestamps have elapsed at the operator.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::Scope;
    /// use timely::dataflow::operators::{Input, Probe, Inspect};
    /// use timely::progress::timestamp::RootTimestamp;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let (mut input, probe) = worker.dataflow(|scope| {
    ///         let (input, stream) = scope.new_input();
    ///         let probe = stream.inspect(|x| println!("hello {:?}", x))
    ///                           .probe();
    ///         (input, probe)
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step_while(|| probe.less_than(input.time()));
    ///     }
    /// }).unwrap();
    /// ```
    fn probe(&self) -> Handle<G::Timestamp>;

    /// Inserts a progress probe in a stream.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::Scope;
    /// use timely::dataflow::operators::{Input, Probe, Inspect};
    /// use timely::dataflow::operators::probe::Handle;
    /// use timely::progress::timestamp::RootTimestamp;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut probe = Handle::new();
    ///     let mut input = worker.dataflow(|scope| {
    ///         let (input, stream) = scope.new_input();
    ///         stream.probe_with(&mut probe)
    ///               .inspect(|x| println!("hello {:?}", x));
    ///
    ///         input
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step_while(|| probe.less_than(input.time()));
    ///     }
    /// }).unwrap();
    /// ```
    fn probe_with(&self, handle: &mut Handle<G::Timestamp>) -> Stream<G, D>;
}

impl<G: Scope, D: Data> Probe<G, D> for Stream<G, D> {
    fn probe(&self) -> Handle<G::Timestamp> {

        // the frontier is shared state; scope updates, handle reads.
        let handle = Handle::new();

        let mut scope = self.scope();   // clones the scope
        let channel_id = scope.new_identifier();

        let (sender, receiver) = Pipeline.connect(&mut scope, channel_id);
        let (targets, registrar) = Tee::<G::Timestamp,D>::new();
        let operator = Operator {
            input: PullCounter::new(receiver),
            output: PushBuffer::new(PushCounter::new(targets, Rc::new(RefCell::new(CountMap::new())))),
            frontier: handle.frontier.clone(),
        };

        let index = scope.add_operator(operator);
        self.connect_to(Target { index: index, port: 0 }, sender, channel_id);
        Stream::new(Source { index: index, port: 0 }, registrar, scope);
        handle
    }
    fn probe_with(&self, handle: &mut Handle<G::Timestamp>) -> Stream<G, D> {

        let mut scope = self.scope();   // clones the scope
        let channel_id = scope.new_identifier();

        let (sender, receiver) = Pipeline.connect(&mut scope, channel_id);
        let (targets, registrar) = Tee::<G::Timestamp,D>::new();
        let operator = Operator {
            input: PullCounter::new(receiver),
            output: PushBuffer::new(PushCounter::new(targets, Rc::new(RefCell::new(CountMap::new())))),
            frontier: handle.frontier.clone(),
        };

        let index = scope.add_operator(operator);
        self.connect_to(Target { index: index, port: 0 }, sender, channel_id);
        Stream::new(Source { index: index, port: 0 }, registrar, scope)
    }
}

/// Reports information about progress at the probe.
pub struct Handle<T:Timestamp> {
    frontier: Rc<RefCell<MutableAntichain<T>>>
}

impl<T: Timestamp> Handle<T> {
    /// returns true iff the frontier is strictly less than `time`.
    #[inline] pub fn less_than(&self, time: &T) -> bool { self.frontier.borrow().less_than(time) }
    /// returns true iff the frontier is less than or equal to `time`.
    #[inline] pub fn less_equal(&self, time: &T) -> bool { self.frontier.borrow().less_equal(time) }
    /// returns true iff the frontier is empty.
    #[inline] pub fn done(&self) -> bool { self.frontier.borrow().elements().len() == 0 }
    /// Allocates a new handle.
    #[inline] pub fn new() -> Self { Handle { frontier: Rc::new(RefCell::new(MutableAntichain::new())) } }

    /// Invokes a method on the frontier, returning its result.
    ///
    /// This method allows inspection of the frontier, which cannot be returned by reference as
    /// it is on the other side of a `RefCell`.
    ///
    /// #Examples
    ///
    /// ```
    /// use timely::dataflow::operators::probe::Handle;
    ///
    /// let handle = Handle::<usize>::new();
    /// let frontier = handle.with_frontier(|frontier| frontier.to_vec());
    /// ```
    #[inline]
    pub fn with_frontier<R, F: Fn(&[T])->R>(&self, function: F) -> R {
        function(self.frontier.borrow().elements())
    }
}

impl<T: Timestamp> Clone for Handle<T> {
    fn clone(&self) -> Self {
        Handle {
            frontier: self.frontier.clone()
        }
    }
}

struct Operator<T:Timestamp, D: Data> {
    input: PullCounter<T, D>,
    output: PushBuffer<T, D, PushCounter<T, D, Tee<T, D>>>,
    frontier: Rc<RefCell<MutableAntichain<T>>>
}

impl<T:Timestamp, D: Data> Operate<T> for Operator<T, D> {
    fn name(&self) -> String { "Probe".to_owned() }
    fn inputs(&self) -> usize { 1 }
    fn outputs(&self) -> usize { 1 }

    // we need to set the initial value of the frontier
    fn set_external_summary(&mut self, _: Vec<Vec<Antichain<T::Summary>>>, counts: &mut [CountMap<T>]) {
        let mut borrow = self.frontier.borrow_mut();
        while let Some((time, delta)) = counts[0].pop() {
            borrow.update(&time, delta);
        }
    }

    // each change to the frontier should be shared
    fn push_external_progress(&mut self, counts: &mut [CountMap<T>]) {
        let mut borrow = self.frontier.borrow_mut();
        while let Some((time, delta)) = counts[0].pop() {
            borrow.update(&time, delta);
        }
    }

    // the scope does nothing. this is actually a problem, because "reachability" assumes all messages on each edge.
    fn pull_internal_progress(&mut self, consumed: &mut [CountMap<T>], _: &mut [CountMap<T>], produced: &mut [CountMap<T>]) -> bool {

        while let Some((time, data)) = self.input.next() {
            self.output.session(time).give_content(data);
        }

        self.output.cease();

        // extract what we know about progress from the input and output adapters.
        self.input.pull_progress(&mut consumed[0]);
        self.output.inner().pull_progress(&mut produced[0]);

        false
    }
}

#[cfg(test)]
mod tests {

    use ::Configuration;
    use ::progress::timestamp::RootTimestamp;
    use dataflow::operators::{Input, Probe};

    #[test]
    fn probe() {

        // initializes and runs a timely dataflow computation
        ::execute(Configuration::Thread, |worker| {

            // create a new input, and inspect its output
            let (mut input, probe) = worker.dataflow(move |scope| {
                let (input, stream) = scope.new_input::<String>();
                (input, stream.probe())
            });

            // introduce data and watch!
            for round in 0..10 {
                assert!(!probe.done());
                assert!(probe.less_equal(&RootTimestamp::new(round)));
                assert!(!probe.less_than(&RootTimestamp::new(round)));
                assert!(probe.less_than(&RootTimestamp::new(round + 1)));
                input.advance_to(round + 1);
                worker.step();
            }

            // seal the input
            input.close();

            // finish off any remaining work
            worker.step();
            assert!(probe.done());
        }).unwrap();
    }

}
<commit_msg>change Fn to FnMut<commit_after>//! Monitor progress at a `Stream`.

use std::rc::Rc;
use std::cell::RefCell;

use progress::{Timestamp, Operate, Antichain};
use progress::frontier::MutableAntichain;
use progress::nested::subgraph::{Source, Target};
use progress::count_map::CountMap;

use dataflow::channels::pushers::Tee;
use dataflow::channels::pushers::Counter as PushCounter;
use dataflow::channels::pushers::buffer::Buffer as PushBuffer;
use dataflow::channels::pact::{ParallelizationContract, Pipeline};
use dataflow::channels::pullers::Counter as PullCounter;

use Data;
use dataflow::{Stream, Scope};

/// Monitors progress at a `Stream`.
pub trait Probe<G: Scope, D: Data> {
    /// Constructs a progress probe which indicates which timestamps have elapsed at the operator.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::Scope;
    /// use timely::dataflow::operators::{Input, Probe, Inspect};
    /// use timely::progress::timestamp::RootTimestamp;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let (mut input, probe) = worker.dataflow(|scope| {
    ///         let (input, stream) = scope.new_input();
    ///         let probe = stream.inspect(|x| println!("hello {:?}", x))
    ///                           .probe();
    ///         (input, probe)
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step_while(|| probe.less_than(input.time()));
    ///     }
    /// }).unwrap();
    /// ```
    fn probe(&self) -> Handle<G::Timestamp>;

    /// Inserts a progress probe in a stream.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::Scope;
    /// use timely::dataflow::operators::{Input, Probe, Inspect};
    /// use timely::dataflow::operators::probe::Handle;
    /// use timely::progress::timestamp::RootTimestamp;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut probe = Handle::new();
    ///     let mut input = worker.dataflow(|scope| {
    ///         let (input, stream) = scope.new_input();
    ///         stream.probe_with(&mut probe)
    ///               .inspect(|x| println!("hello {:?}", x));
    ///
    ///         input
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step_while(|| probe.less_than(input.time()));
    ///     }
    /// }).unwrap();
    /// ```
    fn probe_with(&self, handle: &mut Handle<G::Timestamp>) -> Stream<G, D>;
}

impl<G: Scope, D: Data> Probe<G, D> for Stream<G, D> {
    fn probe(&self) -> Handle<G::Timestamp> {

        // the frontier is shared state; scope updates, handle reads.
        let handle = Handle::new();

        let mut scope = self.scope();   // clones the scope
        let channel_id = scope.new_identifier();

        let (sender, receiver) = Pipeline.connect(&mut scope, channel_id);
        let (targets, registrar) = Tee::<G::Timestamp,D>::new();
        let operator = Operator {
            input: PullCounter::new(receiver),
            output: PushBuffer::new(PushCounter::new(targets, Rc::new(RefCell::new(CountMap::new())))),
            frontier: handle.frontier.clone(),
        };

        let index = scope.add_operator(operator);
        self.connect_to(Target { index: index, port: 0 }, sender, channel_id);
        Stream::new(Source { index: index, port: 0 }, registrar, scope);
        handle
    }
    fn probe_with(&self, handle: &mut Handle<G::Timestamp>) -> Stream<G, D> {

        let mut scope = self.scope();   // clones the scope
        let channel_id = scope.new_identifier();

        let (sender, receiver) = Pipeline.connect(&mut scope, channel_id);
        let (targets, registrar) = Tee::<G::Timestamp,D>::new();
        let operator = Operator {
            input: PullCounter::new(receiver),
            output: PushBuffer::new(PushCounter::new(targets, Rc::new(RefCell::new(CountMap::new())))),
            frontier: handle.frontier.clone(),
        };

        let index = scope.add_operator(operator);
        self.connect_to(Target { index: index, port: 0 }, sender, channel_id);
        Stream::new(Source { index: index, port: 0 }, registrar, scope)
    }
}

/// Reports information about progress at the probe.
pub struct Handle<T:Timestamp> {
    frontier: Rc<RefCell<MutableAntichain<T>>>
}

impl<T: Timestamp> Handle<T> {
    /// returns true iff the frontier is strictly less than `time`.
    #[inline] pub fn less_than(&self, time: &T) -> bool { self.frontier.borrow().less_than(time) }
    /// returns true iff the frontier is less than or equal to `time`.
    #[inline] pub fn less_equal(&self, time: &T) -> bool { self.frontier.borrow().less_equal(time) }
    /// returns true iff the frontier is empty.
    #[inline] pub fn done(&self) -> bool { self.frontier.borrow().elements().len() == 0 }
    /// Allocates a new handle.
    #[inline] pub fn new() -> Self { Handle { frontier: Rc::new(RefCell::new(MutableAntichain::new())) } }

    /// Invokes a method on the frontier, returning its result.
    ///
    /// This method allows inspection of the frontier, which cannot be returned by reference as
    /// it is on the other side of a `RefCell`.
    ///
    /// #Examples
    ///
    /// ```
    /// use timely::dataflow::operators::probe::Handle;
    ///
    /// let handle = Handle::<usize>::new();
    /// let frontier = handle.with_frontier(|frontier| frontier.to_vec());
    /// ```
    #[inline]
    pub fn with_frontier<R, F: FnMut(&[T])->R>(&self, mut function: F) -> R {
        function(self.frontier.borrow().elements())
    }
}

impl<T: Timestamp> Clone for Handle<T> {
    fn clone(&self) -> Self {
        Handle {
            frontier: self.frontier.clone()
        }
    }
}

struct Operator<T:Timestamp, D: Data> {
    input: PullCounter<T, D>,
    output: PushBuffer<T, D, PushCounter<T, D, Tee<T, D>>>,
    frontier: Rc<RefCell<MutableAntichain<T>>>
}

impl<T:Timestamp, D: Data> Operate<T> for Operator<T, D> {
    fn name(&self) -> String { "Probe".to_owned() }
    fn inputs(&self) -> usize { 1 }
    fn outputs(&self) -> usize { 1 }

    // we need to set the initial value of the frontier
    fn set_external_summary(&mut self, _: Vec<Vec<Antichain<T::Summary>>>, counts: &mut [CountMap<T>]) {
        let mut borrow = self.frontier.borrow_mut();
        while let Some((time, delta)) = counts[0].pop() {
            borrow.update(&time, delta);
        }
    }

    // each change to the frontier should be shared
    fn push_external_progress(&mut self, counts: &mut [CountMap<T>]) {
        let mut borrow = self.frontier.borrow_mut();
        while let Some((time, delta)) = counts[0].pop() {
            borrow.update(&time, delta);
        }
    }

    // the scope does nothing. this is actually a problem, because "reachability" assumes all messages on each edge.
    fn pull_internal_progress(&mut self, consumed: &mut [CountMap<T>], _: &mut [CountMap<T>], produced: &mut [CountMap<T>]) -> bool {

        while let Some((time, data)) = self.input.next() {
            self.output.session(time).give_content(data);
        }

        self.output.cease();

        // extract what we know about progress from the input and output adapters.
        self.input.pull_progress(&mut consumed[0]);
        self.output.inner().pull_progress(&mut produced[0]);

        false
    }
}

#[cfg(test)]
mod tests {

    use ::Configuration;
    use ::progress::timestamp::RootTimestamp;
    use dataflow::operators::{Input, Probe};

    #[test]
    fn probe() {

        // initializes and runs a timely dataflow computation
        ::execute(Configuration::Thread, |worker| {

            // create a new input, and inspect its output
            let (mut input, probe) = worker.dataflow(move |scope| {
                let (input, stream) = scope.new_input::<String>();
                (input, stream.probe())
            });

            // introduce data and watch!
            for round in 0..10 {
                assert!(!probe.done());
                assert!(probe.less_equal(&RootTimestamp::new(round)));
                assert!(!probe.less_than(&RootTimestamp::new(round)));
                assert!(probe.less_than(&RootTimestamp::new(round + 1)));
                input.advance_to(round + 1);
                worker.step();
            }

            // seal the input
            input.close();

            // finish off any remaining work
            worker.step();
            assert!(probe.done());
        }).unwrap();
    }

}
<|endoftext|>


<commit_before>use std::{fs::File, io::BufReader, io::prelude::*, path::Path, string::String, vec::Vec};

use json;
use tiled;
use tiled::Map;

use crate::critter::CritterData;
use crate::game::constants::{CHARACTER_BUF_LENGTH, CHARACTER_JSON_PATH, ZOMBIE_JSON_PATH};

pub fn load_map_file(filename: &str) -> Map {
  let file = match File::open(&Path::new(&filename)) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let reader = BufReader::new(file);
  match tiled::parse(reader) {
    Ok(m) => m,
    Err(e) => panic!("Map parse error {:?}", e)
  }
}

pub fn get_map_tile(map: &Map, layer_index: usize, x: usize, y: usize) -> u32 {
  let layer = match map.layers.get(layer_index) {
    None => panic!("Layer_index value out of index {:?}", map.layers),
    Some(l) => l
  };
  let y_index = match layer.tiles.iter().rev().nth(y) {
    None => panic!("X value out of index {:?}", map.layers[0]),
    Some(x) => x
  };
  match y_index.get(x) {
    None => panic!("Y value out of index {:?}", layer.tiles[y]),
    Some(val) => *val
  }
}

fn read_sprite_file(filename: &str) -> String {
  let path = Path::new(&filename);
  let mut file = match File::open(&path) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let mut buf = String::new();
  match file.read_to_string(&mut buf) {
    Ok(_) => buf,
    Err(e) => panic!("read file {} error {}", filename, e),
  }
}

pub fn load_character() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(CHARACTER_BUF_LENGTH + 64);
  let character_json = read_sprite_file(CHARACTER_JSON_PATH);
  let character = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character {} parse error {:?}", CHARACTER_JSON_PATH, e),
  };
  for x in 0..16 {
    for y in 0..14 {
      let key = &format!("run_{}_{}", x, y);
      sprites.push(CritterData::new([
        character["frames"][key]["frame"]["x"].as_f32().unwrap(),
        character["frames"][key]["frame"]["y"].as_f32().unwrap(),
        character["frames"][key]["frame"]["w"].as_f32().unwrap(),
        character["frames"][key]["frame"]["h"].as_f32().unwrap(),
      ]));
    }
  }

  for x in 0..15 {
    for y in 0..4 {
      let key = &format!("fire_{}_{}", x, y);
      sprites.push(CritterData::new([
        character["frames"][key]["frame"]["x"].as_f32().unwrap(),
        character["frames"][key]["frame"]["y"].as_f32().unwrap(),
        character["frames"][key]["frame"]["w"].as_f32().unwrap(),
        character["frames"][key]["frame"]["h"].as_f32().unwrap(),
      ]));
    }
  }

  sprites
}

pub fn load_zombie() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(256);
  let zombie_json = read_sprite_file(ZOMBIE_JSON_PATH);
  let zombie = match json::parse(&zombie_json) {
    Ok(res) => res,
    Err(e) => panic!("Zombie {} parse error {:?}", ZOMBIE_JSON_PATH, e),
  };
  for x in 0..7 {
    for y in 0..7 {
      let key = &format!("critical_{}_{}", x, y);
      sprites.push(CritterData::new([
        zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["h"].as_f32().unwrap()
      ]));
    }
  }
  for x in 0..7 {
    for y in 0..5 {
      let key = &format!("normal_{}_{}", x, y);
      sprites.push(CritterData::new([
        zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["h"].as_f32().unwrap()
      ]));
    }
  }
  for x in 0..7 {
    for y in 0..4 {
      let key = &format!("still_{}_{}", x, y);
      sprites.push(CritterData::new([
        zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["h"].as_f32().unwrap()
      ]));
    }
  }

  for x in 0..7 {
    for y in 0..7 {
      let key = &format!("walk_{}_{}", x, y);
      sprites.push(CritterData::new([
        zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["h"].as_f32().unwrap()
      ]));
    }
  }
  sprites
}
<commit_msg>Remove duplicated code<commit_after>use std::{fs::File, io::BufReader, io::prelude::*, path::Path, string::String, vec::Vec};

use json;
use json::JsonValue;
use tiled;
use tiled::Map;

use crate::critter::CritterData;
use crate::game::constants::{CHARACTER_BUF_LENGTH, CHARACTER_JSON_PATH, ZOMBIE_JSON_PATH};

pub fn load_map_file(filename: &str) -> Map {
  let file = match File::open(&Path::new(&filename)) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let reader = BufReader::new(file);
  match tiled::parse(reader) {
    Ok(m) => m,
    Err(e) => panic!("Map parse error {:?}", e)
  }
}

pub fn get_map_tile(map: &Map, layer_index: usize, x: usize, y: usize) -> u32 {
  let layer = match map.layers.get(layer_index) {
    None => panic!("Layer_index value out of index {:?}", map.layers),
    Some(l) => l
  };
  let y_index = match layer.tiles.iter().rev().nth(y) {
    None => panic!("X value out of index {:?}", map.layers[0]),
    Some(x) => x
  };
  match y_index.get(x) {
    None => panic!("Y value out of index {:?}", layer.tiles[y]),
    Some(val) => *val
  }
}

fn read_sprite_file(filename: &str) -> String {
  let path = Path::new(&filename);
  let mut file = match File::open(&path) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let mut buf = String::new();
  match file.read_to_string(&mut buf) {
    Ok(_) => buf,
    Err(e) => panic!("read file {} error {}", filename, e),
  }
}

pub fn load_character() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(CHARACTER_BUF_LENGTH + 64);
  let character_json = read_sprite_file(CHARACTER_JSON_PATH);
  let character = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character {} parse error {:?}", CHARACTER_JSON_PATH, e),
  };

  let frame_data = |character: &JsonValue, key: &String| -> [f32; 4] {
    [
      character["frames"][key]["frame"]["x"].as_f32().unwrap(),
      character["frames"][key]["frame"]["y"].as_f32().unwrap(),
      character["frames"][key]["frame"]["w"].as_f32().unwrap(),
      character["frames"][key]["frame"]["h"].as_f32().unwrap(),
    ]
  };

  for x in 0..16 {
    for y in 0..14 {
      let key = &format!("run_{}_{}", x, y);
      sprites.push(CritterData::new(frame_data(&character, key)));
    }
  }

  for x in 0..15 {
    for y in 0..4 {
      let key = &format!("fire_{}_{}", x, y);
      sprites.push(CritterData::new(frame_data(&character, key)));
    }
  }

  sprites
}

pub fn load_zombie() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(256);
  let zombie_json = read_sprite_file(ZOMBIE_JSON_PATH);
  let zombie = match json::parse(&zombie_json) {
    Ok(res) => res,
    Err(e) => panic!("Zombie {} parse error {:?}", ZOMBIE_JSON_PATH, e),
  };

  let frame_data = |zombie: &JsonValue, key: &String| -> [f32; 4] {
    [
      zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
      zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
      zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
      zombie["frames"][key]["frame"]["h"].as_f32().unwrap(),
    ]
  };

  for x in 0..7 {
    for y in 0..7 {
      let key = &format!("critical_{}_{}", x, y);
      sprites.push(CritterData::new(frame_data(&zombie, key)));
    }
  }
  for x in 0..7 {
    for y in 0..5 {
      let key = &format!("normal_{}_{}", x, y);
      sprites.push(CritterData::new(frame_data(&zombie, key)));
    }
  }
  for x in 0..7 {
    for y in 0..4 {
      let key = &format!("still_{}_{}", x, y);
      sprites.push(CritterData::new(frame_data(&zombie, key)));
    }
  }

  for x in 0..7 {
    for y in 0..7 {
      let key = &format!("walk_{}_{}", x, y);
      sprites.push(CritterData::new(frame_data(&zombie, key)));
    }
  }
  sprites
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! Parser for Intecture data files.
//!
//! # Examples
//!
//! ```no_run
//! ```

mod condition;
// pub mod ffi;

use error::{Error, Result};
use serde_json::{self, Value};
use std::collections::BTreeMap;
use std::fs;
use std::path::Path;

/// Parser for Intecture data files.
pub struct DataParser;

impl DataParser {
    /// Open a new file and recursively parse its contents.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// ```
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Value> {
        let file = try!(DataFile::new(path));
        Ok(try!(file.merge(Value::Null)))
    }
}

struct DataFile {
    v: Value,
}

impl DataFile {
    fn new<P: AsRef<Path>>(path: P) -> Result<DataFile> {
        let mut fh = try!(fs::File::open(path.as_ref()));
        let data: Value = try!(serde_json::from_reader(&mut fh));

        if !data.is_object() {
            Err(Error::Generic("Value is not an object".into()))
        } else {
            Ok(DataFile {
                v: data,
            })
        }
    }

    fn dependencies(&self) -> Result<Vec<DataFile>> {
        let mut deps = Vec::new();

        if let Some(inc) = self.v.find("_include") {
            if !inc.is_array() {
                return Err(Error::Generic("Value of `_include` is not an array".into()));
            }

            // Loop in reverse order to get lowest importance first
            for i in inc.as_array().unwrap().iter().rev() {
                deps.push(try!(DataFile::new(i.as_str().unwrap())));
            }
        }

        Ok(deps)
    }

    fn merge(self, mut last_value: Value) -> Result<Value> {
        for dep in try!(self.dependencies()) {
            last_value = try!(dep.merge(last_value));
        }

        let lv_clone = last_value.clone();
        Ok(try!(Self::merge_values(self.v, last_value, &lv_clone)))
    }

    fn merge_values(into: Value, mut from: Value, parent_from: &Value) -> Result<Value> {
        match into {
            Value::Null |
            Value::Bool(_) |
            Value::I64(_) |
            Value::U64(_) |
            Value::F64(_) |
            Value::String(_) => Ok(into),
            Value::Array(mut a) => {
                if from.is_array() {
                    a.append(from.as_array_mut().unwrap());
                } else {
                    a.push(from);
                }

                Ok(Value::Array(a))
            },
            Value::Object(o) => {
                let mut new: BTreeMap<String, Value> = BTreeMap::new();

                for (mut key, mut value) in o {
                    if key.ends_with("?") || key.ends_with("?!") {
                        if key.pop().unwrap() == '!' {
                            key.pop();
                            key.push('!');
                        }

                        value = try!(Self::query_value(&parent_from, value)).unwrap_or(Value::Null);
                    }

                    if key.ends_with("!") {
                        key.pop();
                    }
                    else if let Some(o1) = from.find(&key) {
                        value = try!(Self::merge_values(value, o1.clone(), &parent_from));
                    }

                    new.insert(key, value);
                }

                // Insert any missing values
                if let Some(o1) = from.as_object() {
                    for (key, value) in o1 {
                        if !new.contains_key(key) {
                            new.insert(key.clone(), value.clone());
                        }
                    }
                }

                Ok(Value::Object(new))
            }
        }
    }

    fn query_value(data: &Value, value: Value) -> Result<Option<Value>> {
        match value {
            Value::Array(a) => {
                for opt in a {
                    if let Some(v) = try!(Self::query_value(data, opt)) {
                        return Ok(Some(v));
                    }
                }
            },
            Value::Object(mut o) => {
                if let Some(v) = o.remove("_") {
                    if let Some(q) = o.get("?") {
                        match *q {
                            Value::String(ref s) => {
                                if try!(condition::eval(data, s)) {
                                    return Ok(Some(v));
                                }
                            },
                            _ => return Err(Error::Generic("Query must be string".into())),
                        };
                    }

                    return Ok(Some(v));
                }
            },
            _ => return Ok(Some(value)),
        }

        Ok(None)
    }
}

#[cfg(test)]
mod tests {
    use serde_json::{self, Value};
    use std::fs::File;
    use std::io::Write;
    use std::path::PathBuf;
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn test_parser() {
        let tempdir = TempDir::new("parser_test").unwrap();
        let mut path = tempdir.path().to_owned();
        let expected_value = create_data(&mut path);

        path.push("top.json");
        let value = DataParser::open(&path).unwrap();

        assert_eq!(value, expected_value);
    }

    fn create_data(path: &mut PathBuf) -> Value {
        path.push("top.json");
        let mut fh = File::create(&path).unwrap();
        path.pop();
        fh.write_all(format!("{{
            \"a\": 1,
            \"payload\": {{
                \"b\": [ 1, 2 ],
                \"c?\": [
                    {{
                        \"_\": [ 6, 7 ],
                        \"?\": \"/variable = false\"
                    }},
                    {{
                        \"_\": [ 8, 9 ]
                    }}
                ],
                \"d\": [ 123 ]
            }},
            \"variable\": {{
                \"one!\": true,
                \"two\": false
            }},
            \"_include\": [
                \"{0}/middle.json\",
                \"{0}/bottom.json\"
            ]
        }}", &path.to_str().unwrap()).as_bytes()).unwrap();

        path.push("middle.json");
        let mut fh = File::create(&path).unwrap();
        path.pop();
        fh.write_all(b"{
            \"payload\": {
                \"b!\": [ 3, 4 ],
                \"d\": [ 987 ]
            },
            \"variable\": false,
            \"d\": 4
        }").unwrap();

        path.push("bottom.json");
        let mut fh = File::create(&path).unwrap();
        path.pop();
        fh.write_all(b"{
            \"moo\": \"cow\",
            \"payload\": {
                \"b\": [ 5 ],
                \"d\": [ 999 ]
            }
        }").unwrap();

        serde_json::from_str(&format!("{{
            \"_include\": [
                \"{0}/middle.json\",
                \"{0}/bottom.json\"
            ],
            \"a\": 1,
            \"d\": 4,
            \"moo\": \"cow\",
            \"payload\": {{
                \"b\": [ 1, 2, 3, 4 ],
                \"c\": [ 6, 7 ],
                \"d\": [ 123, 987, 999 ]
            }},
            \"variable\": {{
                \"one\": true,
                \"two\": false
            }}
        }}", &path.to_str().unwrap())).unwrap()
    }
}
<commit_msg>Fix bug with merging arrays where merging would not happen recursively<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! Parser for Intecture data files.
//!
//! # Examples
//!
//! ```no_run
//! ```

mod condition;
// pub mod ffi;

use error::{Error, Result};
use serde_json::{self, Value};
use std::collections::BTreeMap;
use std::fs;
use std::path::Path;

/// Parser for Intecture data files.
pub struct DataParser;

impl DataParser {
    /// Open a new file and recursively parse its contents.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// ```
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Value> {
        let file = try!(DataFile::new(path));
        Ok(try!(file.merge(Value::Null)))
    }
}

struct DataFile {
    v: Value,
}

impl DataFile {
    fn new<P: AsRef<Path>>(path: P) -> Result<DataFile> {
        let mut fh = try!(fs::File::open(path.as_ref()));
        let data: Value = try!(serde_json::from_reader(&mut fh));

        if !data.is_object() {
            Err(Error::Generic("Value is not an object".into()))
        } else {
            Ok(DataFile {
                v: data,
            })
        }
    }

    fn dependencies(&self) -> Result<Vec<DataFile>> {
        let mut deps = Vec::new();

        if let Some(inc) = self.v.find("_include") {
            if !inc.is_array() {
                return Err(Error::Generic("Value of `_include` is not an array".into()));
            }

            // Loop in reverse order to get lowest importance first
            for i in inc.as_array().unwrap().iter().rev() {
                deps.push(try!(DataFile::new(i.as_str().unwrap())));
            }
        }

        Ok(deps)
    }

    fn merge(self, mut last_value: Value) -> Result<Value> {
        for dep in try!(self.dependencies()) {
            last_value = try!(dep.merge(last_value));
        }

        let lv_clone = last_value.clone();
        Ok(try!(Self::merge_values(self.v, last_value, &lv_clone)))
    }

    fn merge_values(into: Value, mut from: Value, parent_from: &Value) -> Result<Value> {
        match into {
            Value::Null |
            Value::Bool(_) |
            Value::I64(_) |
            Value::U64(_) |
            Value::F64(_) |
            Value::String(_) => Ok(into),
            Value::Array(mut a) => {
                if from.is_array() {
                    a.append(from.as_array_mut().unwrap());
                } else {
                    a.push(from);
                }

                let mut b = Vec::new();

                for v in a {
                    b.push(try!(Self::merge_values(v, Value::Null, parent_from)));
                }

                Ok(Value::Array(b))
            },
            Value::Object(o) => {
                let mut new: BTreeMap<String, Value> = BTreeMap::new();

                for (mut key, mut value) in o {
                    if key.ends_with("?") || key.ends_with("?!") {
                        if key.pop().unwrap() == '!' {
                            key.pop();
                            key.push('!');
                        }

                        value = try!(Self::query_value(&parent_from, value)).unwrap_or(Value::Null);
                    }

                    if key.ends_with("!") {
                        key.pop();
                    }
                    else if let Some(o1) = from.find(&key) {
                        value = try!(Self::merge_values(value, o1.clone(), &parent_from));
                    }

                    new.insert(key, value);
                }

                // Insert any missing values
                if let Some(o1) = from.as_object() {
                    for (key, value) in o1 {
                        if !new.contains_key(key) {
                            new.insert(key.clone(), value.clone());
                        }
                    }
                }

                Ok(Value::Object(new))
            }
        }
    }

    fn query_value(data: &Value, value: Value) -> Result<Option<Value>> {
        match value {
            Value::Array(a) => {
                for opt in a {
                    if let Some(v) = try!(Self::query_value(data, opt)) {
                        return Ok(Some(v));
                    }
                }
            },
            Value::Object(mut o) => {
                if let Some(v) = o.remove("_") {
                    if let Some(q) = o.get("?") {
                        match *q {
                            Value::String(ref s) => {
                                if try!(condition::eval(data, s)) {
                                    return Ok(Some(v));
                                }
                            },
                            _ => return Err(Error::Generic("Query must be string".into())),
                        };
                    }

                    return Ok(Some(v));
                }
            },
            _ => return Ok(Some(value)),
        }

        Ok(None)
    }
}

#[cfg(test)]
mod tests {
    use serde_json::{self, Value};
    use std::fs::File;
    use std::io::Write;
    use std::path::PathBuf;
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn test_parser() {
        let tempdir = TempDir::new("parser_test").unwrap();
        let mut path = tempdir.path().to_owned();
        let expected_value = create_data(&mut path);

        path.push("top.json");
        let value = DataParser::open(&path).unwrap();

        assert_eq!(value, expected_value);
    }

    fn create_data(path: &mut PathBuf) -> Value {
        path.push("top.json");
        let mut fh = File::create(&path).unwrap();
        path.pop();
        fh.write_all(format!("{{
            \"a\": 1,
            \"payload\": {{
                \"b\": [ 1, 2 ],
                \"c?\": [
                    {{
                        \"_\": [ 6, 7 ],
                        \"?\": \"/variable = false\"
                    }},
                    {{
                        \"_\": [ 8, 9 ]
                    }}
                ],
                \"d\": [ 123 ]
            }},
            \"variable\": {{
                \"one!\": true,
                \"two\": false
            }},
            \"_include\": [
                \"{0}/middle.json\",
                \"{0}/bottom.json\"
            ]
        }}", &path.to_str().unwrap()).as_bytes()).unwrap();

        path.push("middle.json");
        let mut fh = File::create(&path).unwrap();
        path.pop();
        fh.write_all(b"{
            \"payload\": {
                \"b!\": [ 3, 4 ],
                \"d\": [ 987 ]
            },
            \"variable\": false,
            \"d\": 4
        }").unwrap();

        path.push("bottom.json");
        let mut fh = File::create(&path).unwrap();
        path.pop();
        fh.write_all(b"{
            \"moo\": \"cow\",
            \"payload\": {
                \"b\": [ 5 ],
                \"d\": [ 999 ]
            }
        }").unwrap();

        serde_json::from_str(&format!("{{
            \"_include\": [
                \"{0}/middle.json\",
                \"{0}/bottom.json\"
            ],
            \"a\": 1,
            \"d\": 4,
            \"moo\": \"cow\",
            \"payload\": {{
                \"b\": [ 1, 2, 3, 4 ],
                \"c\": [ 6, 7 ],
                \"d\": [ 123, 987, 999 ]
            }},
            \"variable\": {{
                \"one\": true,
                \"two\": false
            }}
        }}", &path.to_str().unwrap())).unwrap()
    }
}
<|endoftext|>