<commit_before>use super::core;
use super::elaborate::{self, ElabCx, LocalElabCx};
use super::error_reporting::Report;
use super::parser;
use super::ast::{self, SourceMap};
use super::typeck::{self, LocalCx};

use std::io;
use std::path::PathBuf;
use readline;

const HELP_MESSAGE: &'static str = r#"
Commands:
    :help        Show this message
    :type <term> Infer the type of <term>
    :quit        Exit
"#;

pub struct Repl {
    elab_cx: ElabCx,
    root_file: Option<PathBuf>,
}

// impl From<parser::Error> for Error {
//     fn from(err: parser::Error) -> Error {
//         Error::Parser(err)
//     }
// }
//

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<elaborate::Error> for Error {
    fn from(err: elaborate::Error) -> Error {
        Error::Elaborator(err)
    }
}

impl From<typeck::Error> for Error {
    fn from(err: typeck::Error) -> Error {
        Error::TypeCk(err)
    }
}

impl From<parser::Error> for Error {
    fn from(err: parser::Error) -> Error {
        Error::Parser(err)
    }
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Elaborator(elaborate::Error),
    UnknownCommand(String),
    TypeCk(typeck::Error),
    Parser(parser::Error),
}

#[derive(Debug)]
enum Command {
    Quit,
    Reload,
    Unknown(String),
    TypeOf(String),
    Help,
}

pub enum Cont {
    Quit,
    Done,
}

impl Repl {
    pub fn from_path(file: &Option<PathBuf>) -> Result<Repl, Error> {
        match file {
            &None => {
                let ecx = ElabCx::from_module(ast::Module::empty(), SourceMap::empty());
                Ok(Repl {
                    elab_cx: ecx,
                    root_file: None
                })
            }
            &Some(ref file_path) => {
                let parser = try!(parser::from_file(file_path));
                let module = try!(parser.parse());

                let mut ecx = ElabCx::from_module(module, parser.source_map.clone());

                let emodule = try!(ecx.elaborate_module(file_path));

                {
                    let main = try!(ecx.ty_cx.get_main_body());
                    let result = try!(ecx.ty_cx.eval(main));
                    println!("main={}", result);
                }

                Ok(Repl {
                    elab_cx: ecx,
                    root_file: file.clone(),
                })
            }
        }
    }

    /// Starts the read-eval-print-loop for querying the language.
    pub fn start(mut self) -> Result<(), Error> {
        loop {
            // First we grab a line ...
            let input = match readline::readline("hubris> ") {
                None => {
                    println!("");
                    break;
                }
                Some(input) => input,
            };

            // Add it to the history
            readline::add_history(input.as_ref());

            match self.repl_interation(input) {
                // please make me look better
                Err(e) => println!("repl error: {:?}", e),
                Ok(cont) => {
                    match cont {
                        Cont::Quit => break,
                        Cont::Done => {}
                    }
                }
            }
        }

        Ok(())
    }

    pub fn repl_interation(&mut self, input: String) -> Result<Cont, Error> {
        if input.len() <= 0 {
            // do nothing
        } else if &input[0..1] == ":" {
            let cmd = self.parse_command(&input[1..]);
            match cmd {
                Command::Quit => return Ok(Cont::Quit),
                Command::Reload => panic!("unsupported command"),
                Command::Unknown(u) => return Err(Error::UnknownCommand(u)),
                Command::TypeOf(t) => {
                    let term = try!(self.preprocess_term(t));
                    println!("{}", try!(self.type_check_term(&term)));
                }
                Command::Help => println!("{}", HELP_MESSAGE),
            }
        } else {
            try!(self.handle_input(input.to_string()));
        }

        Ok(Cont::Done)
    }

    fn preprocess_term(&mut self, source: String) -> Result<core::Term, Error> {
        let parser = parser::from_string(source).unwrap();
        let term = try!(parser.parse_term());

        let mut lcx = LocalElabCx::from_elab_cx(&mut self.elab_cx);
        let term = try!(lcx.elaborate_term(term));

        Ok(term)
    }

    fn type_check_term(&mut self, term: &core::Term) -> Result<core::Term, Error> {
        let mut ltycx = LocalCx::from_cx(&self.elab_cx.ty_cx);
        let term = try!(ltycx.type_infer_term(&term));

        Ok(term)
    }

    fn handle_input(&mut self, source: String) -> Result<(), Error> {
        let term = try!(self.preprocess_term(source));
        let ty = try!(self.type_check_term(&term));
        println!("{} : {}", term, ty);
        println!("{}", try!(self.elab_cx.ty_cx.eval(&term)));
        Ok(())
    }

    fn parse_command(&self, command_text: &str) -> Command {
        if command_text == "quit" {
            Command::Quit
        } else if command_text == "reload" {
            Command::Reload
        } else if &command_text[0..4] == "type" {
            Command::TypeOf(command_text[0..4].to_string())
        } else if &command_text[0..1] == "t" {
            Command::TypeOf(command_text[1..].to_string())
        } else if &command_text[0..4] == "help" {
            Command::Help
        } else {
            Command::Unknown(command_text.to_string())
        }
    }
}

// impl Report for Error {
//     type Context = ElabCx;
//
//     fn report<O: Write>(cx: &Self::Context,
//                          mut out: Box<Terminal<Output = O>>,
//                          error: Self)
//                          -> TResult<()> {
//         match error {
//             Error::TypeCk(ty_ck) => panic!(),
//             _ => panic!(),
//         }
//     }
// }
<commit_msg>Make repl more usable with command prefixes<commit_after>use super::core;
use super::elaborate::{self, ElabCx, LocalElabCx};
use super::error_reporting::Report;
use super::parser;
use super::ast::{self, SourceMap};
use super::typeck::{self, LocalCx};

use std::io;
use std::path::PathBuf;
use readline;

const HELP_MESSAGE: &'static str = r#"
Commands:
    :help        Show this message
    :type <term> Infer the type of <term>
    :quit        Exit
"#;

pub struct Repl {
    elab_cx: ElabCx,
    root_file: Option<PathBuf>,
}

// impl From<parser::Error> for Error {
//     fn from(err: parser::Error) -> Error {
//         Error::Parser(err)
//     }
// }
//

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<elaborate::Error> for Error {
    fn from(err: elaborate::Error) -> Error {
        Error::Elaborator(err)
    }
}

impl From<typeck::Error> for Error {
    fn from(err: typeck::Error) -> Error {
        Error::TypeCk(err)
    }
}

impl From<parser::Error> for Error {
    fn from(err: parser::Error) -> Error {
        Error::Parser(err)
    }
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Elaborator(elaborate::Error),
    UnknownCommand(String),
    TypeCk(typeck::Error),
    Parser(parser::Error),
}

#[derive(Debug)]
enum Command {
    Quit,
    Reload,
    Unknown(String),
    TypeOf(String),
    Help,
}

pub enum Cont {
    Quit,
    Done,
}

fn split_command(command_text: &str) -> (&str, &str) {

    for (i, c) in command_text.char_indices() {
        if c.is_whitespace() {
            return command_text.split_at(i);
        }
    }

    (command_text, "")
}

impl Repl {
    pub fn from_path(file: &Option<PathBuf>) -> Result<Repl, Error> {
        match file {
            &None => {
                let ecx = ElabCx::from_module(ast::Module::empty(), SourceMap::empty());
                Ok(Repl {
                    elab_cx: ecx,
                    root_file: None
                })
            }
            &Some(ref file_path) => {
                let parser = try!(parser::from_file(file_path));
                let module = try!(parser.parse());

                let mut ecx = ElabCx::from_module(module, parser.source_map.clone());

                let emodule = try!(ecx.elaborate_module(file_path));

                {
                    let main = try!(ecx.ty_cx.get_main_body());
                    let result = try!(ecx.ty_cx.eval(main));
                    println!("main={}", result);
                }

                Ok(Repl {
                    elab_cx: ecx,
                    root_file: file.clone(),
                })
            }
        }
    }

    /// Starts the read-eval-print-loop for querying the language.
    pub fn start(mut self) -> Result<(), Error> {
        loop {
            // First we grab a line ...
            let input = match readline::readline("hubris> ") {
                None => {
                    println!("");
                    break;
                }
                Some(input) => input,
            };

            // Add it to the history
            readline::add_history(input.as_ref());

            match self.repl_interation(input) {
                // please make me look better
                Err(e) => println!("repl error: {:?}", e),
                Ok(cont) => {
                    match cont {
                        Cont::Quit => break,
                        Cont::Done => {}
                    }
                }
            }
        }

        Ok(())
    }

    pub fn repl_interation(&mut self, input: String) -> Result<Cont, Error> {
        if input.len() <= 0 {
            // do nothing
        } else if &input[0..1] == ":" {
            let cmd = self.parse_command(&input[1..]);
            match cmd {
                Command::Quit => return Ok(Cont::Quit),
                Command::Reload => panic!("unsupported command"),
                Command::Unknown(u) => return Err(Error::UnknownCommand(u)),
                Command::TypeOf(t) => {
                    let term = try!(self.preprocess_term(t));
                    println!("{}", try!(self.type_check_term(&term)));
                }
                Command::Help => println!("{}", HELP_MESSAGE),
            }
        } else {
            try!(self.handle_input(input.to_string()));
        }

        Ok(Cont::Done)
    }

    fn preprocess_term(&mut self, source: String) -> Result<core::Term, Error> {
        let parser = parser::from_string(source).unwrap();
        let term = try!(parser.parse_term());

        let mut lcx = LocalElabCx::from_elab_cx(&mut self.elab_cx);
        let term = try!(lcx.elaborate_term(term));

        Ok(term)
    }

