<commit_before>//! Combines sequences of arithmetic or logical instructions into single instructions.

use middle::ir::MOpcode;
use middle::ssa::ssa_traits::*;
use middle::ssa::ssastorage::SSAStorage;

use either::*;

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;

mod combine_rules;

type SSAValue = <SSAStorage as SSA>::ValueRef;

/// For every instruction, try to combine one of its operands into itself. This
/// transforms linear data-dependency chains into trees.
pub fn run(ssa: &mut SSAStorage) -> () {
    Combiner::new().run(ssa);
}

/// Represents binary operations that are effectively unary because one of the
/// operands is constant. In other words, represents curried binary operations.
/// e.g. `(|x| 7 & x)`, `(|x| x + 3)`, etc.
#[derive(Clone)]
struct CombinableOpInfo(MOpcode, CombinableOpConstInfo);
#[derive(Clone, Debug)]
enum CombinableOpConstInfo {
    /// no const, like in `(|x| !x)`
    Unary,
    /// const is on the left, like in `(|x| 3 - x)`
    Left(u64),
    /// const is on the right, like in `(|x| x - 3)`
    Right(u64),
}

use self::CombinableOpConstInfo as COCI;

#[derive(Debug)]
struct Combiner {
    /// Nodes that could potentially be combined into another
    combine_candidates: HashMap<SSAValue, (SSAValue, CombinableOpInfo)>,
}

impl Combiner {
    fn new() -> Self {
        Combiner {
            combine_candidates: HashMap::new(),
        }
    }

    /// Calls `visit_node` on every node and replaces the node in the SSA with
    /// its return value.
    fn run(&mut self, ssa: &mut SSAStorage) -> () {
        for node in ssa.inorder_walk() {
            if let Some(repl_node) = self.visit_node(node, ssa) {
                let blk = ssa.block_for(node).unwrap();
                let addr = ssa.address(node).unwrap();
                ssa.replace_value(node, repl_node);
                if !ssa.is_constant(repl_node) && ssa.address(repl_node).is_none() {
                    ssa.insert_into_block(repl_node, blk, addr);
                }
            }
        }
    }

    /// Returns `Some(new_node)` if one of `cur_node`'s operands can be combined
    /// into `cur_node`, resulting in `new_node`; or, if `cur_node` could be
    /// simplified, resulting in `new_node`.
    /// Returns `None` if no simplification can occur.
    fn visit_node(&mut self, cur_node: SSAValue, ssa: &mut SSAStorage) -> Option<SSAValue> {
        // bail if non-combinable
        let extracted = extract_opinfo(cur_node, ssa)?;
        match extracted {
            Left((sub_node, cur_opinfo, cur_vt)) => {
                radeco_trace!(
                    "trying to combine ({:?} = {:?} {:?})",
                    cur_node,
                    sub_node,
                    cur_opinfo
                );
                let opt_new_node = self.make_combined_node(&cur_opinfo, cur_vt, sub_node, ssa);
                match opt_new_node {
                    Some(Left((new_node, new_sub_node, new_opinfo))) => {
                        radeco_trace!(
                            "  {:?} ==> ({:?} = {:?} {:?})",
                            cur_node,
                            new_node,
                            new_sub_node,
                            new_opinfo
                        );
                        self.combine_candidates
                            .insert(new_node, (new_sub_node, new_opinfo));
                        Some(new_node)
                    }
                    Some(Right(new_node)) => {
                        radeco_trace!("  {:?} ==> no-op", cur_node);
                        Some(new_node)
                    }
                    None => {
                        // no change; still add to `combine_candidates`
                        self.combine_candidates
                            .insert(cur_node, (sub_node, cur_opinfo));
                        None
                    }
                }
            }
            Right(c_val) => {
                // combined to constant
                radeco_trace!("{:?} = {:#x}", cur_node, c_val);
                let c_node = ssa.insert_const(c_val)?;
                Some(c_node)
            }
        }
    }

    /// Returns `Left(new_node, new_sub_node, new_opinfo)` if `cur_opinfo`
    /// combined with an operand or if `cur_opinfo` was simplified.
    /// Returns `Right(new_node)` if `cur_opinfo` canceled with an
    /// operand to make a no-op or was originally a no-op.
    /// Returns `None` if no combination or simplification exists.
    fn make_combined_node(
        &self,
        cur_opinfo: &CombinableOpInfo,
        cur_vt: ValueInfo,
        sub_node: SSAValue,
        ssa: &mut SSAStorage,
    ) -> Option<Either<(SSAValue, SSAValue, CombinableOpInfo), SSAValue>> {
        let (new_sub_node, new_opinfo) = self.combine_candidates
            .get(&sub_node)
            .and_then(|(sub_sub_node, sub_opinfo)| {
                combine_rules::combine_opinfo(cur_opinfo, sub_opinfo).map(|new_opinfo| {
                    radeco_trace!(
                        "    combined ({:?} {:?}) into ({:?})",
                        sub_opinfo,
                        cur_opinfo,
                        new_opinfo
                    );
                    (*sub_sub_node, Cow::Owned(new_opinfo))
                })
            })
            .unwrap_or((sub_node, Cow::Borrowed(cur_opinfo)));

        // simplify
        match simplify_opinfo(&new_opinfo) {
            Some(Some(simpl_new_opinfo)) => {
                radeco_trace!(
                    "    simplified ({:?}) into ({:?})",
                    new_opinfo,
                    simpl_new_opinfo
                );
                // make the new node
                let CombinableOpInfo(new_opcode, new_coci) = simpl_new_opinfo.clone();
                let new_node = ssa.insert_op(new_opcode, cur_vt, None)?;
                match new_coci {
                    COCI::Unary => {
                        ssa.op_use(new_node, 0, sub_node);
                    }
                    COCI::Left(new_c) => {
                        let new_cnode = ssa.insert_const(new_c)?;
                        ssa.op_use(new_node, 0, new_cnode);
                        ssa.op_use(new_node, 1, new_sub_node);
                    }
                    COCI::Right(new_c) => {
                        let new_cnode = ssa.insert_const(new_c)?;
                        ssa.op_use(new_node, 0, new_sub_node);
                        ssa.op_use(new_node, 1, new_cnode);
                    }
                };
                Some(Left((new_node, new_sub_node, simpl_new_opinfo)))
            }
            Some(None) => {
                radeco_trace!("    simplified ({:?}) into no-op", new_opinfo);
                Some(Right(new_sub_node))
            }
            None => {
                // no simplification
                None
            }
        }
    }
}

/// Returns an equivalent `CombinableOpInfo`, but "simpler" in some sence.
/// Currently, this converts `OpAdd`s or `OpSub`s with "negative" constants into
/// equivalent operations with positive constants.
/// Returns `Some(None)` if `info` is a no-op.
/// Returns `None` if no simplification exists.
fn simplify_opinfo(info: &CombinableOpInfo) -> Option<Option<CombinableOpInfo>> {
    use self::CombinableOpConstInfo as COCI;
    use self::CombinableOpInfo as COI;
    use middle::ir::MOpcode::*;

    match info {
        COI(OpAdd, COCI::Left(0))
        | COI(OpAdd, COCI::Right(0))
        | COI(OpSub, COCI::Right(0))
        | COI(OpAnd, COCI::Left(0xFFFFFFFFFFFFFFFF))
        | COI(OpAnd, COCI::Right(0xFFFFFFFFFFFFFFFF))
        | COI(OpOr, COCI::Left(0))
        | COI(OpOr, COCI::Right(0))
        | COI(OpXor, COCI::Left(0))
        | COI(OpXor, COCI::Right(0)) => Some(None),
        COI(OpAdd, COCI::Left(c)) | COI(OpAdd, COCI::Right(c)) if *c > u64::max_value() / 2 => {
            let c = OpSub.eval_binop(0, *c).unwrap();
            Some(Some(COI(OpSub, COCI::Right(c))))
        }
        COI(OpSub, COCI::Right(c)) if *c > u64::max_value() / 2 => {
            let c = OpSub.eval_binop(0, *c).unwrap();
            Some(Some(COI(OpAdd, COCI::Left(c))))
        }
        _ => None,
    }
}

/// Returns `Some(Left(_))` if `cur_node` has exactly one non-const operand.
/// Returns `Some(Right(_))` if `cur_node` has all const operands.
/// Returns `None` if `cur_node` is non-combinable.
fn extract_opinfo(
    cur_node: SSAValue,
    ssa: &SSAStorage,
) -> Option<Either<(SSAValue, CombinableOpInfo, ValueInfo), u64>> {
    // bail if non-`NodeType::Op`
    let (cur_opcode, cur_vt) = extract_opcode(cur_node, ssa)?;
    let cur_operands = ssa.operands_of(cur_node);
    match cur_operands.as_slice() {
        &[sub_node] => {
            let cur_opinfo = CombinableOpInfo(cur_opcode, COCI::Unary);
            Some(Left((sub_node, cur_opinfo, cur_vt)))
        }
        &[sub_node1, sub_node2] => {
            match (ssa.constant(sub_node1), ssa.constant(sub_node2)) {
                (Some(c1), Some(c2)) => {
                    // this is const_prop's job, but we can do this here too
                    // bail if `cur_opcode` is non-evalable, since that also
                    // implies it's non-combinable
                    let res_val = cur_opcode.eval_binop(c1, c2)?;
                    Some(Right(res_val))
                }
                (None, Some(c)) => {
                    let cur_opinfo = CombinableOpInfo(cur_opcode, COCI::Right(c));
                    Some(Left((sub_node1, cur_opinfo, cur_vt)))
                }
                (Some(c), None) => {
                    let cur_opinfo = CombinableOpInfo(cur_opcode, COCI::Left(c));
                    Some(Left((sub_node2, cur_opinfo, cur_vt)))
                }
                (None, None) => None,
            }
        }
        _ => None,
    }
}

fn extract_opcode(node: SSAValue, ssa: &SSAStorage) -> Option<(MOpcode, ValueInfo)> {
    if let NodeData {
        vt,
        nt: NodeType::Op(opcode),
    } = ssa.node_data(node).ok()?
    {
        Some((opcode, vt))
    } else {
        None
    }
}

impl fmt::Debug for CombinableOpInfo {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.1 {
            COCI::Unary => fmt.write_fmt(format_args!("-> ({:?} .)", self.0)),
            COCI::Left(c) => fmt.write_fmt(format_args!("-> ({:#x} {:?} .)", c, self.0)),
            COCI::Right(c) => fmt.write_fmt(format_args!("-> (. {:?} {:#x})", self.0, c)),
        }
    }
}
<commit_msg>Fix `inst_combine` not combining when not also simplifying<commit_after>//! Combines sequences of arithmetic or logical instructions into single instructions.

use middle::ir::MOpcode;
use middle::ssa::ssa_traits::*;
use middle::ssa::ssastorage::SSAStorage;

use either::*;

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;

mod combine_rules;

type SSAValue = <SSAStorage as SSA>::ValueRef;

/// For every instruction, try to combine one of its operands into itself. This
/// transforms linear data-dependency chains into trees.
pub fn run(ssa: &mut SSAStorage) -> () {
    Combiner::new().run(ssa);
}

/// Represents binary operations that are effectively unary because one of the
/// operands is constant. In other words, represents curried binary operations.
/// e.g. `(|x| 7 & x)`, `(|x| x + 3)`, etc.
#[derive(Clone)]
struct CombinableOpInfo(MOpcode, CombinableOpConstInfo);
#[derive(Clone, Debug)]
enum CombinableOpConstInfo {
    /// no const, like in `(|x| !x)`
    Unary,
    /// const is on the left, like in `(|x| 3 - x)`
    Left(u64),
    /// const is on the right, like in `(|x| x - 3)`
    Right(u64),
}

use self::CombinableOpConstInfo as COCI;

#[derive(Debug)]
struct Combiner {
    /// Nodes that could potentially be combined into another
    combine_candidates: HashMap<SSAValue, (SSAValue, CombinableOpInfo)>,
}

impl Combiner {
    fn new() -> Self {
        Combiner {
            combine_candidates: HashMap::new(),
        }
    }

    /// Calls `visit_node` on every node and replaces the node in the SSA with
    /// its return value.
    fn run(&mut self, ssa: &mut SSAStorage) -> () {
        for node in ssa.inorder_walk() {
            if let Some(repl_node) = self.visit_node(node, ssa) {
                let blk = ssa.block_for(node).unwrap();
                let addr = ssa.address(node).unwrap();
                ssa.replace_value(node, repl_node);
                if !ssa.is_constant(repl_node) && ssa.address(repl_node).is_none() {
                    ssa.insert_into_block(repl_node, blk, addr);
                }
            }
        }
    }

    /// Returns `Some(new_node)` if one of `cur_node`'s operands can be combined
    /// into `cur_node`, resulting in `new_node`; or, if `cur_node` could be
    /// simplified, resulting in `new_node`.
    /// Returns `None` if no simplification can occur.
    fn visit_node(&mut self, cur_node: SSAValue, ssa: &mut SSAStorage) -> Option<SSAValue> {
        // bail if non-combinable
        let extracted = extract_opinfo(cur_node, ssa)?;
        match extracted {
            Left((sub_node, cur_opinfo, cur_vt)) => {
                radeco_trace!(
                    "trying to combine ({:?} = {:?} {:?})",
                    cur_node,
                    sub_node,
                    cur_opinfo
                );
                let opt_new_node = self.make_combined_node(&cur_opinfo, cur_vt, sub_node, ssa);
                match opt_new_node {
                    Some(Left((new_node, new_sub_node, new_opinfo))) => {
                        radeco_trace!(
                            "  {:?} ==> ({:?} = {:?} {:?})",
                            cur_node,
                            new_node,
                            new_sub_node,
                            new_opinfo
                        );
                        self.combine_candidates
                            .insert(new_node, (new_sub_node, new_opinfo));
                        Some(new_node)
                    }
                    Some(Right(new_node)) => {
                        radeco_trace!("  {:?} ==> no-op", cur_node);
                        Some(new_node)
                    }
                    None => {
                        // no change; still add to `combine_candidates`
                        self.combine_candidates
                            .insert(cur_node, (sub_node, cur_opinfo));
                        None
                    }
                }
            }
            Right(c_val) => {
                // combined to constant
                radeco_trace!("{:?} = {:#x}", cur_node, c_val);
                let c_node = ssa.insert_const(c_val)?;
                Some(c_node)
            }
        }
    }

    /// Returns `Left(new_node, new_sub_node, new_opinfo)` if `cur_opinfo`
    /// combined with an operand or if `cur_opinfo` was simplified.
    /// Returns `Right(new_node)` if `cur_opinfo` canceled with an
    /// operand to make a no-op or was originally a no-op.
    /// Returns `None` if no combination or simplification exists.
    fn make_combined_node(
        &self,
        cur_opinfo: &CombinableOpInfo,
        cur_vt: ValueInfo,
        sub_node: SSAValue,
        ssa: &mut SSAStorage,
    ) -> Option<Either<(SSAValue, SSAValue, CombinableOpInfo), SSAValue>> {
        let (new_opinfo, new_sub_node) = self
            .combine_opinfo(cur_opinfo, sub_node)
            .map(|(oi, sn)| (Cow::Owned(oi), sn))
            .unwrap_or((Cow::Borrowed(cur_opinfo), sub_node));

        // simplify
        match simplify_opinfo(&new_opinfo) {
            Some(Some(simpl_new_opinfo)) => {
                radeco_trace!(
                    "    simplified ({:?}) into ({:?})",
                    new_opinfo,
                    simpl_new_opinfo
                );
                // make the new node
                let new_node =
                    make_opinfo_node(cur_vt, simpl_new_opinfo.clone(), new_sub_node, ssa)?;
                Some(Left((new_node, new_sub_node, simpl_new_opinfo)))
            }
            Some(None) => {
                radeco_trace!("    simplified ({:?}) into no-op", new_opinfo);
                Some(Right(new_sub_node))
            }
            None => {
                // no simplification
                match new_opinfo {
                    Cow::Borrowed(_) => None,
                    Cow::Owned(new_opinfo) => {
                        // combined, but no further simplification
                        let new_node =
                            make_opinfo_node(cur_vt, new_opinfo.clone(), new_sub_node, ssa)?;
                        Some(Left((new_node, new_sub_node, new_opinfo)))
                    }
                }
            }
        }
    }

    /// Tries to combine `sub_node` into `cur_opinfo`.
    /// Returns `None` if no combination exists.
    fn combine_opinfo(
        &self,
        cur_opinfo: &CombinableOpInfo,
        sub_node: SSAValue,
    ) -> Option<(CombinableOpInfo, SSAValue)> {
        let &(sub_sub_node, ref sub_opinfo) = self.combine_candidates.get(&sub_node)?;
        let new_opinfo = combine_rules::combine_opinfo(cur_opinfo, sub_opinfo)?;
        radeco_trace!(
            "    combined ({:?} {:?}) into ({:?})",
            sub_opinfo,
            cur_opinfo,
            new_opinfo
        );
        Some((new_opinfo, sub_sub_node))
    }
}

/// Creates an SSA node from the given `CombinableOpInfo`.
/// Returns `None` on SSA error.
fn make_opinfo_node(
    vt: ValueInfo,
    opinfo: CombinableOpInfo,
    sub_node: SSAValue,
    ssa: &mut SSAStorage,
) -> Option<SSAValue> {
    let ret = ssa.insert_op(opinfo.0, vt, None)?;
    match opinfo.1 {
        COCI::Unary => {
            ssa.op_use(ret, 0, sub_node);
        }
        COCI::Left(new_c) => {
            let new_cnode = ssa.insert_const(new_c)?;
            ssa.op_use(ret, 0, new_cnode);
            ssa.op_use(ret, 1, sub_node);
        }
        COCI::Right(new_c) => {
            let new_cnode = ssa.insert_const(new_c)?;
            ssa.op_use(ret, 0, sub_node);
            ssa.op_use(ret, 1, new_cnode);
        }
    };
    Some(ret)
}

/// Returns an equivalent `CombinableOpInfo`, but "simpler" in some sence.
/// Currently, this converts `OpAdd`s or `OpSub`s with "negative" constants into
/// equivalent operations with positive constants.
/// Returns `Some(None)` if `info` is a no-op.
/// Returns `None` if no simplification exists.
fn simplify_opinfo(info: &CombinableOpInfo) -> Option<Option<CombinableOpInfo>> {
    use self::CombinableOpConstInfo as COCI;
    use self::CombinableOpInfo as COI;
    use middle::ir::MOpcode::*;

    match info {
        COI(OpAdd, COCI::Left(0))
        | COI(OpAdd, COCI::Right(0))
        | COI(OpSub, COCI::Right(0))
        | COI(OpAnd, COCI::Left(0xFFFFFFFFFFFFFFFF))
        | COI(OpAnd, COCI::Right(0xFFFFFFFFFFFFFFFF))
        | COI(OpOr, COCI::Left(0))
        | COI(OpOr, COCI::Right(0))
        | COI(OpXor, COCI::Left(0))
        | COI(OpXor, COCI::Right(0)) => Some(None),
        COI(OpAdd, COCI::Left(c)) | COI(OpAdd, COCI::Right(c)) if *c > u64::max_value() / 2 => {
            let c = OpSub.eval_binop(0, *c).unwrap();
            Some(Some(COI(OpSub, COCI::Right(c))))
        }
        COI(OpSub, COCI::Right(c)) if *c > u64::max_value() / 2 => {
            let c = OpSub.eval_binop(0, *c).unwrap();
            Some(Some(COI(OpAdd, COCI::Left(c))))
        }
        _ => None,
    }
}