    fn type_check_term(&mut self, term: &core::Term) -> Result<core::Term, Error> {
        let mut ltycx = LocalCx::from_cx(&self.elab_cx.ty_cx);
        let term = try!(ltycx.type_infer_term(&term));

        Ok(term)
    }

    fn handle_input(&mut self, source: String) -> Result<(), Error> {
        let term = try!(self.preprocess_term(source));
        let ty = try!(self.type_check_term(&term));
        println!("{} : {}", term, ty);
        println!("{}", try!(self.elab_cx.ty_cx.eval(&term)));
        Ok(())
    }

    fn parse_command(&self, command_text: &str) -> Command {
        let (command, arg) = split_command(command_text);

        if command == "" {
            Command::Unknown(command_text.to_string())
        } else if "quit".starts_with(command) {
            Command::Quit
        } else if "reload".starts_with(command) {
            Command::Reload
        } else if "type".starts_with(command) {
            Command::TypeOf(arg.to_string())
        } else if "help".starts_with(command) {
            Command::Help
        } else {
            Command::Unknown(command_text.to_string())
        }
    }
}

// impl Report for Error {
//     type Context = ElabCx;
//
//     fn report<O: Write>(cx: &Self::Context,
//                          mut out: Box<Terminal<Output = O>>,
//                          error: Self)
//                          -> TResult<()> {
//         match error {
//             Error::TypeCk(ty_ck) => panic!(),
//             _ => panic!(),
//         }
//     }
// }
<|endoftext|>


<commit_before>use arch::ArchDetail;
use std::ffi::CStr;
use std::slice;
use std::str;
use std::fmt::{self, Debug, Display, Error, Formatter};
use capstone_sys::*;
use constants::Arch;

/// Representation of the array of instructions returned by disasm
#[derive(Debug)]
pub struct Instructions<'a>(&'a mut [cs_insn]);

/// Integer type used in `InsnId`
pub type InsnIdInt = u32;

/// Represents an instruction id, which may architecture-specific.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct InsnId(pub InsnIdInt);

/// Integer type used in `InsnGroupId`
pub type InsnGroupIdInt = u8;

/// Represents the group an instruction belongs to, which may be architecture-specific.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct InsnGroupId(pub InsnGroupIdInt);

/// Integer type used in `RegId`
pub type RegIdInt = u16;

/// Represents an register id, which is architecture-specific.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct RegId(pub RegIdInt);

impl<'a> Instructions<'a> {
    pub(crate) unsafe fn from_raw_parts(ptr: *mut cs_insn, len: usize) -> Instructions<'a> {
        Instructions(slice::from_raw_parts_mut(ptr, len))
    }

    pub(crate) fn new_empty() -> Instructions<'a> {
        Instructions(&mut [])
    }

    /// Get number of instructions
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Iterator over instructions
    pub fn iter<'b>(&'a self) -> InstructionIterator<'b>
    where
        'a: 'b,
    {
        let iter = self.0.iter();
        InstructionIterator(iter)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl<'a> Drop for Instructions<'a> {
    fn drop(&mut self) {
        if self.len() > 0 {
            unsafe {
                cs_free(self.0.as_mut_ptr(), self.len());
            }
        }
    }
}

/// An iterator over the instructions returned by disasm
///
/// This is currently the only supported interface for reading them.
pub struct InstructionIterator<'a>(slice::Iter<'a, cs_insn>);

impl<'a> Iterator for InstructionIterator<'a> {
    type Item = Insn;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|x| Insn(*x))
    }
}

/// A wrapper for the raw capstone-sys instruction
pub struct Insn(pub(crate) cs_insn);

/// Contains extra information about an instruction such as register reads in
/// addition to architecture-specific information
pub struct InsnDetail<'a>(pub(crate) &'a cs_detail, pub(crate) Arch);

impl Insn {
    /// The mnemonic for the instruction
    pub fn mnemonic(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.0.mnemonic.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }

    /// The operand string associated with the instruction
    pub fn op_str(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.0.op_str.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }

    /// Access instruction id
    pub fn id(&self) -> InsnId {
        InsnId(self.0.id)
    }

    /// Size of instruction (in bytes)
    fn len(&self) -> usize {
        self.0.size as usize
    }

    /// Instruction address
    pub fn address(&self) -> u64 {
        self.0.address as u64
    }

    /// Byte-level representation of the instruction
    pub fn bytes(&self) -> &[u8] {
        &self.0.bytes[..self.len()]
    }

    /// Returns the `Detail` object, if there is one. It is up to the caller to determine
    /// the pre-conditions are satisfied.
    ///
    /// Be careful this is still in early stages and largely untested with various `cs_option` and
    /// architecture matrices
    pub(crate) unsafe fn detail(&self, arch: Arch) -> InsnDetail {
        InsnDetail(&*self.0.detail, arch)
    }
}

impl Debug for Insn {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        fmt.debug_struct("Insn")
            .field("address", &self.address())
            .field("len", &self.len())
            .field("bytes", &self.bytes())
            .field("mnemonic", &self.mnemonic())
            .field("op_str", &self.op_str())
            .finish()
    }
}

impl Display for Insn {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{:#x}: ", self.address())?;
        if let Some(mnemonic) = self.mnemonic() {
            write!(fmt, "{} ", mnemonic)?;
            if let Some(op_str) = self.op_str() {
                write!(fmt, "{}", op_str)?;
            }
        }
        Ok(())
    }
}

/// Iterator over registers ids
#[derive(Debug, Clone)]
pub struct RegsIter<'a, T: 'a + Into<RegIdInt> + Copy>(slice::Iter<'a, T>);

impl<'a, T: 'a + Into<RegIdInt> + Copy> Iterator for RegsIter<'a, T> {
    type Item = RegId;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.next() {
            Some(x) => Some(RegId((*x).into())),
            None => None,
        }
    }
}

/// Iterator over instruction group ids
#[derive(Debug, Clone)]
pub struct InsnGroupIter<'a>(slice::Iter<'a, InsnGroupIdInt>);

impl<'a> Iterator for InsnGroupIter<'a> {
    type Item = InsnGroupId;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.next() {
            Some(x) => Some(InsnGroupId(*x as InsnGroupIdInt)),
            None => None,
        }
    }
}

impl<'a> InsnDetail<'a> {
    /// Returns the implicit read registers
    pub fn regs_read(&self) -> RegsIter<u8> {
        RegsIter((*self.0).regs_read[..self.regs_read_count() as usize].iter())
    }

    /// Returns the number of implicit read registers
    pub fn regs_read_count(&self) -> u8 {
        (*self.0).regs_read_count
    }

    /// Returns the implicit write registers
    pub fn regs_write(&self) -> RegsIter<u8> {
        RegsIter((*self.0).regs_write[..self.regs_write_count() as usize].iter())
    }

    /// Returns the number of implicit write registers
    pub fn regs_write_count(&self) -> u8 {
        (*self.0).regs_write_count
    }

    /// Returns the groups to which this instruction belongs
    pub fn groups(&self) -> InsnGroupIter {
        InsnGroupIter((*self.0).groups[..self.groups_count() as usize].iter())
    }

    /// Returns the number groups to which this instruction belongs
    pub fn groups_count(&self) -> u8 {
        (*self.0).groups_count
    }

    /// Architecture-specific detail
    pub fn arch_detail(&self) -> ArchDetail {
        macro_rules! def_arch_detail_match {
            (
                $( [ $ARCH:ident, $detail:ident, $insn_detail:ident, $arch:ident ] )*
            ) => {
                use self::ArchDetail::*;
                use Arch::*;
                $( use arch::$arch::$insn_detail; )*

                return match self.1 {
                    $(
                        $ARCH => {
                            $detail($insn_detail(unsafe { &self.0.__bindgen_anon_1.$arch }))
                        }
                    )*
                    _ => panic!("Unsupported detail arch"),
                }
            }
        }
        def_arch_detail_match!(
            [ARM, ArmDetail, ArmInsnDetail, arm]
            [ARM64, Arm64Detail, Arm64InsnDetail, arm64]
            [MIPS, MipsDetail, MipsInsnDetail, mips]
            [PPC, PpcDetail, PpcInsnDetail, ppc]
            [SPARC, SparcDetail, SparcInsnDetail, sparc]
            [X86, X86Detail, X86InsnDetail, x86]
            [XCORE, XcoreDetail, XcoreInsnDetail, xcore]
        );
    }
}

impl<'a> Debug for InsnDetail<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Detail")
            .field("regs_read", &self.regs_read())
            .field("regs_read_count", &self.regs_read_count())
            .field("regs_write", &self.regs_write())
            .field("regs_write_count", &self.regs_write_count())
            .field("groups", &self.groups())
            .field("groups_count", &self.groups_count())
            .finish()
    }
}

impl<'a> Display for Instructions<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        for instruction in self.iter() {
            write!(fmt, "{:x}:\t", instruction.address())?;
            for byte in instruction.bytes() {
                write!(fmt, " {:02x}", byte)?;
            }
            let remainder = 16 * 3 - (instruction.bytes().len()) * 3;
            for _ in 0..remainder {
                write!(fmt, " ")?;
            }
            if let Some(mnemonic) = instruction.mnemonic() {
                write!(fmt, " {}", mnemonic)?;
                if let Some(op_str) = instruction.op_str() {
                    write!(fmt, " {}", op_str)?;
                }
            }
            write!(fmt, "\n")?;
        }
        Ok(())
    }
}
<commit_msg>Implement size_hint for InstructionIterator<commit_after>use arch::ArchDetail;
use std::ffi::CStr;
use std::slice;
use std::str;
use std::fmt::{self, Debug, Display, Error, Formatter};
use capstone_sys::*;
use constants::Arch;