/// Returns `Some(Left(_))` if `cur_node` has exactly one non-const operand.
/// Returns `Some(Right(_))` if `cur_node` has all const operands.
/// Returns `None` if `cur_node` is non-combinable.
fn extract_opinfo(
    cur_node: SSAValue,
    ssa: &SSAStorage,
) -> Option<Either<(SSAValue, CombinableOpInfo, ValueInfo), u64>> {
    // bail if non-`NodeType::Op`
    let (cur_opcode, cur_vt) = extract_opcode(cur_node, ssa)?;
    let cur_operands = ssa.operands_of(cur_node);
    match cur_operands.as_slice() {
        &[sub_node] => {
            let cur_opinfo = CombinableOpInfo(cur_opcode, COCI::Unary);
            Some(Left((sub_node, cur_opinfo, cur_vt)))
        }
        &[sub_node1, sub_node2] => {
            match (ssa.constant(sub_node1), ssa.constant(sub_node2)) {
                (Some(c1), Some(c2)) => {
                    // this is const_prop's job, but we can do this here too
                    // bail if `cur_opcode` is non-evalable, since that also
                    // implies it's non-combinable
                    let res_val = cur_opcode.eval_binop(c1, c2)?;
                    Some(Right(res_val))
                }
                (None, Some(c)) => {
                    let cur_opinfo = CombinableOpInfo(cur_opcode, COCI::Right(c));
                    Some(Left((sub_node1, cur_opinfo, cur_vt)))
                }
                (Some(c), None) => {
                    let cur_opinfo = CombinableOpInfo(cur_opcode, COCI::Left(c));
                    Some(Left((sub_node2, cur_opinfo, cur_vt)))
                }
                (None, None) => None,
            }
        }
        _ => None,
    }
}

fn extract_opcode(node: SSAValue, ssa: &SSAStorage) -> Option<(MOpcode, ValueInfo)> {
    if let NodeData {
        vt,
        nt: NodeType::Op(opcode),
    } = ssa.node_data(node).ok()?
    {
        Some((opcode, vt))
    } else {
        None
    }
}

impl fmt::Debug for CombinableOpInfo {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.1 {
            COCI::Unary => fmt.write_fmt(format_args!("-> ({:?} .)", self.0)),
            COCI::Left(c) => fmt.write_fmt(format_args!("-> ({:#x} {:?} .)", c, self.0)),
            COCI::Right(c) => fmt.write_fmt(format_args!("-> (. {:?} {:#x})", self.0, c)),
        }
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;
use std::io::File;
use std::io::signal::{Listener, Interrupt};

struct Shell {
    cmd_prompt: ~str,
    log:        ~[~str],
}

impl Shell {

    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            log: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt); // prints 'gash >'
            io::stdio::flush();

            let line = stdin.read_line().unwrap(); // reads whats on the line
            let cmd_line = line.trim().to_owned();  // removes leading and trailing whitespace
            let user_input: ~[&str] = cmd_line.split(' ').collect();
            let mut index: uint = 0;
            let mut line: ~str = ~"";

            for &string in user_input.iter(){

                match string {

                    "<" => {
                        let file  = user_input[index+1].to_owned(); // get file name
                        let command = line.trim().to_owned();
                        let message = read_file(file);
                        println(message);

                        line = ~"";
                    }

                    ">" => {
			            let file = user_input[index + 1].to_owned();
			            let command = line.trim().to_owned();
			            let message = self.find_prog(command, true).to_owned();
                        write_file(file,message);
                        line = ~"";
                        user_input.iter().next();
                    }

                    "|" => {
                        let command = line.trim().to_owned();
                        let mut command2: ~str = ~"";
                        let length = user_input.len();

                        for i in range(index+1,length){
                            match user_input[i]{
                                "<" => {break;}
                                ">" =>{break;}
                                "|" => {break;}
                                _   => {command2 = command2 + " " + user_input[i];}
                            }
                        }
                        command2 = command2.trim().to_owned();
                        let message = self.find_prog(command, true).to_owned();
                        line = ~"";
                    }
                    _ => {
                        line = line + " " + string;
                    }
                }
                index += 1;
            }

            let result = self.find_prog(line.trim(),false);
            match result {
                ~"return" => {return}
                ~"continue" => {continue;}
                _          => {continue;}
            }

        }
    }

    fn find_prog(&mut self, cmd_line : &str, output: bool) -> ~str{
         let program = cmd_line.splitn(' ', 1).nth(0).expect("no program"); // get command

         match program {
                ""      =>  { return ~"continue"; }
                "exit"  =>  { return ~"return"; }
                "history" => {
                    self.log.push(cmd_line.to_owned());
                    return self.run_history(output);
                }
                "cd" => {
                    self.log.push(cmd_line.to_owned());
                    self.run_cd(cmd_line);
                }
                _       =>  {
                    self.log.push(cmd_line.to_owned());
                    return self.run_cmdline(cmd_line, output);
                }
            }
        ~"fine"
    }

    fn run_cmdline(&mut self, cmd_line: &str, output: bool) -> ~str {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

	let length = argv.len()-1;

    	if argv[length] == ~"&" {
	    argv.remove(length);
            let program: ~str = argv.remove(0);
	    let argv2 = argv.clone();
	    if self.cmd_exists(program){

		spawn(proc() {run::process_status(program, argv2);});

	    }
            else {
		println!("{:s}: command not found", program);
            }
	return ~"none";
	}
	else{
        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            return self.run_cmd(program, argv, output);
        }
	}
	return ~"none";
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str], output: bool)->~str {
        if self.cmd_exists(program) {
	    if output == false {
            run::process_status(program, argv);
	    return ~"none";
	    }
	    else {
	    	let output = run::process_output(program, argv);
	  	let output_str = output.unwrap().output;
		return std::str::from_utf8(output_str).to_owned();
	    }
        } else {
            println!("{:s}: command not found", program);
        }
	return ~"none";
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn run_history(&mut self, output: bool)-> ~str{
	if output == false{
        	for i in range(0, self.log.len()) {
            		println!("{}", self.log[i]);
        	}
		return ~"none";
	}
	else {
		let mut out: ~str = ~"";
		for i in range(0, self.log.len()){
			out = out + self.log[i].to_owned();
		}
		return out;
	}
    }

    fn run_cd(&mut self, cmd_line: &str) {
         let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {

            if argv.len() == 1 {
                self.go_to_home_dir();
                return ;
            }

            let string: ~str = argv.remove(1);
            if string == ~"$HOME" || string == ~"$home"{
                self.go_to_home_dir();
                return ;
            }
            let path = ~Path::new(string);
            if (path.exists()){
                let success = std::os::change_dir(path);
                if !success {
                    println("Invalid path");
                }
            }
        }
        else {
            println("Invalid input");
        }
    }

    fn go_to_home_dir(&mut self){
        match std::os::homedir() {
            Some(path) => {
                    std::os::change_dir(&path);
               }
             None => {
                    println("$HOME is not set");
               }
         }
    }

}

fn write_file(filename: ~str, message: ~str){

    match File::create(&Path::new(filename)) {
        Some(mut file) => {
            file.write_str(message);
        }
        None =>{
            println("Opening file failed!");
        }
    }
}

fn read_file(filename: ~str) -> ~str{

    let path = Path::new(filename);
    match File::open(&path) {
        Some(file) => {
            let mut reader = BufferedReader::new(file);
            let input = reader.read_to_str();
            return input;
        }
        None =>{
            println("Opening file failed");
            return ~"";
        }
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    spawn(proc () {
    let mut listener = Listener::new();
        listener.register(Interrupt);
    loop{
        match listener.port.recv() {
            Interrupt => println!("Got interrupt"),
            _ => (),
        }
    }
   });

    match opt_cmd_line {
        Some(cmd_line) => {Shell::new("").run_cmdline(cmd_line, false);}
        None           => {Shell::new("gash > ").run();}
    }
}
<commit_msg>update with shitty pipes<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;
use std::io::File;
use std::io::signal::{Listener, Interrupt};

struct Shell {
    cmd_prompt: ~str,
    log:        ~[~str],
}

impl Shell {

    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            log: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt); // prints 'gash >'
            io::stdio::flush();

            let line = stdin.read_line().unwrap(); // reads whats on the line
            let cmd_line = line.trim().to_owned();  // removes leading and trailing whitespace
            let user_input: ~[&str] = cmd_line.split(' ').collect();
            let mut line: ~str = ~"";
            let length: uint = user_input.len();
            let mut i : uint = 0;

            while (i < length){

                let string = user_input[i].clone();
                let mut input = ~"";
                match string {

                    "<" => {
                        if !(i < length-1)
                            {println!("invalid command");}

                        let file  = user_input[i+1].to_owned(); // get file name
                        let command = line.trim().to_owned();
                        line = command + " " + file;
                        i += 1;
                    }

                    ">" => {
                        if !(i < length-1)
                            {println!("invalid command");}

			            let file = user_input[i + 1].to_owned();
			            let command = line.trim().to_owned();
			            let message = self.find_prog(command, true).to_owned();

                        if message == ~"none"{
                            i = length;
                        }

                        write_file(file,message);
                        line = ~"";
                        i += 1;
                    }

                    "|" => {

                        let command = line.trim().to_owned();
                        let mut command2: ~str = ~"";

                        for k in range(i + 1,length){
                            match user_input[k]{
                                "<" => {break;}
                                ">" =>{break;}
                                "|" => {break;}
                                _   => {command2 = command2 + " " + user_input[k];}
                            }
                            i = k;
                        }

                        command2 = command2.trim().to_owned();
                        let mut message = self.find_prog(command, true).to_owned();

                        if message == ~"none"{
                            i = length;
                        }

                        match File::create(&Path::new("f.md")) {
                            Some(mut file) => {
                                file.write_str(message);
                            }
                            None =>{
                                println("Opening file failed!");
                            }
                        }

                        //println(command2);
                        message = self.find_prog(command2 + " " + "f.md", true).to_owned();
                        self.find_prog("rm f.md", true);
                        println!("{}", message);
                        line = ~"";
                    }

                    _ => {
                        line = line + " " + string;
                    }
                }
                i += 1;
            }

            let result = self.find_prog(line.trim(),false);
            match result {
                ~"return" => {
                    println("exit pls");
                    return;}
                //~"continue" => {continue;}
                _          => {}
            }
        }
    }

    fn find_prog(&mut self, cmd_line : &str, output: bool) -> ~str{
         let program = cmd_line.splitn(' ', 1).nth(0).expect("no program"); // get command

         match program {
                ""      =>  { return ~"continue"; }
                "exit"  =>  { return ~"return"; }
                "history" => {
                    self.log.push(cmd_line.to_owned());
                    return self.run_history(output);
                }
                "cd" => {
                    self.log.push(cmd_line.to_owned());
                    self.run_cd(cmd_line);
                }
                _       =>  {
                    self.log.push(cmd_line.to_owned());
                    return self.run_cmdline(cmd_line, output);
                }
            }
        ~"fine"
    }

    fn run_cmdline(&mut self, cmd_line: &str, output: bool) -> ~str {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

	let length = argv.len()-1;

    	if argv[length] == ~"&" {
	    argv.remove(length);
            let program: ~str = argv.remove(0);
	    let argv2 = argv.clone();

	    if self.cmd_exists(program){

		spawn(proc() {run::process_status(program, argv2);});

	    }
            else {
		println!("{:s}: command not found", program);
            }

	return ~"none";
	}

	else{
        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            return self.run_cmd(program, argv, output);
        }
	}
	return ~"none";
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str], output: bool)->~str {
        if self.cmd_exists(program) {
	    if output == false {
            run::process_status(program, argv);
	    return ~"none";
	    }
	    else {
	    	let output = run::process_output(program, argv);
	  	let output_str = output.unwrap().output;
		return std::str::from_utf8(output_str).to_owned();
	    }
        } else {
            println!("{:s}: command not found", program);
        }
	return ~"none";
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn run_history(&mut self, output: bool)-> ~str{
	if output == false{
        	for i in range(0, self.log.len()) {
            		println!("{}", self.log[i]);
        	}
		return ~"none";
	}
	else {
		let mut out: ~str = ~"";
		for i in range(0, self.log.len()){
			out = out + self.log[i].to_owned();
		}
		return out;
	}
    }

    fn run_cd(&mut self, cmd_line: &str) {
         let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {

            if argv.len() == 1 {
                self.go_to_home_dir();
                return ;
            }

            let string: ~str = argv.remove(1);
            if string == ~"$HOME" || string == ~"$home"{
                self.go_to_home_dir();
                return ;
            }
            let path = ~Path::new(string);
            if (path.exists()){
                let success = std::os::change_dir(path);
                if !success {
                    println("Invalid path");
                }
            }
        }
        else {
            println("Invalid input");
        }
    }

    fn go_to_home_dir(&mut self){
        match std::os::homedir() {
            Some(path) => {
                    std::os::change_dir(&path);
               }
             None => {
                    println("$HOME is not set");
               }
         }
    }

}

fn write_file(filename: ~str, message: ~str){

    match File::create(&Path::new(filename)) {
        Some(mut file) => {
            file.write_str(message);
        }
        None =>{
            println("Opening file failed!");
        }
    }
}

/*
fn read_file(filename: ~str) -> ~str{

    let path = Path::new(filename);
    match File::open(&path) {
        Some(file) => {
            let mut reader = BufferedReader::new(file);
            let input = reader.read_to_str();
            return input;
        }
        None =>{
            println("Opening file failed");
            return ~"";
        }
    }
}
*/

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    spawn(proc () {
    let mut listener = Listener::new();
        listener.register(Interrupt);
    loop{
        match listener.port.recv() {
            Interrupt => print!(""),
            _ => (),
        }
    }
   });

    match opt_cmd_line {
        Some(cmd_line) => {Shell::new("").run_cmdline(cmd_line, false);}
        None           => {Shell::new("gash > ").run();}
    }
}
<|endoftext|>


<commit_before>extern mod crypto;

use crypto::hash;

pub fn hmac(key: &[u8]) {
    let h = hash::Hasher(hash::SHA1);
}

fn main() {
    io::println("Hi?");
}
<commit_msg>Initial attempt at FFIing OpenSSL HMAC<commit_after>extern mod crypto;

use crypto::hash::HashType;

#[allow(non_camel_case_types)]
type EVP_MD_CTX = *libc::c_void;

#[allow(non_camel_case_types)]
type EVP_MD = *libc::c_void;

#[allow(non_camel_case_types)]
struct HMAC_CTX {
    mut md: EVP_MD,
    mut md_ctx: EVP_MD_CTX,
    mut i_ctx: EVP_MD_CTX,
    mut o_ctx: EVP_MD_CTX,
    mut key_length: libc::c_uint,
    mut key: [libc::c_uchar * 128]
}

#[link_name = "crypto"]
#[abi = "cdecl"]
extern mod libcrypto {

    fn HMAC_CTX_init(ctx: *mut HMAC_CTX, key: *u8, keylen: libc::c_int, md: EVP_MD);

    fn HMAC_Update(ctx: *mut HMAC_CTX, input: *u8, len: libc::c_uint);

    fn HMAC_Final(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut libc::c_uint);
}

// fixme copied from gitcrypto hash.rs
fn evpmd(t: HashType) -> (EVP_MD, uint) {
    match t {
        MD5 => (crypto::hash::libcrypto::EVP_md5(), 16u),
        SHA1 => (libcrypto::EVP_sha1(), 20u),
        SHA224 => (libcrypto::EVP_sha224(), 28u),
        SHA256 => (libcrypto::EVP_sha256(), 32u),
        SHA384 => (libcrypto::EVP_sha384(), 48u),
        SHA512 => (libcrypto::EVP_sha512(), 64u),
    }
}

pub struct HMAC {
    priv mut ctx: HMAC_CTX,
    priv len: uint,
}

pub fn HMAC(ht: HashType, key: ~[u8]) -> HMAC {
    unsafe {

        let (evp, mdlen) = crypto::hash::evpmd(ht);

        let mut ctx : HMAC_CTX = HMAC_CTX {
            mut md: ptr::null(),
            mut md_ctx: ptr::null(),
            mut i_ctx: ptr::null(),
            mut o_ctx: ptr::null(),
            mut key_length: 0,
            mut key: [0u8, .. 128]
        };

        libcrypto::HMAC_CTX_init(&mut ctx,
                                 vec::raw::to_ptr(key),
                                 key.len() as libc::c_int,
                                 evp);

        HMAC { ctx: ctx, len: mdlen }
    }
}

pub impl HMAC {
    fn update(data: &[u8]) unsafe {
        do vec::as_imm_buf(data) |pdata, len| {
            libcrypto::HMAC_Update(&mut self.ctx, pdata, len as libc::c_uint)
        }
    }

    fn final() -> ~[u8] unsafe {
        let mut res = vec::from_elem(self.len, 0u8);
        let mut outlen: libc::c_uint = 0;
        do vec::as_mut_buf(res) |pres, _len| {
            libcrypto::HMAC_Final(&mut self.ctx, pres, &mut outlen);
            assert self.len == outlen as uint
        }
        res
    }
}

fn main() {
    let h = HMAC(crypto::hash::SHA512, ~[00u8]);

    h.update(~[00u8]);

    io::println(fmt!("%?", h.final()))
}<|endoftext|>


<commit_before>use std::any::Any;
use std::fmt;
use std::io::Read;
use std::io::Write;

#[cfg(feature = "bytes")]
use bytes::Bytes;

use clear::Clear;
use reflect::ProtobufValue;
use unknown::UnknownFields;
use stream::WithCodedInputStream;
use stream::WithCodedOutputStream;
use stream::CodedInputStream;
use stream::CodedOutputStream;
use stream::with_coded_output_stream_to_bytes;
use error::ProtobufError;
use error::ProtobufResult;
use reflect::MessageDescriptor;

/// Trait implemented for all generated structs for protobuf messages.
/// Also, generated messages implement `Clone + Default + PartialEq`
pub trait Message : fmt::Debug + Clear + Send + Sync + ProtobufValue {
    /// Message descriptor for this message, used for reflection.
    fn descriptor(&self) -> &'static MessageDescriptor;

    /// True iff all required fields are initialized.
    /// Always returns `true` for protobuf 3.
    fn is_initialized(&self) -> bool;

    /// Update this message object with fields read from given stream.
    fn merge_from(&mut self, is: &mut CodedInputStream) -> ProtobufResult<()>;