/// Representation of the array of instructions returned by disasm
#[derive(Debug)]
pub struct Instructions<'a>(&'a mut [cs_insn]);

/// Integer type used in `InsnId`
pub type InsnIdInt = u32;

/// Represents an instruction id, which may architecture-specific.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct InsnId(pub InsnIdInt);

/// Integer type used in `InsnGroupId`
pub type InsnGroupIdInt = u8;

/// Represents the group an instruction belongs to, which may be architecture-specific.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct InsnGroupId(pub InsnGroupIdInt);

/// Integer type used in `RegId`
pub type RegIdInt = u16;

/// Represents an register id, which is architecture-specific.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct RegId(pub RegIdInt);

impl<'a> Instructions<'a> {
    pub(crate) unsafe fn from_raw_parts(ptr: *mut cs_insn, len: usize) -> Instructions<'a> {
        Instructions(slice::from_raw_parts_mut(ptr, len))
    }

    pub(crate) fn new_empty() -> Instructions<'a> {
        Instructions(&mut [])
    }

    /// Get number of instructions
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Iterator over instructions
    pub fn iter<'b>(&'a self) -> InstructionIterator<'b>
    where
        'a: 'b,
    {
        let iter = self.0.iter();
        InstructionIterator(iter)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl<'a> Drop for Instructions<'a> {
    fn drop(&mut self) {
        if self.len() > 0 {
            unsafe {
                cs_free(self.0.as_mut_ptr(), self.len());
            }
        }
    }
}

/// An iterator over the instructions returned by disasm
///
/// This is currently the only supported interface for reading them.
pub struct InstructionIterator<'a>(slice::Iter<'a, cs_insn>);

impl<'a> Iterator for InstructionIterator<'a> {
    type Item = Insn;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|x| Insn(*x))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }

    #[inline]
    fn count(self) -> usize {
        self.0.count()
    }
}

impl<'a> DoubleEndedIterator for InstructionIterator<'a> {
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.0.next_back().map(|x| Insn(*x))
    }
}

/// A wrapper for the raw capstone-sys instruction
pub struct Insn(pub(crate) cs_insn);

/// Contains extra information about an instruction such as register reads in
/// addition to architecture-specific information
pub struct InsnDetail<'a>(pub(crate) &'a cs_detail, pub(crate) Arch);

impl Insn {
    /// The mnemonic for the instruction
    pub fn mnemonic(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.0.mnemonic.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }

    /// The operand string associated with the instruction
    pub fn op_str(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.0.op_str.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }

    /// Access instruction id
    pub fn id(&self) -> InsnId {
        InsnId(self.0.id)
    }

    /// Size of instruction (in bytes)
    fn len(&self) -> usize {
        self.0.size as usize
    }

    /// Instruction address
    pub fn address(&self) -> u64 {
        self.0.address as u64
    }

    /// Byte-level representation of the instruction
    pub fn bytes(&self) -> &[u8] {
        &self.0.bytes[..self.len()]
    }

    /// Returns the `Detail` object, if there is one. It is up to the caller to determine
    /// the pre-conditions are satisfied.
    ///
    /// Be careful this is still in early stages and largely untested with various `cs_option` and
    /// architecture matrices
    pub(crate) unsafe fn detail(&self, arch: Arch) -> InsnDetail {
        InsnDetail(&*self.0.detail, arch)
    }
}

impl Debug for Insn {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        fmt.debug_struct("Insn")
            .field("address", &self.address())
            .field("len", &self.len())
            .field("bytes", &self.bytes())
            .field("mnemonic", &self.mnemonic())
            .field("op_str", &self.op_str())
            .finish()
    }
}

impl Display for Insn {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{:#x}: ", self.address())?;
        if let Some(mnemonic) = self.mnemonic() {
            write!(fmt, "{} ", mnemonic)?;
            if let Some(op_str) = self.op_str() {
                write!(fmt, "{}", op_str)?;
            }
        }
        Ok(())
    }
}

/// Iterator over registers ids
#[derive(Debug, Clone)]
pub struct RegsIter<'a, T: 'a + Into<RegIdInt> + Copy>(slice::Iter<'a, T>);

impl<'a, T: 'a + Into<RegIdInt> + Copy> Iterator for RegsIter<'a, T> {
    type Item = RegId;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.next() {
            Some(x) => Some(RegId((*x).into())),
            None => None,
        }
    }
}

/// Iterator over instruction group ids
#[derive(Debug, Clone)]
pub struct InsnGroupIter<'a>(slice::Iter<'a, InsnGroupIdInt>);

impl<'a> Iterator for InsnGroupIter<'a> {
    type Item = InsnGroupId;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.next() {
            Some(x) => Some(InsnGroupId(*x as InsnGroupIdInt)),
            None => None,
        }
    }
}

impl<'a> InsnDetail<'a> {
    /// Returns the implicit read registers
    pub fn regs_read(&self) -> RegsIter<u8> {
        RegsIter((*self.0).regs_read[..self.regs_read_count() as usize].iter())
    }

    /// Returns the number of implicit read registers
    pub fn regs_read_count(&self) -> u8 {
        (*self.0).regs_read_count
    }

    /// Returns the implicit write registers
    pub fn regs_write(&self) -> RegsIter<u8> {
        RegsIter((*self.0).regs_write[..self.regs_write_count() as usize].iter())
    }

    /// Returns the number of implicit write registers
    pub fn regs_write_count(&self) -> u8 {
        (*self.0).regs_write_count
    }

    /// Returns the groups to which this instruction belongs
    pub fn groups(&self) -> InsnGroupIter {
        InsnGroupIter((*self.0).groups[..self.groups_count() as usize].iter())
    }

    /// Returns the number groups to which this instruction belongs
    pub fn groups_count(&self) -> u8 {
        (*self.0).groups_count
    }

    /// Architecture-specific detail
    pub fn arch_detail(&self) -> ArchDetail {
        macro_rules! def_arch_detail_match {
            (
                $( [ $ARCH:ident, $detail:ident, $insn_detail:ident, $arch:ident ] )*
            ) => {
                use self::ArchDetail::*;
                use Arch::*;
                $( use arch::$arch::$insn_detail; )*

                return match self.1 {
                    $(
                        $ARCH => {
                            $detail($insn_detail(unsafe { &self.0.__bindgen_anon_1.$arch }))
                        }
                    )*
                    _ => panic!("Unsupported detail arch"),
                }
            }
        }
        def_arch_detail_match!(
            [ARM, ArmDetail, ArmInsnDetail, arm]
            [ARM64, Arm64Detail, Arm64InsnDetail, arm64]
            [MIPS, MipsDetail, MipsInsnDetail, mips]
            [PPC, PpcDetail, PpcInsnDetail, ppc]
            [SPARC, SparcDetail, SparcInsnDetail, sparc]
            [X86, X86Detail, X86InsnDetail, x86]
            [XCORE, XcoreDetail, XcoreInsnDetail, xcore]
        );
    }
}

impl<'a> Debug for InsnDetail<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Detail")
            .field("regs_read", &self.regs_read())
            .field("regs_read_count", &self.regs_read_count())
            .field("regs_write", &self.regs_write())
            .field("regs_write_count", &self.regs_write_count())
            .field("groups", &self.groups())
            .field("groups_count", &self.groups_count())
            .finish()
    }
}

impl<'a> Display for Instructions<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        for instruction in self.iter() {
            write!(fmt, "{:x}:\t", instruction.address())?;
            for byte in instruction.bytes() {
                write!(fmt, " {:02x}", byte)?;
            }
            let remainder = 16 * 3 - (instruction.bytes().len()) * 3;
            for _ in 0..remainder {
                write!(fmt, " ")?;
            }
            if let Some(mnemonic) = instruction.mnemonic() {
                write!(fmt, " {}", mnemonic)?;
                if let Some(op_str) = instruction.op_str() {
                    write!(fmt, " {}", op_str)?;
                }
            }
            write!(fmt, "\n")?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before><commit_msg>Add while loops<commit_after><|endoftext|>


<commit_before><commit_msg>Make primitive function calls work<commit_after><|endoftext|>


<commit_before>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::handle::{WlcView, WlcOutput};

pub type TreeResult = Result<(), TryLockError<MutexGuard<'static, Tree>>>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

impl Tree {
    fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    fn get_current_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            //if let Some(child) = container.get_ancestor_of_type(ContainerType::Workspace) {
            //return child.get_children()[0].get_parent()

            //}
            // NOTE hack here, remove commented code above to make this work properly
            let parent = container.get_parent().expect(ERR_BAD_TREE);
            for child in parent.get_children_mut() {
                if child == container {
                    return Some(child);
                }
            }
        }
        return None
    }

    fn get_output_of_view(&self, wlc_view: &WlcView) -> Option<WlcOutput> {
        if let Some(view_node) = self.root.find_view_by_handle(wlc_view) {
            if let Some(output_node) = view_node.get_ancestor_of_type(ContainerType::Output) {
                if let Some(handle) =  output_node.get_val().get_handle() {
                    return match handle {
                        Handle::Output(output) => Some(output),
                        _ => None
                    }
                }
            }
        }
        return None;
    }

    fn get_workspace_by_name(&self, name: &str) -> Option<&Node> {
        for child in self.root.get_children()[0].get_children() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn add_output(&mut self, wlc_output: WlcOutput) {
        self.root.new_child(Container::new_output(wlc_output));
    }

    fn add_workspace(&mut self, name: &str) {
        let workspace = Container::new_workspace(name.to_string());
        let mut index = 0;
        if let Some(output) = self.get_active_output() {
            for (cur_index, child) in self.root.get_children().iter().enumerate() {
                if child == output {
                    index = cur_index;
                    break;
                }
            }
        }
        self.root.get_children_mut()[index].new_child(workspace);
    }

    fn add_view(&self, wlc_view: WlcView) {
        if let Some(current_workspace) = self.get_current_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            current_workspace.new_child(Container::new_view(wlc_view));
        }
    }

    fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub fn add_output(wlc_output: WlcOutput) -> TreeResult {
    {
        let mut tree = try!(TREE.try_lock());
        tree.add_output(wlc_output);
    }
    try!(add_workspace(&"1"));
    try!(switch_workspace(&"1"));
    Ok(())
}