    /// Write message to the stream.
    ///
    /// Sizes of this messages and nested messages must be cached
    /// by calling `compute_size` prior to this call.
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> ProtobufResult<()>;

    /// Compute and cache size of this message and all nested messages
    fn compute_size(&self) -> u32;

    /// Get size previously computed by `compute_size`.
    fn get_cached_size(&self) -> u32;

    /// Write the message to the stream.
    ///
    /// Results in error if message is not fully initialized.
    fn write_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        self.check_initialized()?;

        // cache sizes
        self.compute_size();
        // TODO: reserve additional
        self.write_to_with_cached_sizes(os)?;

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    /// Write the message to the stream prepending the message with message length
    /// encoded as varint.
    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        let size = self.compute_size();
        os.write_raw_varint32(size)?;
        self.write_to_with_cached_sizes(os)?;

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    /// Write the message to the vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> ProtobufResult<()> {
        let mut os = CodedOutputStream::vec(vec);
        self.write_length_delimited_to(&mut os)?;
        os.flush()?;
        Ok(())
    }

    /// Update this message object with fields read from given stream.
    fn merge_from_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    /// Check if all required fields of this object are initialized.
    fn check_initialized(&self) -> ProtobufResult<()> {
        if !self.is_initialized() {
            Err(ProtobufError::message_not_initialized(self.descriptor().name()))
        } else {
            Ok(())
        }
    }

    /// Write the message to the writer.
    fn write_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_vec(&self, v: &mut Vec<u8>) -> ProtobufResult<()> {
        v.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        self.check_initialized()?;

        let size = self.compute_size() as usize;
        let mut v = Vec::with_capacity(size);
        // skip zerofill
        unsafe {
            v.set_len(size);
        }
        {
            let mut os = CodedOutputStream::bytes(&mut v);
            self.write_to_with_cached_sizes(&mut os)?;
            os.check_eof();
        }
        Ok(v)
    }

    /// Write the message to the writer, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
    }

    /// Write the message to the bytes vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        with_coded_output_stream_to_bytes(|os| self.write_length_delimited_to(os))
    }

    /// Get a reference to unknown fields.
    fn get_unknown_fields<'s>(&'s self) -> &'s UnknownFields;
    /// Get a mutable reference to unknown fields.
    fn mut_unknown_fields<'s>(&'s mut self) -> &'s mut UnknownFields;

    /// Create an empty message object.
    fn new() -> Self where Self : Sized;

    /// Get message descriptor for message type.
    fn descriptor_static() -> &'static MessageDescriptor
        where Self : Sized
    {
        panic!(
            "descriptor_static is not implemented for message, \
             LITE_RUNTIME must be used"
        );
    }

    /// Return a pointer to default immutable message.
    fn default_instance() -> &'static Self
        where Self : Sized;
}

impl Message {
    pub fn downcast_box<T : Any>(self: Box<Self>) -> Result<Box<T>, Box<Message>> {
        if self.as_any().is::<T>() {
            unsafe {
                let raw: *mut Message = Box::into_raw(self);
                Ok(Box::from_raw(raw as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

impl Clone for Box<Message> {
    fn clone(&self) -> Self {
        use std::ops::Deref;
        self.descriptor().clone(self.deref())
    }
}

#[cfg(off)] // don't need it
impl PartialEq for Box<Message> {
    fn eq(&self, other: &Box<Message>) -> bool {
        use std::ops::Deref;
        self.descriptor() == other.descriptor()
            && self.descriptor().eq(self.deref(), other.deref())
    }
}

pub fn message_down_cast<'a, M : Message + 'a>(m: &'a Message) -> &'a M {
    m.as_any().downcast_ref::<M>().unwrap()
}

pub fn message_down_cast_mut<'a, M : Message + 'a>(m: &'a mut Message) -> &'a mut M {
    m.as_any_mut().downcast_mut::<M>().unwrap()
}

/// Parse message from stream.
pub fn parse_from<M : Message>(is: &mut CodedInputStream) -> ProtobufResult<M> {
    let mut r: M = Message::new();
    r.merge_from(is)?;
    r.check_initialized()?;
    Ok(r)
}

/// Parse message from reader.
/// Parse stops on EOF or when error encountered.
pub fn parse_from_reader<M : Message>(reader: &mut Read) -> ProtobufResult<M> {
    reader.with_coded_input_stream(|is| parse_from::<M>(is))
}

/// Parse message from byte array.
pub fn parse_from_bytes<M : Message>(bytes: &[u8]) -> ProtobufResult<M> {
    bytes.with_coded_input_stream(|is| parse_from::<M>(is))
}

/// Parse message from `Bytes` object.
/// Resulting message may share references to the passed bytes object.
#[cfg(feature = "bytes")]
pub fn parse_from_carllerche_bytes<M : Message>(
    bytes: &Bytes,
) -> ProtobufResult<M> {
    // Call trait explicitly to avoid accidental construction from `&[u8]`
    WithCodedInputStream::with_coded_input_stream(bytes, |is| parse_from::<M>(is))
}
<commit_msg>Elide lifetimes<commit_after>use std::any::Any;
use std::fmt;
use std::io::Read;
use std::io::Write;

#[cfg(feature = "bytes")]
use bytes::Bytes;

use clear::Clear;
use reflect::ProtobufValue;
use unknown::UnknownFields;
use stream::WithCodedInputStream;
use stream::WithCodedOutputStream;
use stream::CodedInputStream;
use stream::CodedOutputStream;
use stream::with_coded_output_stream_to_bytes;
use error::ProtobufError;
use error::ProtobufResult;
use reflect::MessageDescriptor;

/// Trait implemented for all generated structs for protobuf messages.
/// Also, generated messages implement `Clone + Default + PartialEq`
pub trait Message : fmt::Debug + Clear + Send + Sync + ProtobufValue {
    /// Message descriptor for this message, used for reflection.
    fn descriptor(&self) -> &'static MessageDescriptor;

    /// True iff all required fields are initialized.
    /// Always returns `true` for protobuf 3.
    fn is_initialized(&self) -> bool;

    /// Update this message object with fields read from given stream.
    fn merge_from(&mut self, is: &mut CodedInputStream) -> ProtobufResult<()>;

    /// Write message to the stream.
    ///
    /// Sizes of this messages and nested messages must be cached
    /// by calling `compute_size` prior to this call.
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> ProtobufResult<()>;

    /// Compute and cache size of this message and all nested messages
    fn compute_size(&self) -> u32;

    /// Get size previously computed by `compute_size`.
    fn get_cached_size(&self) -> u32;

    /// Write the message to the stream.
    ///
    /// Results in error if message is not fully initialized.
    fn write_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        self.check_initialized()?;

        // cache sizes
        self.compute_size();
        // TODO: reserve additional
        self.write_to_with_cached_sizes(os)?;

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    /// Write the message to the stream prepending the message with message length
    /// encoded as varint.
    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        let size = self.compute_size();
        os.write_raw_varint32(size)?;
        self.write_to_with_cached_sizes(os)?;

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    /// Write the message to the vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> ProtobufResult<()> {
        let mut os = CodedOutputStream::vec(vec);
        self.write_length_delimited_to(&mut os)?;
        os.flush()?;
        Ok(())
    }

    /// Update this message object with fields read from given stream.
    fn merge_from_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    /// Check if all required fields of this object are initialized.
    fn check_initialized(&self) -> ProtobufResult<()> {
        if !self.is_initialized() {
            Err(ProtobufError::message_not_initialized(self.descriptor().name()))
        } else {
            Ok(())
        }
    }

    /// Write the message to the writer.
    fn write_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_vec(&self, v: &mut Vec<u8>) -> ProtobufResult<()> {
        v.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        self.check_initialized()?;

        let size = self.compute_size() as usize;
        let mut v = Vec::with_capacity(size);
        // skip zerofill
        unsafe {
            v.set_len(size);
        }
        {
            let mut os = CodedOutputStream::bytes(&mut v);
            self.write_to_with_cached_sizes(&mut os)?;
            os.check_eof();
        }
        Ok(v)
    }

    /// Write the message to the writer, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
    }

    /// Write the message to the bytes vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        with_coded_output_stream_to_bytes(|os| self.write_length_delimited_to(os))
    }

    /// Get a reference to unknown fields.
    fn get_unknown_fields(&self) -> &UnknownFields;
    /// Get a mutable reference to unknown fields.
    fn mut_unknown_fields(&mut self) -> &mut UnknownFields;

    /// Create an empty message object.
    fn new() -> Self where Self : Sized;

    /// Get message descriptor for message type.
    fn descriptor_static() -> &'static MessageDescriptor
        where Self : Sized
    {
        panic!(
            "descriptor_static is not implemented for message, \
             LITE_RUNTIME must be used"
        );
    }

    /// Return a pointer to default immutable message.
    fn default_instance() -> &'static Self
        where Self : Sized;
}

impl Message {
    pub fn downcast_box<T : Any>(self: Box<Self>) -> Result<Box<T>, Box<Message>> {
        if self.as_any().is::<T>() {
            unsafe {
                let raw: *mut Message = Box::into_raw(self);
                Ok(Box::from_raw(raw as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

impl Clone for Box<Message> {
    fn clone(&self) -> Self {
        use std::ops::Deref;
        self.descriptor().clone(self.deref())
    }
}

#[cfg(off)] // don't need it
impl PartialEq for Box<Message> {
    fn eq(&self, other: &Box<Message>) -> bool {
        use std::ops::Deref;
        self.descriptor() == other.descriptor()
            && self.descriptor().eq(self.deref(), other.deref())
    }
}

pub fn message_down_cast<'a, M : Message + 'a>(m: &'a Message) -> &'a M {
    m.as_any().downcast_ref::<M>().unwrap()
}

pub fn message_down_cast_mut<'a, M : Message + 'a>(m: &'a mut Message) -> &'a mut M {
    m.as_any_mut().downcast_mut::<M>().unwrap()
}

/// Parse message from stream.
pub fn parse_from<M : Message>(is: &mut CodedInputStream) -> ProtobufResult<M> {
    let mut r: M = Message::new();
    r.merge_from(is)?;
    r.check_initialized()?;
    Ok(r)
}

/// Parse message from reader.
/// Parse stops on EOF or when error encountered.
pub fn parse_from_reader<M : Message>(reader: &mut Read) -> ProtobufResult<M> {
    reader.with_coded_input_stream(|is| parse_from::<M>(is))
}

/// Parse message from byte array.
pub fn parse_from_bytes<M : Message>(bytes: &[u8]) -> ProtobufResult<M> {
    bytes.with_coded_input_stream(|is| parse_from::<M>(is))
}

/// Parse message from `Bytes` object.
/// Resulting message may share references to the passed bytes object.
#[cfg(feature = "bytes")]
pub fn parse_from_carllerche_bytes<M : Message>(
    bytes: &Bytes,
) -> ProtobufResult<M> {
    // Call trait explicitly to avoid accidental construction from `&[u8]`
    WithCodedInputStream::with_coded_input_stream(bytes, |is| parse_from::<M>(is))
}
<|endoftext|>


<commit_before>/*!
Methods for hyphenation dictionaries
*/

use std::borrow::Cow;

use hyphenation_commons::dictionary::*;
use hyphenation_commons::dictionary::extended::*;
use case_folding::{realign, refold, Shift};
use score::Score;

/// The indices of soft hyphens (U+00AD) within the string, if any. Existing
/// soft hyphens indicate a preferred hyphenation, which can be used without
/// resorting to best-effort hyphenation.
pub fn soft_hyphen_indices(word : &str) -> Option<Vec<usize>> {
    let shys : Vec<_> = word.match_indices('\u{00ad}').map(|(i, _)| i).collect();
    if shys.len() > 0 {
        Some(shys)
    } else { None }
}

/// A hyphenated word carrying valid breaks.
///
/// The `Word` can be borrowed or moved for iteration with `iter()` and
/// `into_iter()` respectively.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Word<'t, Break> {
    pub text : &'t str,
    pub breaks : Vec<Break>
}

/// A dictionary capable of hyphenating individual words.
///
/// For the purpose of hyphenation, a "word" should not be a compound in
/// hyphenated form (such as "hard-nosed"), but a single run of letters
/// without intervening punctuation or spaces.
///
/// For details, refer to the `patterns/*.chr.txt` file for each language.
pub trait Hyphenator<'h> {
    /// Plain representation of a word break.
    type Opportunity;

    /// An owned opportunity used to specify and store the predetermined hyphenation
    /// of known words.
    type Exact;

    /// Hyphenate a word, computing appropriate word breaks and preparing it for
    /// iteration.
    ///
    /// Soft hyphens take priority over dictionary hyphenation; if the word
    /// contains any, they will be returned as the only breaks available.
    ///
    /// This method is case-insensitive.
    fn hyphenate<'t>(&'h self, word : &'t str) -> Word<'t, Self::Opportunity>;

    /// The hyphenation opportunities that our dictionary can find in the given
    /// word. The word should be lowercase.
    fn opportunities(&'h self, lowercase_word : &str) -> Vec<Self::Opportunity> {
        match self.boundaries(lowercase_word) {
            None => vec![],
            Some(mins) => {
                match self.exact(lowercase_word) {
                    None => self.opportunities_within(lowercase_word, mins),
                    Some(known) => known
                }
            }
        }
    }

    /// The hyphenation opportunities that arise between the specified indices.
    ///
    /// No attempt is made to retrieve a known exact hyphenation.
    fn opportunities_within(&'h self, lowercase_word : &str, bounds : (usize, usize))
        -> Vec<Self::Opportunity>;

    /// Retrieve the known exact hyphenation for this word, if any.
    fn exact(&'h self, lowercase_word : &str) -> Option<Vec<Self::Opportunity>>;

    /// Specify the hyphenation of the given word with an exact sequence of
    /// opportunities. Subsequent calls to `hyphenate` or `opportunities` will
    /// yield this hyphenation instead of generating one from patterns.
    ///
    /// If the word already has an exact hyphenation, the old opportunities
    /// are returned.
    fn add_exact(&mut self, word : String, ops : Vec<Self::Exact>) -> Option<Vec<Self::Exact>>;

    /// The number of `char`s from the start and end of a word where breaks may
    /// not occur.
    fn unbreakable_chars(&self) -> (usize, usize);

    /// The byte indices delimiting the substring where breaks may occur, unless
    /// the word is too short to be hyphenated.
    fn boundaries(&self, word : &str) -> Option<(usize, usize)> {
        let (l_min, r_min) = self.unbreakable_chars();
        let length_min = l_min + r_min;
        if word.chars().count() >= length_min {
            ( word.char_indices().nth(l_min).unwrap().0
            , word.char_indices().rev().nth(r_min.saturating_sub(1)).unwrap().0 ).into()
        } else { None }
    }
}

#[derive(Debug, Clone)]
struct Prepared<'t> {
    word : Cow<'t, str>,
    shifts : Vec<Shift>
}

fn prepare<'t>(text : &'t str) -> Prepared<'t> {
    let (word, shifts) = refold(text);
    Prepared { word, shifts }
}

impl<'h> Hyphenator<'h> for Standard {
    type Opportunity = usize;
    type Exact = usize;

    fn hyphenate<'t>(&'h self, word : &'t str) -> Word<'t, Self::Opportunity> {
        let breaks = match soft_hyphen_indices(word) {
            Some(ops) => ops,
            None => {
                let Prepared { ref word, ref shifts } = prepare(word);
                if shifts.len() > 0 {
                    self.opportunities(word).into_iter()
                        .map(move |o| realign(o, shifts)).collect()
                } else { self.opportunities(word) }
            }
        };

        Word { breaks, text : word }
    }

    fn opportunities_within(&'h self, word : &str, (l, r) : (usize, usize)) -> Vec<usize> {
        (1 .. word.len())
            .zip(self.score(word))
            .filter(|&(i, v)| {
                let valid = Self::denotes_opportunity(v);
                let within_bounds = i >= l && i <= r;
                let legal_index = word.is_char_boundary(i);
                valid && within_bounds && legal_index
            }).map(|(i, _)| i).collect()
    }

    #[inline]
    fn exact(&'h self, w : &str) -> Option<Vec<Self::Opportunity>> {
        self.exceptions.0.get(w).cloned()
    }

    #[inline]
    fn add_exact(&mut self, w : String, ops : Vec<usize>) -> Option<Vec<usize>> {
        self.exceptions.0.insert(w, ops)
    }

    #[inline] fn unbreakable_chars(&self) -> (usize, usize) { self.minima }
}

impl<'h> Hyphenator<'h> for Extended {
    type Opportunity = (usize, Option<&'h Subregion>);
    type Exact = (usize, Option<Subregion>);

    fn hyphenate<'t>(&'h self, word : &'t str) -> Word<'t, Self::Opportunity> {
        let breaks = match soft_hyphen_indices(word) {
            Some(ops) => ops.into_iter().map(|i| (i, None)).collect(),
            None => {
                let Prepared { ref word, ref shifts } = prepare(word);
                if shifts.len() > 0 {
                    self.opportunities(word).into_iter()
                        .map(move |(i, subr)| (realign(i, shifts), subr)).collect()
                } else { self.opportunities(word) }
            }
        };

        Word { breaks, text : word }
    }

    fn opportunities_within(&'h self, word : &str, (l, r) : (usize, usize))
        -> Vec<Self::Opportunity>
    {
        (1 .. word.len())
            .zip(self.score(word))
            .filter(|&(i, v)| {
                let valid = Self::denotes_opportunity(v);
                let within_bounds = i >= l && i <= r;
                let legal_index = word.is_char_boundary(i);
                valid && within_bounds && legal_index
            }).map(|(i, (_, subr))| (i, subr)).collect()
    }

    #[inline]
    fn exact(&'h self, w : &str) -> Option<Vec<Self::Opportunity>> {
        self.exceptions.0.get(w).map(|v| v.iter().map(|&(i, ref sub)| (i, sub.as_ref())).collect())
    }

    #[inline]
    fn add_exact(&mut self, w : String, ops : Vec<Self::Exact>) -> Option<Vec<Self::Exact>> {
        self.exceptions.0.insert(w, ops)
    }

    #[inline] fn unbreakable_chars(&self) -> (usize, usize) { self.minima }
}
<commit_msg>Rename `Hyphenator::exact()` to `exception()`<commit_after>/*!
Methods for hyphenation dictionaries
*/

use std::borrow::Cow;

use hyphenation_commons::dictionary::*;
use hyphenation_commons::dictionary::extended::*;
use case_folding::{realign, refold, Shift};
use score::Score;

/// The indices of soft hyphens (U+00AD) within the string, if any. Existing
/// soft hyphens indicate a preferred hyphenation, which can be used without
/// resorting to best-effort hyphenation.
pub fn soft_hyphen_indices(word : &str) -> Option<Vec<usize>> {
    let shys : Vec<_> = word.match_indices('\u{00ad}').map(|(i, _)| i).collect();
    if shys.len() > 0 {
        Some(shys)
    } else { None }
}

/// A hyphenated word carrying valid breaks.
///
/// The `Word` can be borrowed or moved for iteration with `iter()` and
/// `into_iter()` respectively.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Word<'t, Break> {
    pub text : &'t str,
    pub breaks : Vec<Break>
}

/// A dictionary capable of hyphenating individual words.
///
/// For the purpose of hyphenation, a "word" should not be a compound in
/// hyphenated form (such as "hard-nosed"), but a single run of letters
/// without intervening punctuation or spaces.
///
/// For details, refer to the `patterns/*.chr.txt` file for each language.
pub trait Hyphenator<'h> {
    /// Plain representation of a word break.
    type Opportunity;

    /// An owned opportunity used to specify and store the predetermined hyphenation
    /// of known words.
    type Exact;

    /// Hyphenate a word, computing appropriate word breaks and preparing it for
    /// iteration.
    ///
    /// Soft hyphens take priority over dictionary hyphenation; if the word
    /// contains any, they will be returned as the only breaks available.
    ///
    /// This method is case-insensitive.
    fn hyphenate<'t>(&'h self, word : &'t str) -> Word<'t, Self::Opportunity>;

    /// The hyphenation opportunities that our dictionary can find in the given
    /// word. The word should be lowercase.
    fn opportunities(&'h self, lowercase_word : &str) -> Vec<Self::Opportunity> {
        match self.boundaries(lowercase_word) {
            None => vec![],
            Some(mins) => {
                match self.exception(lowercase_word) {
                    None => self.opportunities_within(lowercase_word, mins),
                    Some(known) => known
                }
            }
        }
    }

    /// The hyphenation opportunities that arise between the specified indices.
    ///
    /// No attempt is made to retrieve a known exact hyphenation.
    fn opportunities_within(&'h self, lowercase_word : &str, bounds : (usize, usize))
        -> Vec<Self::Opportunity>;

    /// If this word is a known exception, retrieve its specified hyphenation.
    fn exception(&'h self, lowercase_word : &str) -> Option<Vec<Self::Opportunity>>;

    /// Specify the hyphenation of the given word with an exact sequence of
    /// opportunities and add it to the exception list. Subsequent calls to
    /// `hyphenate` or `opportunities` will yield this hyphenation instead of
    /// generating one from patterns.
    ///
    /// If the word is already a known exception, the old opportunities are
    /// returned.
    fn add_exception(&mut self, lowercase_word : String, ops : Vec<Self::Exact>)
        -> Option<Vec<Self::Exact>>;

    /// The number of `char`s from the start and end of a word where breaks may
    /// not occur.
    fn unbreakable_chars(&self) -> (usize, usize);

    /// The byte indices delimiting the substring where breaks may occur, unless
    /// the word is too short to be hyphenated.
    fn boundaries(&self, word : &str) -> Option<(usize, usize)> {
        let (l_min, r_min) = self.unbreakable_chars();
        let length_min = l_min + r_min;
        if word.chars().count() >= length_min {
            ( word.char_indices().nth(l_min).unwrap().0
            , word.char_indices().rev().nth(r_min.saturating_sub(1)).unwrap().0 ).into()
        } else { None }
    }
}

#[derive(Debug, Clone)]
struct Prepared<'t> {
    word : Cow<'t, str>,
    shifts : Vec<Shift>
}

fn prepare<'t>(text : &'t str) -> Prepared<'t> {
    let (word, shifts) = refold(text);
    Prepared { word, shifts }
}

impl<'h> Hyphenator<'h> for Standard {
    type Opportunity = usize;
    type Exact = usize;

    fn hyphenate<'t>(&'h self, word : &'t str) -> Word<'t, Self::Opportunity> {
        let breaks = match soft_hyphen_indices(word) {
            Some(ops) => ops,
            None => {
                let Prepared { ref word, ref shifts } = prepare(word);
                if shifts.len() > 0 {
                    self.opportunities(word).into_iter()
                        .map(move |o| realign(o, shifts)).collect()
                } else { self.opportunities(word) }
            }
        };

        Word { breaks, text : word }
    }

    fn opportunities_within(&'h self, word : &str, (l, r) : (usize, usize)) -> Vec<usize> {
        (1 .. word.len())
            .zip(self.score(word))
            .filter(|&(i, v)| {
                let valid = Self::denotes_opportunity(v);
                let within_bounds = i >= l && i <= r;
                let legal_index = word.is_char_boundary(i);
                valid && within_bounds && legal_index
            }).map(|(i, _)| i).collect()
    }

    #[inline]
    fn exception(&'h self, w : &str) -> Option<Vec<Self::Opportunity>> {
        self.exceptions.0.get(w).cloned()
    }

    #[inline]
    fn add_exception(&mut self, w : String, ops : Vec<usize>) -> Option<Vec<usize>> {
        self.exceptions.0.insert(w, ops)
    }

    #[inline] fn unbreakable_chars(&self) -> (usize, usize) { self.minima }
}

impl<'h> Hyphenator<'h> for Extended {
    type Opportunity = (usize, Option<&'h Subregion>);
    type Exact = (usize, Option<Subregion>);

    fn hyphenate<'t>(&'h self, word : &'t str) -> Word<'t, Self::Opportunity> {
        let breaks = match soft_hyphen_indices(word) {
            Some(ops) => ops.into_iter().map(|i| (i, None)).collect(),
            None => {
                let Prepared { ref word, ref shifts } = prepare(word);
                if shifts.len() > 0 {
                    self.opportunities(word).into_iter()
                        .map(move |(i, subr)| (realign(i, shifts), subr)).collect()
                } else { self.opportunities(word) }
            }
        };

        Word { breaks, text : word }
    }

    fn opportunities_within(&'h self, word : &str, (l, r) : (usize, usize))
        -> Vec<Self::Opportunity>
    {
        (1 .. word.len())
            .zip(self.score(word))
            .filter(|&(i, v)| {
                let valid = Self::denotes_opportunity(v);
                let within_bounds = i >= l && i <= r;
                let legal_index = word.is_char_boundary(i);
                valid && within_bounds && legal_index
            }).map(|(i, (_, subr))| (i, subr)).collect()
    }

    #[inline]
    fn exception(&'h self, w : &str) -> Option<Vec<Self::Opportunity>> {
        self.exceptions.0.get(w).map(|v| v.iter().map(|&(i, ref sub)| (i, sub.as_ref())).collect())
    }

    fn add_exception(&mut self, w : String, ops : Vec<Self::Exact>)
        -> Option<Vec<Self::Exact>> {
        self.exceptions.0.insert(w, ops)
    }

    #[inline] fn unbreakable_chars(&self) -> (usize, usize) { self.minima }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/FASTA_format
// Fasta reader in Rust 0.11-pre
// Ported and adapted from rosettacode D example

use std::path::Path;
use std::io::fs::File;
use std::io::BufferedReader;
use std::strbuf::StrBuf;

// Best to use type parameter <T: Buffer> to accept all kinds of buffers
fn format_fasta<T: Buffer>(reader: &mut T) -> ~str {
    let mut result = StrBuf::new();

    for line in reader.lines() {
        // Using the same name for the next variable will just shadow the previous one
        let ln = line.unwrap();

        // We need to trim new lines
        let ln = ln.as_slice().trim();

        // Lines that begin with '>' require special treatment
        if ln.slice(0,1) == ">" {
            if result.len() > 0 {
                result.push_str("\n");
            }

            // Push skipping the '>'
            result.push_str(ln.slice_from(1) + ": ");
        }

        // Other lines are just pushed
        else {
            result.push_str(ln);
        }
    }
    result.to_str()
}

fn read_file() -> ~str {
    let file = File::open(&Path::new("resources/test_data.fasta"));
    format_fasta(&mut BufferedReader::new(file))
}

#[cfg(not(test))]
fn main() {
    let s = read_file();
    println!("{}", s);
}

#[test]
fn test_format_fasta() {
    let s = read_file();
    assert_eq!(s.as_slice(), "Rosetta_Example_1: THERECANBENOSPACE\nRosetta_Example_2: THERECANBESEVERALLINESBUTTHEYALLMUSTBECONCATENATED");
}
<commit_msg>fix link to resources<commit_after>// http://rosettacode.org/wiki/FASTA_format
// Fasta reader in Rust 0.11-pre
// Ported and adapted from rosettacode D example

use std::path::Path;
use std::io::fs::File;
use std::io::BufferedReader;
use std::strbuf::StrBuf;

// Best to use type parameter <T: Buffer> to accept all kinds of buffers
fn format_fasta<T: Buffer>(reader: &mut T) -> ~str {
    let mut result = StrBuf::new();

    for line in reader.lines() {
        // Using the same name for the next variable will just shadow the previous one
        let ln = line.unwrap();

        // We need to trim new lines
        let ln = ln.as_slice().trim();

        // Lines that begin with '>' require special treatment
        if ln.slice(0,1) == ">" {
            if result.len() > 0 {
                result.push_str("\n");
            }

            // Push skipping the '>'
            result.push_str(ln.slice_from(1) + ": ");
        }

        // Other lines are just pushed
        else {
            result.push_str(ln);
        }
    }
    result.to_str()
}

fn read_file() -> ~str {
    let file = File::open(&Path::new("src/resources/test_data.fasta"));
    format_fasta(&mut BufferedReader::new(file))
}

#[cfg(not(test))]
fn main() {
    let s = read_file();
    println!("{}", s);
}

#[test]
fn test_format_fasta() {
    let s = read_file();
    assert_eq!(s.as_slice(), "Rosetta_Example_1: THERECANBENOSPACE
Rosetta_Example_2: THERECANBESEVERALLINESBUTTHEYALLMUSTBECONCATENATED");
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

struct Position {
    row: u8,
    column: u8,
}

struct ConnectedComponent {
    colour: Colour,
    cells: Vec<Position>,
}

struct Graph {
    neighours: HashMap<ConnectedComponent, Vec<ConnectedComponent>>,
}
<commit_msg>Use usize for Position<commit_after>use std::collections::HashMap;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

struct Position {
    row: usize,
    column: usize,
}

struct ConnectedComponent {
    colour: Colour,
    cells: Vec<Position>,
}

struct Graph {
    neighours: HashMap<ConnectedComponent, Vec<ConnectedComponent>>,
}
<|endoftext|>


<commit_before>use proc_macro2::{Delimiter, Span};

use error::Result;
use parse::ParseBuffer;
#[cfg(any(feature = "full", feature = "derive"))]
use parse::ParseStream;
use private;
use token;

pub struct Parens<'a> {
    pub token: token::Paren,
    pub content: ParseBuffer<'a>,
}

pub struct Braces<'a> {
    pub token: token::Brace,
    pub content: ParseBuffer<'a>,
}

pub struct Brackets<'a> {
    pub token: token::Bracket,
    pub content: ParseBuffer<'a>,
}

#[cfg(any(feature = "full", feature = "derive"))]
pub struct Group<'a> {
    pub token: token::Group,
    pub content: ParseBuffer<'a>,
}

impl<'a> ParseBuffer<'a> {
    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
        self.step(|cursor| {
            if let Some((content, span, rest)) = cursor.group(delimiter) {
                let unexpected = private::get_unexpected(self);
                let content =
                    private::new_parse_buffer(span, cursor.advance(content), unexpected);
                Ok(((span, content), rest))
            } else {
                let message = match delimiter {
                    Delimiter::Parenthesis => "expected parentheses",
                    Delimiter::Brace => "expected curly braces",
                    Delimiter::Bracket => "expected square brackets",
                    Delimiter::None => "expected invisible group",
                };
                Err(cursor.error(message))
            }
        })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_parens(&self) -> Result<Parens<'a>> {
        self.parse_delimited(Delimiter::Parenthesis)
            .map(|(span, content)| Parens {
                token: token::Paren(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_braces(&self) -> Result<Braces<'a>> {
        self.parse_delimited(Delimiter::Brace)
            .map(|(span, content)| Braces {
                token: token::Brace(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
        self.parse_delimited(Delimiter::Bracket)
            .map(|(span, content)| Brackets {
                token: token::Bracket(span),
                content: content,
            })
    }
}

#[cfg(any(feature = "full", feature = "derive"))]
impl private {
    pub fn parse_group(input: ParseStream) -> Result<Group> {
        input.parse_delimited(Delimiter::None)
            .map(|(span, content)| Group {
                token: token::Group(span),
                content: content,
            })
    }
}

/// Parse a set of parentheses and expose their content to subsequent parsers.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate syn;
///
/// use syn::{parenthesized, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified tuple struct syntax like:
/// //
/// //     struct S(A, B);
/// struct TupleStruct {
///     struct_token: Token![struct],
///     ident: Ident,
///     paren_token: token::Paren,
///     fields: Punctuated<Type, Token![,]>,
///     semi_token: Token![;],
/// }
///
/// impl Parse for TupleStruct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(TupleStruct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             paren_token: parenthesized!(content in input),
///             fields: content.parse_terminated(Type::parse)?,
///             semi_token: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S(A, B);
/// #     };
/// #     syn::parse2::<TupleStruct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! parenthesized {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
            $crate::export::Ok(parens) => {
                $content = parens.content;
                parens.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// ```rust
/// # extern crate quote;
/// # use quote::quote;
/// #
/// extern crate syn;
///
/// use syn::{braced, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// //     struct S {
/// //         a: A,
/// //         b: B,
/// //     }
/// struct Struct {
///     struct_token: Token![struct],
///     ident: Ident,
///     brace_token: token::Brace,
///     fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
///     name: Ident,
///     colon_token: Token![:],
///     ty: Type,
/// }
///
/// impl Parse for Struct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(Struct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             brace_token: braced!(content in input),
///             fields: content.parse_terminated(Field::parse)?,
///         })
///     }
/// }
///
/// impl Parse for Field {
///     fn parse(input: ParseStream) -> Result<Self> {
///         Ok(Field {
///             name: input.parse()?,
///             colon_token: input.parse()?,
///             ty: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S {
/// #             a: A,
/// #             b: B,
/// #         }
/// #     };
/// #     syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! braced {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
            $crate::export::Ok(braces) => {
                $content = braces.content;
                braces.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
#[macro_export]
macro_rules! bracketed {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
            $crate::export::Ok(brackets) => {
                $content = brackets.content;
                brackets.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}
<commit_msg>Example of bracketed macro<commit_after>use proc_macro2::{Delimiter, Span};

use error::Result;
use parse::ParseBuffer;
#[cfg(any(feature = "full", feature = "derive"))]
use parse::ParseStream;
use private;
use token;

pub struct Parens<'a> {
    pub token: token::Paren,
    pub content: ParseBuffer<'a>,
}

pub struct Braces<'a> {
    pub token: token::Brace,
    pub content: ParseBuffer<'a>,
}

pub struct Brackets<'a> {
    pub token: token::Bracket,
    pub content: ParseBuffer<'a>,
}

#[cfg(any(feature = "full", feature = "derive"))]
pub struct Group<'a> {
    pub token: token::Group,
    pub content: ParseBuffer<'a>,
}

impl<'a> ParseBuffer<'a> {
    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
        self.step(|cursor| {
            if let Some((content, span, rest)) = cursor.group(delimiter) {
                let unexpected = private::get_unexpected(self);
                let content =
                    private::new_parse_buffer(span, cursor.advance(content), unexpected);
                Ok(((span, content), rest))
            } else {
                let message = match delimiter {
                    Delimiter::Parenthesis => "expected parentheses",
                    Delimiter::Brace => "expected curly braces",
                    Delimiter::Bracket => "expected square brackets",
                    Delimiter::None => "expected invisible group",
                };
                Err(cursor.error(message))
            }
        })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_parens(&self) -> Result<Parens<'a>> {
        self.parse_delimited(Delimiter::Parenthesis)
            .map(|(span, content)| Parens {
                token: token::Paren(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_braces(&self) -> Result<Braces<'a>> {
        self.parse_delimited(Delimiter::Brace)
            .map(|(span, content)| Braces {
                token: token::Brace(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
        self.parse_delimited(Delimiter::Bracket)
            .map(|(span, content)| Brackets {
                token: token::Bracket(span),
                content: content,
            })
    }
}

#[cfg(any(feature = "full", feature = "derive"))]
impl private {
    pub fn parse_group(input: ParseStream) -> Result<Group> {
        input.parse_delimited(Delimiter::None)
            .map(|(span, content)| Group {
                token: token::Group(span),
                content: content,
            })
    }
}

/// Parse a set of parentheses and expose their content to subsequent parsers.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate syn;
///
/// use syn::{parenthesized, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified tuple struct syntax like:
/// //
/// //     struct S(A, B);
/// struct TupleStruct {
///     struct_token: Token![struct],
///     ident: Ident,
///     paren_token: token::Paren,
///     fields: Punctuated<Type, Token![,]>,
///     semi_token: Token![;],
/// }
///
/// impl Parse for TupleStruct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(TupleStruct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             paren_token: parenthesized!(content in input),
///             fields: content.parse_terminated(Type::parse)?,
///             semi_token: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S(A, B);
/// #     };
/// #     syn::parse2::<TupleStruct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! parenthesized {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
            $crate::export::Ok(parens) => {
                $content = parens.content;
                parens.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// ```rust
/// # extern crate quote;
/// # use quote::quote;
/// #
/// extern crate syn;
///
/// use syn::{braced, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// //     struct S {
/// //         a: A,
/// //         b: B,
/// //     }
/// struct Struct {
///     struct_token: Token![struct],
///     ident: Ident,
///     brace_token: token::Brace,
///     fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
///     name: Ident,
///     colon_token: Token![:],
///     ty: Type,
/// }
///
/// impl Parse for Struct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(Struct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             brace_token: braced!(content in input),
///             fields: content.parse_terminated(Field::parse)?,
///         })
///     }
/// }
///
/// impl Parse for Field {
///     fn parse(input: ParseStream) -> Result<Self> {
///         Ok(Field {
///             name: input.parse()?,
///             colon_token: input.parse()?,
///             ty: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S {
/// #             a: A,
/// #             b: B,
/// #         }
/// #     };
/// #     syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! braced {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
            $crate::export::Ok(braces) => {
                $content = braces.content;
                braces.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate proc_macro2;
/// extern crate syn;
///
/// use proc_macro2::TokenStream;
/// use syn::{bracketed, token, Token};
/// use syn::parse::{Parse, ParseStream, Result};
///
/// // Parse an outer attribute like:
/// //
/// //     #[repr(C, packed)]
/// struct OuterAttribute {
///     pound_token: Token![#],
///     bracket_token: token::Bracket,
///     content: TokenStream,
/// }
///
/// impl Parse for OuterAttribute {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(OuterAttribute {
///             pound_token: input.parse()?,
///             bracket_token: bracketed!(content in input),
///             content: content.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         #[repr(C, packed)]
/// #     };
/// #     syn::parse2::<OuterAttribute>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! bracketed {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
            $crate::export::Ok(brackets) => {
                $content = brackets.content;
                brackets.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}
<|endoftext|>