pub fn add_workspace(name: &str) -> TreeResult {
    trace!("Adding new workspace to root");
    let mut tree = try!(TREE.lock());
    tree.add_workspace(name);
    Ok(())
}

pub fn add_view(wlc_view: WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.add_view(wlc_view);
    Ok(())
}

pub fn remove_view(wlc_view: &WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.remove_view(wlc_view);
    Ok(())
}

pub fn switch_workspace(name: &str) -> TreeResult {
    trace!("Switching to workspace {}", name);
    let mut tree = try!(TREE.lock());
    if let Some(old_workspace) = tree.get_current_workspace() {
        // Make all the views in the original workspace to be invisible
        for view in old_workspace.get_children_mut() {
            trace!("Setting {:?} invisible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(0),
                _ => {},
            }
        }
    }
    let current_workspace: *const Node;
    {
        let new_current_workspace: &mut Node;
        if let Some(_) = tree.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
            new_current_workspace = tree.get_workspace_by_name_mut(name)
                .expect(ERR_BAD_TREE);
        } else {
            drop(tree);
            try!(add_workspace(name));
            tree = try!(TREE.lock());
            new_current_workspace = tree.get_workspace_by_name_mut(name)
                .expect(ERR_BAD_TREE);
        }
        for view in new_current_workspace.get_children_mut() {
            trace!("Setting {:?} visible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(1),
                _ => {},
            }
        }
        // Set the first view to be focused, so that the view is updated to this new workspace
        if new_current_workspace.get_children().len() > 0 {
            trace!("Focusing view");
            match new_current_workspace.get_children_mut()[0]
                .get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.focus(),
                _ => {},
            }
        } else {
            WlcView::root().focus();
        }
        current_workspace = new_current_workspace as *const Node;
    }
    tree.active_container = current_workspace;
    Ok(())
}

/// Finds the WlcOutput associated with the WlcView from the tree
pub fn get_output_of_view(wlc_view: &WlcView) -> Option<WlcOutput> {
    let tree = TREE.lock().expect("Unable to lock layout tree!");
    tree.get_output_of_view(wlc_view)
}

<commit_msg>Touched up switch_workspace<commit_after>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::handle::{WlcView, WlcOutput};

pub type TreeResult = Result<(), TryLockError<MutexGuard<'static, Tree>>>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

impl Tree {
    fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    fn get_current_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            //if let Some(child) = container.get_ancestor_of_type(ContainerType::Workspace) {
            //return child.get_children()[0].get_parent()

            //}
            // NOTE hack here, remove commented code above to make this work properly
            let parent = container.get_parent().expect(ERR_BAD_TREE);
            for child in parent.get_children_mut() {
                if child == container {
                    return Some(child);
                }
            }
        }
        return None
    }

    fn get_output_of_view(&self, wlc_view: &WlcView) -> Option<WlcOutput> {
        if let Some(view_node) = self.root.find_view_by_handle(wlc_view) {
            if let Some(output_node) = view_node.get_ancestor_of_type(ContainerType::Output) {
                if let Some(handle) =  output_node.get_val().get_handle() {
                    return match handle {
                        Handle::Output(output) => Some(output),
                        _ => None
                    }
                }
            }
        }
        return None;
    }

    fn get_workspace_by_name(&self, name: &str) -> Option<&Node> {
        for child in self.root.get_children()[0].get_children() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn add_output(&mut self, wlc_output: WlcOutput) {
        self.root.new_child(Container::new_output(wlc_output));
    }

    fn add_workspace(&mut self, name: &str) {
        let workspace = Container::new_workspace(name.to_string());
        let mut index = 0;
        if let Some(output) = self.get_active_output() {
            for (cur_index, child) in self.root.get_children().iter().enumerate() {
                if child == output {
                    index = cur_index;
                    break;
                }
            }
        }
        self.root.get_children_mut()[index].new_child(workspace);
    }

    fn add_view(&self, wlc_view: WlcView) {
        if let Some(current_workspace) = self.get_current_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            current_workspace.new_child(Container::new_view(wlc_view));
        }
    }

    fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub fn add_output(wlc_output: WlcOutput) -> TreeResult {
    {
        let mut tree = try!(TREE.try_lock());
        tree.add_output(wlc_output);
    }
    try!(add_workspace(&"1"));
    try!(switch_workspace(&"1"));
    Ok(())
}

pub fn add_workspace(name: &str) -> TreeResult {
    trace!("Adding new workspace to root");
    let mut tree = try!(TREE.lock());
    tree.add_workspace(name);
    Ok(())
}

pub fn add_view(wlc_view: WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.add_view(wlc_view);
    Ok(())
}

pub fn remove_view(wlc_view: &WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.remove_view(wlc_view);
    Ok(())
}

pub fn switch_workspace(name: &str) -> TreeResult {
    trace!("Switching to workspace {}", name);
    let mut tree = try!(TREE.lock());
    if let Some(old_workspace) = tree.get_current_workspace() {
        // Make all the views in the original workspace to be invisible
        for view in old_workspace.get_children_mut() {
            trace!("Setting {:?} invisible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(0),
                _ => {},
            }
        }
    }
    let current_workspace: *const Node;
    {
        if let Some(_) = tree.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
        } else {
            trace!("Adding workspace {}", name);
            try!(add_workspace(name));
        }
        let new_current_workspace = tree.get_workspace_by_name_mut(name).expect(ERR_BAD_TREE);
        for view in new_current_workspace.get_children_mut() {
            trace!("Setting {:?} visible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(1),
                _ => {},
            }
        }
        // Set the first view to be focused, so that the view is updated to this new workspace
        if new_current_workspace.get_children().len() > 0 {
            trace!("Focusing view");
            match new_current_workspace.get_children_mut()[0]
                .get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.focus(),
                _ => {},
            }
        } else {
            WlcView::root().focus();
        }
        current_workspace = new_current_workspace as *const Node;
    }
    tree.active_container = current_workspace;
    Ok(())
}

/// Finds the WlcOutput associated with the WlcView from the tree
pub fn get_output_of_view(wlc_view: &WlcView) -> Option<WlcOutput> {
    let tree = TREE.lock().expect("Unable to lock layout tree!");
    tree.get_output_of_view(wlc_view)
}

<|endoftext|>


<commit_before>enum Category {
    Identifier,
    AssignmentOperator,
    IntegerLiteral,
    StringLiteral,
}

pub struct Token {
    lexeme: String,
    category: Category,
}
<commit_msg>Derive traits necessary to use categories in assert_eq!.<commit_after>#[derive(PartialEq, Show)]
pub enum Category {
    Identifier,
    AssignmentOperator,
    IntegerLiteral,
    StringLiteral,
}

pub struct Token {
    lexeme: String,
    category: Category,
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map;
use std::default::Default;
use std::slice;
use stream::wire_format;
use clear::Clear;

#[derive(Show)]
pub enum UnknownValue {
    Fixed32(u32),
    Fixed64(u64),
    Varint(u64),
    LengthDelimited(Vec<u8>),
}

impl UnknownValue {
    pub fn wire_type(&self) -> wire_format::WireType {
        self.get_ref().wire_type()
    }

    pub fn get_ref<'s>(&'s self) -> UnknownValueRef<'s> {
        match *self {
            UnknownValue::Fixed32(fixed32) => UnknownValueRef::Fixed32(fixed32),
            UnknownValue::Fixed64(fixed64) => UnknownValueRef::Fixed64(fixed64),
            UnknownValue::Varint(varint) => UnknownValueRef::Varint(varint),
            UnknownValue::LengthDelimited(ref bytes) => UnknownValueRef::LengthDelimited(bytes.as_slice()),
        }
    }
}

pub enum UnknownValueRef<'o> {
    Fixed32(u32),
    Fixed64(u64),
    Varint(u64),
    LengthDelimited(&'o [u8]),
}

impl<'o> UnknownValueRef<'o> {
    pub fn wire_type(&self) -> wire_format::WireType {
        match *self {
            UnknownValueRef::Fixed32(_) => wire_format::WireTypeFixed32,
            UnknownValueRef::Fixed64(_) => wire_format::WireTypeFixed64,
            UnknownValueRef::Varint(_) => wire_format::WireTypeVarint,
            UnknownValueRef::LengthDelimited(_) => wire_format::WireTypeLengthDelimited,
        }
    }
}

#[derive(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownValues {
    pub fixed32: Vec<u32>,
    pub fixed64: Vec<u64>,
    pub varint: Vec<u64>,
    pub length_delimited: Vec<Vec<u8>>,
}

impl UnknownValues {
    pub fn add_value(&mut self, value: UnknownValue) {
        match value {
            UnknownValue::Fixed64(fixed64) => self.fixed64.push(fixed64),
            UnknownValue::Fixed32(fixed32) => self.fixed32.push(fixed32),
            UnknownValue::Varint(varint) => self.varint.push(varint),
            UnknownValue::LengthDelimited(length_delimited) => self.length_delimited.push(length_delimited),
        };
    }

    pub fn iter<'s>(&'s self) -> UnknownValuesIter<'s> {
        UnknownValuesIter {
            fixed32: self.fixed32.iter(),
            fixed64: self.fixed64.iter(),
            varint: self.varint.iter(),
            length_delimited: self.length_delimited.iter(),
        }
    }
}

pub struct UnknownValuesIter<'o> {
    fixed32: slice::Iter<'o, u32>,
    fixed64: slice::Iter<'o, u64>,
    varint: slice::Iter<'o, u64>,
    length_delimited: slice::Iter<'o, Vec<u8>>,
}

impl<'o> Iterator for UnknownValuesIter<'o> {
    type Item = UnknownValueRef<'o>;

    fn next(&mut self) -> Option<UnknownValueRef<'o>> {
        let fixed32 = self.fixed32.next();
        if fixed32.is_some() {
            return Some(UnknownValueRef::Fixed32(*fixed32.unwrap()));
        }
        let fixed64 = self.fixed64.next();
        if fixed64.is_some() {
            return Some(UnknownValueRef::Fixed64(*fixed64.unwrap()));
        }
        let varint = self.varint.next();
        if varint.is_some() {
            return Some(UnknownValueRef::Varint(*varint.unwrap()));
        }
        let length_delimited = self.length_delimited.next();
        if length_delimited.is_some() {
            return Some(UnknownValueRef::LengthDelimited(length_delimited.unwrap().as_slice()))
        }
        None
    }
}

#[derive(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownFields {
    // option is needed, because HashMap constructor performs allocation,
    // and very expensive
    pub fields: Option<Box<HashMap<u32, UnknownValues>>>,
}

impl UnknownFields {
    pub fn new() -> UnknownFields {
        Default::default()
    }

    fn init_map(&mut self) {
        if self.fields.is_none() {
            self.fields = Some(box Default::default());
        }
    }

    fn find_field<'a>(&'a mut self, number: u32) -> &'a mut UnknownValues {
        self.init_map();

        match self.fields.as_mut().unwrap().entry(number) {
            hash_map::Entry::Occupied(e) => e.into_mut(),
            hash_map::Entry::Vacant(e) => e.set(Default::default()),
        }
    }

    pub fn add_fixed32(&mut self, number: u32, fixed32: u32) {
        self.find_field(number).fixed32.push(fixed32);
    }

    pub fn add_fixed64(&mut self, number: u32, fixed64: u64) {
        self.find_field(number).fixed64.push(fixed64);
    }

    pub fn add_varint(&mut self, number: u32, varint: u64) {
        self.find_field(number).varint.push(varint);
    }

    pub fn add_length_delimited(&mut self, number: u32, length_delimited: Vec<u8>) {
        self.find_field(number).length_delimited.push(length_delimited);
    }

    pub fn add_value(&mut self, number: u32, value: UnknownValue) {
        self.find_field(number).add_value(value);
    }

    pub fn iter<'s>(&'s self) -> UnknownFieldIter<'s> {
        UnknownFieldIter {
            entries: self.fields.as_ref().map(|m| m.iter())
        }
    }
}

impl Clear for UnknownFields {
    fn clear(&mut self) {
        if self.fields.is_some() {
            self.fields.as_mut().unwrap().clear();
        }
    }
}

pub struct UnknownFieldIter<'s> {
    entries: Option<hash_map::Iter<'s, u32, UnknownValues>>,
}

impl<'s> Iterator for UnknownFieldIter<'s> {
    type Item = (u32, &'s UnknownValues);

    fn next(&mut self) -> Option<(u32, &'s UnknownValues)> {
        if self.entries.is_none() {
            None
        } else {
            self.entries.as_mut().unwrap().next().map(|(&number, values)| (number, values))
        }
    }
}
<commit_msg>update to lastest rust<commit_after>use std::collections::HashMap;
use std::collections::hash_map;
use std::default::Default;
use std::slice;
use stream::wire_format;
use clear::Clear;

#[derive(Show)]
pub enum UnknownValue {
    Fixed32(u32),
    Fixed64(u64),
    Varint(u64),
    LengthDelimited(Vec<u8>),
}

impl UnknownValue {
    pub fn wire_type(&self) -> wire_format::WireType {
        self.get_ref().wire_type()
    }

    pub fn get_ref<'s>(&'s self) -> UnknownValueRef<'s> {
        match *self {
            UnknownValue::Fixed32(fixed32) => UnknownValueRef::Fixed32(fixed32),
            UnknownValue::Fixed64(fixed64) => UnknownValueRef::Fixed64(fixed64),
            UnknownValue::Varint(varint) => UnknownValueRef::Varint(varint),
            UnknownValue::LengthDelimited(ref bytes) => UnknownValueRef::LengthDelimited(bytes.as_slice()),
        }
    }
}

pub enum UnknownValueRef<'o> {
    Fixed32(u32),
    Fixed64(u64),
    Varint(u64),
    LengthDelimited(&'o [u8]),
}

impl<'o> UnknownValueRef<'o> {
    pub fn wire_type(&self) -> wire_format::WireType {
        match *self {
            UnknownValueRef::Fixed32(_) => wire_format::WireTypeFixed32,
            UnknownValueRef::Fixed64(_) => wire_format::WireTypeFixed64,
            UnknownValueRef::Varint(_) => wire_format::WireTypeVarint,
            UnknownValueRef::LengthDelimited(_) => wire_format::WireTypeLengthDelimited,
        }
    }
}

#[derive(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownValues {
    pub fixed32: Vec<u32>,
    pub fixed64: Vec<u64>,
    pub varint: Vec<u64>,
    pub length_delimited: Vec<Vec<u8>>,
}

impl UnknownValues {
    pub fn add_value(&mut self, value: UnknownValue) {
        match value {
            UnknownValue::Fixed64(fixed64) => self.fixed64.push(fixed64),
            UnknownValue::Fixed32(fixed32) => self.fixed32.push(fixed32),
            UnknownValue::Varint(varint) => self.varint.push(varint),
            UnknownValue::LengthDelimited(length_delimited) => self.length_delimited.push(length_delimited),
        };
    }

    pub fn iter<'s>(&'s self) -> UnknownValuesIter<'s> {
        UnknownValuesIter {
            fixed32: self.fixed32.iter(),
            fixed64: self.fixed64.iter(),
            varint: self.varint.iter(),
            length_delimited: self.length_delimited.iter(),
        }
    }
}

pub struct UnknownValuesIter<'o> {
    fixed32: slice::Iter<'o, u32>,
    fixed64: slice::Iter<'o, u64>,
    varint: slice::Iter<'o, u64>,
    length_delimited: slice::Iter<'o, Vec<u8>>,
}

impl<'o> Iterator for UnknownValuesIter<'o> {
    type Item = UnknownValueRef<'o>;

    fn next(&mut self) -> Option<UnknownValueRef<'o>> {
        let fixed32 = self.fixed32.next();
        if fixed32.is_some() {
            return Some(UnknownValueRef::Fixed32(*fixed32.unwrap()));
        }
        let fixed64 = self.fixed64.next();
        if fixed64.is_some() {
            return Some(UnknownValueRef::Fixed64(*fixed64.unwrap()));
        }
        let varint = self.varint.next();
        if varint.is_some() {
            return Some(UnknownValueRef::Varint(*varint.unwrap()));
        }
        let length_delimited = self.length_delimited.next();
        if length_delimited.is_some() {
            return Some(UnknownValueRef::LengthDelimited(length_delimited.unwrap().as_slice()))
        }
        None
    }
}

#[derive(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownFields {
    // option is needed, because HashMap constructor performs allocation,
    // and very expensive
    pub fields: Option<Box<HashMap<u32, UnknownValues>>>,
}

impl UnknownFields {
    pub fn new() -> UnknownFields {
        Default::default()
    }

    fn init_map(&mut self) {
        if self.fields.is_none() {
            self.fields = Some(box Default::default());
        }
    }

    fn find_field<'a>(&'a mut self, number: &'a u32) -> &'a mut UnknownValues {
        self.init_map();

        match self.fields.as_mut().unwrap().entry(number) {
            hash_map::Entry::Occupied(e) => e.into_mut(),
            hash_map::Entry::Vacant(e) => e.insert(Default::default()),
        }
    }

    pub fn add_fixed32(&mut self, number: u32, fixed32: u32) {
        self.find_field(&number).fixed32.push(fixed32);
    }

    pub fn add_fixed64(&mut self, number: u32, fixed64: u64) {
        self.find_field(&number).fixed64.push(fixed64);
    }

    pub fn add_varint(&mut self, number: u32, varint: u64) {
        self.find_field(&number).varint.push(varint);
    }

    pub fn add_length_delimited(&mut self, number: u32, length_delimited: Vec<u8>) {
        self.find_field(&number).length_delimited.push(length_delimited);
    }

    pub fn add_value(&mut self, number: u32, value: UnknownValue) {
        self.find_field(&number).add_value(value);
    }

    pub fn iter<'s>(&'s self) -> UnknownFieldIter<'s> {
        UnknownFieldIter {
            entries: self.fields.as_ref().map(|m| m.iter())
        }
    }
}

impl Clear for UnknownFields {
    fn clear(&mut self) {
        if self.fields.is_some() {
            self.fields.as_mut().unwrap().clear();
        }
    }
}

pub struct UnknownFieldIter<'s> {
    entries: Option<hash_map::Iter<'s, u32, UnknownValues>>,
}

impl<'s> Iterator for UnknownFieldIter<'s> {
    type Item = (u32, &'s UnknownValues);

    fn next(&mut self) -> Option<(u32, &'s UnknownValues)> {
        if self.entries.is_none() {
            None
        } else {
            self.entries.as_mut().unwrap().next().map(|(&number, values)| (number, values))
        }
    }
}
<|endoftext|>


<commit_before>use ::nfa::{State, Edge, NFA};

#[cfg(test)] mod spec;

#[derive(Clone,PartialEq,Debug)]
struct PotentialMatch {
    current_state: Option<State>,
    remaining_text: String
}

impl PotentialMatch {
    pub fn advance(&self, nfa: &NFA) -> Vec<PotentialMatch> {
        if self.current_state.is_none() {
            return vec![self.clone()];
        }

        let current_state = self.current_state.clone().unwrap();

        match current_state {
            State::State{ref edge, ref out} => {
                self.next(nfa, edge, out)
            },
            State::Split{ref s1, ref out1, ref s2, ref out2} => {
                let mut s1_next = self.next(nfa, s1, out1);
                let mut s2_next = self.next(nfa, s2, out2);
                s1_next.append(&mut s2_next);
                s1_next
            }
        }
    }

    fn next(&self, nfa: &NFA, edge: &Option<char>, out: &Edge) -> Vec<PotentialMatch> {
        match edge {
            &Some(val) => {
                if self.remaining_text.is_empty() {
                    // no character to consume, this potential match cannot continue
                    return vec![];
                }

                if val == self.remaining_text.as_bytes()[0] as char {
                    // can consume char and advance along edge
                    match out {
                        &Edge::End => {
                            vec![PotentialMatch::new(None,
                                                     &self.remaining_text[1..])]
                        },
                        &Edge::Id(id) => {
                            vec![PotentialMatch::new(nfa.get_state(id),
                            &self.remaining_text[1..])]
                        },
                        _ => panic!()
                    }
                } else { // cannot proceed
                    vec![]
                }
            },
            &None => {
                // can advance along empty edge
                match out {
                    &Edge::End => {
                        vec![PotentialMatch::new(None,
                                                 &self.remaining_text)]
                    },
                    &Edge::Id(id) => {
                        vec![PotentialMatch::new(
                            nfa.get_state(id),
                            &self.remaining_text)]
                    },
                    _ => panic!()
                }
            }
        }

    }

    pub fn is_match(&self) -> bool {
        self.current_state.is_none()
    }

    pub fn new(state: Option<State>, remaining_text: &str) -> PotentialMatch {
        PotentialMatch {
            current_state: state,
            remaining_text: remaining_text.to_owned()
        }
    }
}

pub struct Matcher {
    nfa: NFA,
    text: String
}

impl Matcher {
    pub fn new(nfa: NFA, text: &str) -> Matcher {
        Matcher {
            nfa: nfa,
            text: text.to_owned()
        }
    }

    pub fn run(&mut self) -> bool {

        if self.nfa.num_states() == 0 { // regex is empty
            return true;
        }

        let mut states = vec![
            PotentialMatch::new(Some(self.nfa.get_start().unwrap()),
                                &self.text)
        ];

        while Self::has_valid_state(&states) {

            let mut updated_states = Vec::new();

            for state in states {
                let new_states = state.advance(&self.nfa);

                for s in new_states {
                    if s.is_match() {
                        return true;
                    } else {
                        updated_states.push(s);
                    }
                }
            }

            states = updated_states;
        }

        false
    }

    fn has_valid_state(states: &Vec<PotentialMatch>) -> bool {
        states.len() > 0
    }
}

<commit_msg>handle split state case<commit_after>use ::nfa::{State, Edge, NFA};

#[cfg(test)] mod spec;

#[derive(Clone,PartialEq,Debug)]
struct PotentialMatch {
    current_state: Option<State>,
    remaining_text: String
}

impl PotentialMatch {
    pub fn advance(&self, nfa: &NFA) -> Vec<PotentialMatch> {
        if self.current_state.is_none() {
            return vec![self.clone()];
        }

        let current_state = self.current_state.clone().unwrap();

        match current_state {
            State::State{ref edge, ref out} => {
                vec![self.next_for_edge(nfa, edge, out)]
            },
            State::Split{ref s1, ref out1, ref s2, ref out2} => {
                let mut s1_next = self.next_for_edge(nfa, s1, out1);
                let mut s2_next = self.next_for_edge(nfa, s2, out2);
                vec![s1_next, s2_next]
            }
        }
    }

    fn next(&self, nfa: &NFA, edge: &Option<char>, out: &Edge) -> Option<PotentialMatch> {
        match edge {
            &Some(val) => {
                if self.remaining_text.is_empty() {
                    // no character to consume, this potential match cannot continue
                    return None;
                }

                if val == self.remaining_text.as_bytes()[0] as char {
                    // can consume char and advance along edge
                    match out {
                        &Edge::End => {
                            Some(PotentialMatch::new(None,
                                                     &self.remaining_text[1..]))
                        },
                        &Edge::Id(id) => {
                            Some(PotentialMatch::new(nfa.get_state(id),
                            &self.remaining_text[1..]))
                        },
                        _ => panic!()
                    }
                } else {
                    // potential match cannot proceed, mismatched character
                    None
                }
            },
            &None => {
                // can advance along empty edge
                match out {
                    &Edge::End => {
                        Some(PotentialMatch::new(None,
                                                 &self.remaining_text))
                    },
                    &Edge::Id(id) => {
                        Some(PotentialMatch::new(
                            nfa.get_state(id),
                            &self.remaining_text))
                    },
                    _ => panic!("cannot evaluate incomplete NFA")
                }
            }
        }

    }

    pub fn is_match(&self) -> bool {
        self.current_state.is_none()
    }

    pub fn new(state: Option<State>, remaining_text: &str) -> PotentialMatch {
        PotentialMatch {
            current_state: state,
            remaining_text: remaining_text.to_owned()
        }
    }
}

pub struct Matcher {
    nfa: NFA,
    text: String
}

impl Matcher {
    pub fn new(nfa: NFA, text: &str) -> Matcher {
        Matcher {
            nfa: nfa,
            text: text.to_owned()
        }
    }

    pub fn run(&mut self) -> bool {

        if self.nfa.num_states() == 0 { // regex is empty
            return true;
        }

        let mut states = vec![
            PotentialMatch::new(Some(self.nfa.get_start().unwrap()),
                                &self.text)
        ];

        while Self::has_valid_state(&states) {

            let mut updated_states = Vec::new();

            for state in states {
                let new_states = state.advance(&self.nfa);

                for s in new_states {
                    if s.is_match() {
                        return true;
                    } else {
                        updated_states.push(s);
                    }
                }
            }

            states = updated_states;
        }

        false
    }

    fn has_valid_state(states: &Vec<PotentialMatch>) -> bool {
        states.len() > 0
    }
}

<|endoftext|>


<commit_before>use std::ops::{Add, Mul};

/// A pair of coordinates
#[derive(Clone, Copy)]
pub struct Vec2(pub usize, pub usize);

/// A structure of values
pub struct Matrix<T> {
    /// 2 dimensional array of rows and columns
    dim: Vec2,
    /// `Vector` of values in the `Matrix`
    buffer: Vec<T>,
}

impl <T> Matrix<T> {
    /// Returns a new `Matrix`
    ///
    /// # Arguments
    ///
    /// - `dimensions` - 2 dimensional array of rows and columns
    /// - `buffer` - `Vector` of values
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// ```
    pub fn new(dimensions: Vec2, buffer: Vec<T>) -> Matrix<T> {
        Matrix {
            dim: dimensions,
            buffer: buffer,
        }
    }
}

impl <T> Matrix<T> where T: Copy {
    /// Returns reference to value at `Vec2`
    ///
    /// # Arguments
    ///
    /// - `Vec2` - coordinates of the value in the `Matrix`
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// ```
    pub fn get(&self, Vec2(x, y): Vec2) -> T {
        self.buffer[x * self.dim.1 + y]
    }
}

//////////////
// Addition //
//////////////

impl<T> Add<Matrix<T>> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 + matrix2;
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: Matrix<T>) -> Matrix<T> {
        let mut buffer = Vec::new();
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b Matrix<T>> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 + &matrix2;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        let mut buffer = Vec::new();
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<T> Add<T> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - a constant
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = matrix1 + float;
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// ```
    fn add(self, rhs: T) -> Matrix<T> {
        let mut buffer = Vec::new();
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b T> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - a constant reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = &matrix1 + &float;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// assert_eq!(float, 1.0);
    /// ```
    fn add(self, &rhs: &'b T) -> Matrix<T> {
        let mut buffer = Vec::new();
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

/////////////////////
// Multiplication  //
/////////////////////

impl<T> Mul<Matrix<T>> for Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 * matrix2;
    /// assert_eq!(matrix3.buffer.len(), 4);
    /// ```
    fn mul(self, rhs: Matrix<T>) -> Matrix<<<T as Mul>::Output as Add>::Output> {
        let mut buffer = Vec::new();
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

// impl<'a, 'b, T> Add<&'b Matrix<T>> for &'a Matrix<T> where T: Add + Copy {
//     type Output = Matrix<<T as Add>::Output>;
//
//     /// Add Matricies by reference
//     ///
//     /// # Arguments
//     ///
//     /// - `self` - this matrix reference
//     /// - `rhs` - another matrix reference
//     ///
//     /// # Example
//     ///
//     /// ```
//     /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
//     /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
//     /// let matrix3 = &matrix1 + &matrix2;
//     /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
//     /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
//     /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
//     /// ```
//     fn add(self, rhs: &'b Matrix<T>) -> Matrix<<T as Add>::Output> {
//         let mut buffer = Vec::new();
//         for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
//             buffer.push(i + j);
//         }
//         Matrix::new(self.dim, buffer)
//     }
// }
//
// impl<T> Add<T> for Matrix<T> where T: Add + Copy {
//     type Output = Matrix<<T as Add>::Output>;
//
//     /// Add Matrix and a constant
//     ///
//     /// # Arguments
//     ///
//     /// - `self` - this matrix
//     /// - `rhs` - a constant
//     ///
//     /// # Example
//     ///
//     /// ```
//     /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
//     /// let float = 1.0;
//     /// let matrix2 = matrix1 + float;
//     /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
//     /// ```
//     fn add(self, rhs: T) -> Matrix<<T as Add>::Output> {
//         let mut buffer = Vec::new();
//         for &i in self.buffer.iter() {
//             buffer.push(i + rhs);
//         }
//         Matrix::new(self.dim, buffer)
//     }
// }
//
// impl<'a, 'b, T> Add<&'b T> for &'a Matrix<T> where T: Add + Copy {
//     type Output = Matrix<<T as Add>::Output>;
//
//     /// Add Matrix and a constant
//     ///
//     /// # Arguments
//     ///
//     /// - `self` - this matrix reference
//     /// - `rhs` - a constant reference
//     ///
//     /// # Example
//     ///
//     /// ```
//     /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
//     /// let float = 1.0;
//     /// let matrix2 = &matrix1 + &float;
//     /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
//     /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
//     /// assert_eq!(float, 1.0);
//     /// ```
//     fn add(self, &rhs: &'b T) -> Matrix<<T as Add>::Output> {
//         let mut buffer = Vec::new();
//         for &i in self.buffer.iter() {
//             buffer.push(i + rhs);
//         }
//         Matrix::new(self.dim, buffer)
//     }
// }
<commit_msg>matrix multiply<commit_after>use std::ops::{Add, Mul};

/// A pair of coordinates
#[derive(Clone, Copy)]
pub struct Vec2(pub usize, pub usize);

/// A structure of values
pub struct Matrix<T> {
    /// 2 dimensional array of rows and columns
    dim: Vec2,
    /// `Vector` of values in the `Matrix`
    buffer: Vec<T>,
}

impl <T> Matrix<T> {
    /// Returns a new `Matrix`
    ///
    /// # Arguments
    ///
    /// - `dimensions` - 2 dimensional array of rows and columns
    /// - `buffer` - `Vector` of values
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// ```
    pub fn new(dimensions: Vec2, buffer: Vec<T>) -> Matrix<T> {
        Matrix {
            dim: dimensions,
            buffer: buffer,
        }
    }

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

impl <T> Matrix<T> where T: Copy {
    /// Returns reference to value at `Vec2`
    ///
    /// # Arguments
    ///
    /// - `Vec2` - coordinates of the value in the `Matrix`
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// ```
    pub fn get(&self, Vec2(x, y): Vec2) -> T {
        self.buffer[x * self.dim.1 + y]
    }
}

//////////////
// Addition //
//////////////

impl<T> Add<Matrix<T>> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 + matrix2;
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: Matrix<T>) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b Matrix<T>> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 + &matrix2;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<T> Add<T> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - a constant
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = matrix1 + float;
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// ```
    fn add(self, rhs: T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b T> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - a constant reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = &matrix1 + &float;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// assert_eq!(float, 1.0);
    /// ```
    fn add(self, &rhs: &'b T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

/////////////////////
// Multiplication  //
/////////////////////

impl<T> Mul<Matrix<T>> for Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 * matrix2;
    /// assert_eq!(matrix3.len(), 4);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn mul(self, rhs: Matrix<T>) -> Matrix<T> {
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        assert_eq!(y, x2);
        let mut buffer = Vec::with_capacity(x * y2);
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

impl<'a, 'b, T> Mul<&'b Matrix<T>> for &'a Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 * &matrix2;
    /// assert_eq!(matrix3.len(), 4);
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn mul(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        assert_eq!(y, x2);
        let mut buffer = Vec::with_capacity(x * y2);
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

// impl<T> Add<T> for Matrix<T> where T: Add + Copy {
//     type Output = Matrix<<T as Add>::Output>;
//
//     /// Add Matrix and a constant
//     ///
//     /// # Arguments
//     ///
//     /// - `self` - this matrix
//     /// - `rhs` - a constant
//     ///
//     /// # Example
//     ///
//     /// ```
//     /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
//     /// let float = 1.0;
//     /// let matrix2 = matrix1 + float;
//     /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
//     /// ```
//     fn add(self, rhs: T) -> Matrix<<T as Add>::Output> {
//         let mut buffer = Vec::new();
//         for &i in self.buffer.iter() {
//             buffer.push(i + rhs);
//         }
//         Matrix::new(self.dim, buffer)
//     }
// }
//
// impl<'a, 'b, T> Add<&'b T> for &'a Matrix<T> where T: Add + Copy {
//     type Output = Matrix<<T as Add>::Output>;
//
//     /// Add Matrix and a constant
//     ///
//     /// # Arguments
//     ///
//     /// - `self` - this matrix reference
//     /// - `rhs` - a constant reference
//     ///
//     /// # Example
//     ///
//     /// ```
//     /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
//     /// let float = 1.0;
//     /// let matrix2 = &matrix1 + &float;
//     /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
//     /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
//     /// assert_eq!(float, 1.0);
//     /// ```
//     fn add(self, &rhs: &'b T) -> Matrix<<T as Add>::Output> {
//         let mut buffer = Vec::new();
//         for &i in self.buffer.iter() {
//             buffer.push(i + rhs);
//         }
//         Matrix::new(self.dim, buffer)
//     }
// }
<|endoftext|>


<commit_before>use super::{allocate_shapes, allocate_states, Boundary, Find, Mesh};
use crate::shapes::{Shape, StateOfShape};
use crate::StrError;
use std::ffi::OsStr;

/// Holds all data related to a mesh including element shapes, states, boundaries, and functions to find entities
///
/// This struct is a (high-level) convenience that calls the necessary functions to generate all derived data from a mesh struct.
///
/// The Region basically calls the following functions:
///
/// ```text
/// let shapes = allocate_shapes(&mesh)?;
/// let states = allocate_states(&mesh, &shapes)?;
/// let boundary = Boundary::new(&mesh, &shapes)?;
/// let find = Find::new(&mesh, &boundary)?;
/// ```
pub struct Region {
    /// Holds the raw mesh data
    pub mesh: Mesh,

    /// Holds all shapes of all cells (len = **number of cells**)
    pub shapes: Vec<Shape>,

    /// Holds all states of shapes of all cells (len = **number of cells**)
    pub states: Vec<StateOfShape>,

    /// Holds the boundary data such as points, edges, and faces on boundary
    pub boundary: Boundary,

    /// Allows finding points, edges, and faces on the boundary by giving coordinates or keys
    pub find: Find,
}

impl Region {
    /// Allocates and prepares a new region with a given mesh
    ///
    /// # Examples
    ///
    /// ```
    /// use gemlab::mesh::{At, Cell, Mesh, Point, Region};
    /// use gemlab::shapes::GeoKind;
    /// use gemlab::StrError;
    ///
    /// fn main() -> Result<(), StrError> {
    ///     //  3---------2---------5
    ///     //  |         |         |
    ///     //  |   [0]   |   [1]   |
    ///     //  |         |         |
    ///     //  0---------1---------4
    ///     let mesh = Mesh {
    ///         space_ndim: 2,
    ///         points: vec![
    ///             Point { id: 0, coords: vec![0.0, 0.0] },
    ///             Point { id: 1, coords: vec![1.0, 0.0] },
    ///             Point { id: 2, coords: vec![1.0, 1.0] },
    ///             Point { id: 3, coords: vec![0.0, 1.0] },
    ///             Point { id: 4, coords: vec![2.0, 0.0] },
    ///             Point { id: 5, coords: vec![2.0, 1.0] },
    ///         ],
    ///         cells: vec![
    ///             Cell { id: 0, attribute_id: 1, geo_ndim: 2, points: vec![0, 1, 2, 3] },
    ///             Cell { id: 1, attribute_id: 2, geo_ndim: 2, points: vec![1, 4, 5, 2] },
    ///         ],
    ///     };
    ///     let region = Region::with(mesh)?;
    ///     assert_eq!(region.mesh.space_ndim, 2);
    ///     assert_eq!(region.shapes.len(), 2);
    ///     assert_eq!(region.states.len(), 2);
    ///     assert_eq!(region.shapes[0].kind, GeoKind::Qua4);
    ///     assert_eq!(region.boundary.points.len(), 6);
    ///     assert_eq!(region.boundary.edges.len(), 6);
    ///     assert_eq!(region.boundary.faces.len(), 0);
    ///     assert_eq!(region.boundary.min, &[0.0, 0.0]);
    ///     assert_eq!(region.boundary.max, &[2.0, 1.0]);
    ///     assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
    ///     Ok(())
    /// }
    /// ```
    pub fn with(mesh: Mesh) -> Result<Self, StrError> {
        let shapes = allocate_shapes(&mesh)?;
        let states = allocate_states(&mesh, &shapes)?;
        let boundary = Boundary::new(&mesh, &shapes)?;
        let find = Find::new(&mesh, &boundary)?;
        Ok(Region {
            mesh,
            shapes,
            states,
            boundary,
            find,
        })
    }

    /// Allocates and prepares a new region with a mesh defined in a text string
    #[inline]
    pub fn with_text(mesh_text: &str) -> Result<Self, StrError> {
        let mesh = Mesh::from_text(mesh_text)?;
        Region::with(mesh)
    }

    /// Allocates and prepares a new region with a mesh read from a text file
    ///
    /// # Input
    ///
    /// * `full_path` -- may be a String, &str, or Path
    #[inline]
    pub fn with_text_file<P>(full_path: &P) -> Result<Self, StrError>
    where
        P: AsRef<OsStr> + ?Sized,
    {
        let mesh = Mesh::from_text_file(full_path)?;
        Region::with(mesh)
    }

    /// Allocates and prepares a new region with a mesh read from a binary file
    ///
    /// # Input
    ///
    /// * `full_path` -- may be a String, &str, or Path
    #[inline]
    pub fn with_binary_file<P>(full_path: &P) -> Result<Self, StrError>
    where
        P: AsRef<OsStr> + ?Sized,
    {
        let mesh = Mesh::read(full_path)?;
        Region::with(mesh)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{Mesh, Region};
    use crate::mesh::{At, Samples};
    use crate::StrError;

    #[test]
    fn with_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Samples::two_quads_horizontal();
        let region = Region::with(mesh)?;
        // println!("{:?}", mesh); // WRONG: mesh has been moved into region
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }

    #[test]
    fn with_text_works() -> Result<(), StrError> {
        let mesh = Mesh::from_text(
            "# 1.0  3-----------2-----------5
             #      |           |           |
             #      |    [0]    |    [1]    |  [*] indicates id
             #      |    (1)    |    (2)    |  (*) indicates attribute_id
             #      |           |           |
             # 0.0  0-----------1-----------4
             #     0.0         1.0         2.0
             #
             # header
             # space_ndim npoint ncell
                     2      6     2

             # points
             # id    x   y
             0  0.0 0.0
             1  1.0 0.0
             2  1.0 1.0
             3  0.0 1.0
             4  2.0 0.0
             5  2.0 1.0

             # cells
             # id att geo_ndim nnode  point_ids...
             0   1        2     4  0 1 2 3
             1   2        2     4  1 4 5 2
             ",
        )?;
        let region = Region::with(mesh)?;
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }

    #[test]
    fn with_text_file_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Mesh::from_text_file("./data/meshes/two_quads_horizontal.msh")?;
        let region = Region::with(mesh)?;
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }

    #[test]
    fn with_binary_file_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let full_path = "/tmp/gemlab/test_region_two_quads_horizontal.dat";
        let mesh = Samples::two_quads_horizontal();
        mesh.write(full_path)?;
        let region = Region::with_binary_file(full_path)?;
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }
}
<commit_msg>Fix test<commit_after>use super::{allocate_shapes, allocate_states, Boundary, Find, Mesh};
use crate::shapes::{Shape, StateOfShape};
use crate::StrError;
use std::ffi::OsStr;

/// Holds all data related to a mesh including element shapes, states, boundaries, and functions to find entities
///
/// This struct is a (high-level) convenience that calls the necessary functions to generate all derived data from a mesh struct.
///
/// The Region basically calls the following functions:
///
/// ```text
/// let shapes = allocate_shapes(&mesh)?;
/// let states = allocate_states(&mesh, &shapes)?;
/// let boundary = Boundary::new(&mesh, &shapes)?;
/// let find = Find::new(&mesh, &boundary)?;
/// ```
pub struct Region {
    /// Holds the raw mesh data
    pub mesh: Mesh,

    /// Holds all shapes of all cells (len = **number of cells**)
    pub shapes: Vec<Shape>,

    /// Holds all states of shapes of all cells (len = **number of cells**)
    pub states: Vec<StateOfShape>,

    /// Holds the boundary data such as points, edges, and faces on boundary
    pub boundary: Boundary,

    /// Allows finding points, edges, and faces on the boundary by giving coordinates or keys
    pub find: Find,
}

impl Region {
    /// Allocates and prepares a new region with a given mesh
    ///
    /// # Examples
    ///
    /// ```
    /// use gemlab::mesh::{At, Cell, Mesh, Point, Region};
    /// use gemlab::shapes::GeoKind;
    /// use gemlab::StrError;
    ///
    /// fn main() -> Result<(), StrError> {
    ///     //  3---------2---------5
    ///     //  |         |         |
    ///     //  |   [0]   |   [1]   |
    ///     //  |         |         |
    ///     //  0---------1---------4
    ///     let mesh = Mesh {
    ///         space_ndim: 2,
    ///         points: vec![
    ///             Point { id: 0, coords: vec![0.0, 0.0] },
    ///             Point { id: 1, coords: vec![1.0, 0.0] },
    ///             Point { id: 2, coords: vec![1.0, 1.0] },
    ///             Point { id: 3, coords: vec![0.0, 1.0] },
    ///             Point { id: 4, coords: vec![2.0, 0.0] },
    ///             Point { id: 5, coords: vec![2.0, 1.0] },
    ///         ],
    ///         cells: vec![
    ///             Cell { id: 0, attribute_id: 1, geo_ndim: 2, points: vec![0, 1, 2, 3] },
    ///             Cell { id: 1, attribute_id: 2, geo_ndim: 2, points: vec![1, 4, 5, 2] },
    ///         ],
    ///     };
    ///     let region = Region::with(mesh)?;
    ///     assert_eq!(region.mesh.space_ndim, 2);
    ///     assert_eq!(region.shapes.len(), 2);
    ///     assert_eq!(region.states.len(), 2);
    ///     assert_eq!(region.shapes[0].kind, GeoKind::Qua4);
    ///     assert_eq!(region.boundary.points.len(), 6);
    ///     assert_eq!(region.boundary.edges.len(), 6);
    ///     assert_eq!(region.boundary.faces.len(), 0);
    ///     assert_eq!(region.boundary.min, &[0.0, 0.0]);
    ///     assert_eq!(region.boundary.max, &[2.0, 1.0]);
    ///     assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
    ///     Ok(())
    /// }
    /// ```
    pub fn with(mesh: Mesh) -> Result<Self, StrError> {
        let shapes = allocate_shapes(&mesh)?;
        let states = allocate_states(&mesh, &shapes)?;
        let boundary = Boundary::new(&mesh, &shapes)?;
        let find = Find::new(&mesh, &boundary)?;
        Ok(Region {
            mesh,
            shapes,
            states,
            boundary,
            find,
        })
    }

    /// Allocates and prepares a new region with a mesh defined in a text string
    #[inline]
    pub fn with_text(mesh_text: &str) -> Result<Self, StrError> {
        let mesh = Mesh::from_text(mesh_text)?;
        Region::with(mesh)
    }

    /// Allocates and prepares a new region with a mesh read from a text file
    ///
    /// # Input
    ///
    /// * `full_path` -- may be a String, &str, or Path
    #[inline]
    pub fn with_text_file<P>(full_path: &P) -> Result<Self, StrError>
    where
        P: AsRef<OsStr> + ?Sized,
    {
        let mesh = Mesh::from_text_file(full_path)?;
        Region::with(mesh)
    }

    /// Allocates and prepares a new region with a mesh read from a binary file
    ///
    /// # Input
    ///
    /// * `full_path` -- may be a String, &str, or Path
    #[inline]
    pub fn with_binary_file<P>(full_path: &P) -> Result<Self, StrError>
    where
        P: AsRef<OsStr> + ?Sized,
    {
        let mesh = Mesh::read(full_path)?;
        Region::with(mesh)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{Mesh, Region};
    use crate::mesh::{At, Samples};
    use crate::StrError;

    #[test]
    fn with_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Samples::two_quads_horizontal();
        let region = Region::with(mesh)?;
        // println!("{:?}", mesh); // WRONG: mesh has been moved into region
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }

    #[test]
    fn with_text_works() -> Result<(), StrError> {
        let region = Region::with_text(
            "# 1.0  3-----------2-----------5
             #      |           |           |
             #      |    [0]    |    [1]    |  [*] indicates id
             #      |    (1)    |    (2)    |  (*) indicates attribute_id
             #      |           |           |
             # 0.0  0-----------1-----------4
             #     0.0         1.0         2.0
             #
             # header
             # space_ndim npoint ncell
                        2      6     2

             # points
             # id    x   y
                0  0.0 0.0
                1  1.0 0.0
                2  1.0 1.0
                3  0.0 1.0
                4  2.0 0.0
                5  2.0 1.0

             # cells
             # id att geo_ndim nnode  point_ids...
                0   1        2     4  0 1 2 3
                1   2        2     4  1 4 5 2
             ",
        )?;
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }

    #[test]
    fn with_text_file_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Mesh::from_text_file("./data/meshes/two_quads_horizontal.msh")?;
        let region = Region::with(mesh)?;
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }

    #[test]
    fn with_binary_file_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let full_path = "/tmp/gemlab/test_region_two_quads_horizontal.dat";
        let mesh = Samples::two_quads_horizontal();
        mesh.write(full_path)?;
        let region = Region::with_binary_file(full_path)?;
        assert_eq!(region.mesh.space_ndim, 2);
        assert_eq!(region.shapes.len(), 2);
        assert_eq!(region.states.len(), 2);
        assert_eq!(region.boundary.points.len(), 6);
        assert_eq!(region.boundary.edges.len(), 6);
        assert_eq!(region.boundary.faces.len(), 0);
        assert_eq!(region.find.points(At::XY(0.0, 0.0))?.len(), 1);
        Ok(())
    }
}
<|endoftext|>