<commit_before>// http://rosettacode.org/wiki/24_game

//! Implements with a recursive descent parser for a simple calculator (+ - * /) using the shunting
//! yard algorithm as explained on http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm. It follows
//! operator precedence (i.e. 2 + 3 * 3 = 11), understands negation (-5 + 6 = 1), ignores
//! whitespace and allows the use of parentheses

extern crate rand;
use std::cmp::Ordering::{self, Greater};

fn main() {
    use std::io;

    let mut rng = rand::thread_rng();
    let input = io::stdin();

    loop {
        let mut sample = rand::sample(&mut rng, (1u32..10), 4);

        println!("make 24 by combining the following 4 numbers with + - * / or (q)uit");
        println!("{:?}", sample);
        let mut line = String::new();
        let _ = input.read_line(&mut line).unwrap();
        match line.trim() {
            "q" => break,
            input => {
                if check_values(&mut sample[..], input) {
                    match Parser::new(input).parse() {
                        Ok(i) if i == 24. => println!("you made it!"),
                        Ok(i) => println!("you entered {}, try again!", i),
                        Err(s) => println!("{}", s),
                    };
                } else {
                    println!("unrecognized input, try again")
                }
            }
        }
    }
}

/// Returns true if the entered expression uses the values contained in sample
pub fn check_values(sample: &mut [u32], input: &str) -> bool {
    let lex = Lexer::new(input);

    let mut numbers_used = lex.filter_map(|a| {
                                  match a {
                                      Token::Int(i) => Some(i),
                                      _ => None,
                                  }
                              })
                              .collect::<Vec<u32>>();

    numbers_used.sort();
    sample.sort();
    numbers_used == sample
}

/// the tokens that our parser is going to recognize
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum Token {
    LParen,
    RParen,
    Plus,
    Minus,
    Slash,
    Star,
    Int(u32),
}

impl Token {
    /// are tokens associated to a binary operation?
    fn is_binary(&self) -> bool {
        match *self {
            Token::Plus | Token::Minus | Token::Slash | Token::Star => true,
            _ => false,
        }
    }
}

trait Tokenable {
    fn as_token(&self) -> Option<Token>; }

/// map a character to its corresponding token
impl Tokenable for char {
    #[inline]
    fn as_token(&self) -> Option<Token> {
        let tok = match *self {
            '(' => Token::LParen,
            ')' => Token::RParen,
            '+' => Token::Plus,
            '-' => Token::Minus,
            '/' => Token::Slash,
            '*' => Token::Star,
            _ => return None,
        };

        Some(tok)
    }
}

/// Lexer reads an expression like (a + b) / c * d as an iterator on the tokens that compose it
/// Int(a), LParen, Plus, Int(b), RParen...
#[derive(Copy, Clone)]
pub struct Lexer<'a> {
    input: &'a str,
    offset: usize,
}

impl<'a> Lexer<'a> {
    pub fn new(input: &str) -> Lexer {
        Lexer {
            input: input,
            offset: 0,
        }
    }

    fn expect(&mut self, expected: &[Token]) -> Result<Token, String> {
        let n = self.offset;
        match self.next() {
            Some(a) if expected.contains(&a) => Ok(a),
            other => Err(format!("Parsing error: {:?} was unexpected at offset {}", other, n)),
        }
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        // slice the original string starting from the current offset
        let mut remaining = self.input[self.offset..]
                                .char_indices()
                                .skip_while(|&(_, ch)| ch.is_whitespace());

        let (tok, cur_offset) = match remaining.next() {
            // Found a digit. if there are others, transform them to `u32`
            Some((mut offset, ch)) if ch.is_digit(10) => {
                let mut val = ch.to_digit(10).unwrap();
                let mut more = false;

                for (idx, ch) in remaining {
                    more = true;
                    if ch.is_digit(10) {
                        let digit = ch.to_digit(10).unwrap();
                        val = val * 10 + digit;
                    } else {
                        offset = idx;
                        break;
                    }
                }
                if !more {
                    offset = 1;
                }
                (Some(Token::Int(val)), offset)
            }
            // found non-digit, try transforming it to the corresponding token
            Some((o, ch)) => (ch.as_token(), o + 1),
            _ => (None, 0),
        };

        // update the offset for the next iteration
        self.offset += cur_offset;
        tok
    }
}

/// Operators are a "higher level" concept than tokens as they define the semantics of the
/// expression language e.g. token "Minus" can correspond to the unary Neg Operator (-a) or to the
/// binary Sub operator (a - b)
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum Operator {
    Neg,
    Add,
    Sub,
    Mul,
    Div,
    Sentinel,
}

impl Operator {
    fn precedence(&self) -> usize {
        match *self {
            Operator::Sentinel => 0,
            Operator::Add | Operator::Sub => 1,
            Operator::Neg => 2,
            Operator::Mul | Operator::Div => 3,
        }
    }
}

/// Operator precedence for binary operators:
/// * if x has higher precedence than y precedence for x > precedence for y
/// * if x and y have equal precedence the first one has precedence
/// e.g. in expression (4 / 2 * 2) operators * and / have the same precedence, but the operations
/// must be performed in the order they appear (division first, multiplication second) otherwise
/// results are different
impl PartialOrd for Operator {
    fn partial_cmp(&self, other: &Operator) -> Option<Ordering> {
        match (self.precedence(), other.precedence()) {
            (a, b) if a == b => Some(Greater),
            (a, b) => a.partial_cmp(&b),
        }
    }
}

/// recursive descent parser with the shunting yard algorithm as explained on
/// http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm. I followed the names of the methods as
/// closely as possible vs the pseudo-code that illustrates the algorithm
pub struct Parser<'a> {
    operators: Vec<Operator>,
    operands: Vec<f32>,
    lexer: Lexer<'a>,
}

impl<'a> Parser<'a> {
    pub fn new(input: &str) -> Parser {
        Parser {
            operators: vec![],
            operands: vec![],
            lexer: Lexer::new(input),
        }
    }

    pub fn parse(&mut self) -> Result<f32, String> {
        self.operators.push(Operator::Sentinel);
        try!(self.e());
        return match self.operands.last() {
            Some(r) => Ok(*r),
            None => Err("something went wrong, got no result".to_string()),
        };
    }

    fn e(&mut self) -> Result<(), String> {
        try!(self.p());

        loop {
            match self.lexer.peekable().peek() {
                Some(&x) if x.is_binary() => {
                    let op = match x {
                        Token::Plus => Operator::Add,
                        Token::Minus => Operator::Sub,
                        Token::Star => Operator::Mul,
                        Token::Slash => Operator::Div,
                        // there are no other binary operators
                        _ => unreachable!(),
                    };

                    self.push_operator(op);

                    // Consume the peeked value
                    self.lexer.next();
                    try!(self.p());
                }
                _ => break,
            }
        }

        loop {
            match self.operators.last() {
                Some(&op) if op != Operator::Sentinel => self.pop_operator(),
                _ => return Ok(()),
            }
        }
    }

    fn p(&mut self) -> Result<(), String> {
        match self.lexer.next() {
            Some(Token::Int(n)) => self.operands.push(n as f32),
            Some(Token::LParen) => {
                self.operators.push(Operator::Sentinel);
                try!(self.e());
                try!(self.lexer.expect(&[Token::RParen]));
                self.operators.pop();
            }
            Some(Token::Minus) => {
                self.push_operator(Operator::Neg);
                try!(self.p());
            }
            Some(e) => return Err(format!("unexpected token {:?}", e)),
            _ => return Err("unexpected end of command".to_string()),
        }
        Ok(())
    }

    fn pop_operator(&mut self) {
        match self.operators.pop() {
            Some(Operator::Add) => self.binary_op(|t1, t2| t1 + t2),
            Some(Operator::Sub) => self.binary_op(|t1, t2| t1 - t2),
            Some(Operator::Mul) => self.binary_op(|t1, t2| t1 * t2),
            Some(Operator::Div) => self.binary_op(|t1, t2| t1 / t2),
            Some(Operator::Neg) => self.unary_op(|t1| -t1),
            _ => unreachable!(),
        }
    }

    fn push_operator(&mut self, op: Operator) {
        match self.operators.last() {
            Some(&last_op) if last_op > op => self.pop_operator(),
            _ => {}
        }
        self.operators.push(op);
    }

    #[inline]
    fn binary_op<F>(&mut self, op: F)
        where F: Fn(f32, f32) -> f32
    {
        match (self.operands.pop(), self.operands.pop()) {
            (Some(t1), Some(t2)) => self.operands.push(op(t2, t1)),
            _ => unreachable!(),
        }
    }

    #[inline]
    fn unary_op<F>(&mut self, op: F)
        where F: Fn(f32) -> f32
    {
        match self.operands.pop() {
            Some(t1) => self.operands.push(op(t1)),
            _ => unreachable!(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Token, Lexer, Parser};
    use super::Operator::{Add, Sub, Mul, Div};
    use super::check_values;
    use super::Token::{LParen, RParen, Plus, Slash, Star, Int};

    #[test]
    fn test_precedence() {
        assert!(Mul > Add);
        // Ordering matters for these pairs
        assert!(Mul > Div);
        assert!(Div > Mul);

        assert!(Add > Sub);
        assert!(Sub > Add);

        assert!(!(Mul < Div));
    }

    #[test]
    fn lexer_iter() {
        // test read token and character's offset in the iterator
        let t = |lex: &mut Lexer, exp_tok: Token, exp_pos: usize| {
            assert_eq!(lex.next(), Some(exp_tok));
            assert_eq!(lex.offset, exp_pos);
        };

        let tok = &mut Lexer::new("  15 + 4");
        t(tok, Int(15), 4);
        t(tok, Plus, 6);
        let read = tok.expect(&[LParen, Int(4), RParen]);
        assert_eq!(read, Ok(Int(4)));

        let mut tok = Lexer::new("");
        assert_eq!(tok.next(), None);

        let tok = &mut Lexer::new("     ");
        assert_eq!(tok.next(), None);

        let tok = &mut Lexer::new("2 * (3+4/2)");
        t(tok, Int(2), 1);
        t(tok, Star, 3);
        t(tok, LParen, 5);
        t(tok, Int(3), 6);
        t(tok, Plus, 7);
        t(tok, Int(4), 8);
        t(tok, Slash, 9);
        t(tok, Int(2), 10);
        t(tok, RParen, 11);
    }

    #[test]
    fn parse() {
        fn t(input: &str, expected: Result<f32, String>) {
            assert_eq!(Parser::new(input).parse(), expected)
        }

        t("2+2", Ok(4.));
        t("2+3*4", Ok(14.));
        t("4*(3+2)", Ok(20.));
        t("5/(3+2)*3", Ok(3.));
        t("2++12", Err("unexpected token Plus".to_string()));
        t("-2+12", Ok(10.));
        t("-2*(2+3)", Ok(-10.));

        // Testing precedence
        t("4 / 2 * 2", Ok(4.));
        t("2 * 2 / 4", Ok(1.));
    }

    #[test]
    fn try_check_values() {
        let m = &mut [1, 2, 3, 4];
        assert!(check_values(m, "1+3 -(4/2)"));
        // new testcase for #314
        assert!(check_values(m, "1+2+3+4"));
    }
}
<commit_msg>Refactoring for 24_game<commit_after>// http://rosettacode.org/wiki/24_game

//! Implements with a recursive descent parser for a simple calculator (+ - * /) using the shunting
//! yard algorithm as explained on http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm. It follows
//! operator precedence (i.e. 2 + 3 * 3 = 11), understands negation (-5 + 6 = 1), ignores
//! whitespace and allows the use of parentheses

extern crate rand;
use std::cmp::Ordering::{self, Greater};
use std::iter::Peekable;
use std::str::CharIndices;

fn main() {
    use std::io;

    let mut rng = rand::thread_rng();
    let input = io::stdin();

    loop {
        let mut sample = rand::sample(&mut rng, (1u32..10), 4);

        println!("make 24 by combining the following 4 numbers with + - * / or (q)uit");
        println!("{:?}", sample);
        let mut line = String::new();
        let _ = input.read_line(&mut line).unwrap();
        match line.trim() {
            "q" => break,
            input => {
                if check_values(&mut sample[..], input) {
                    match Parser::new(input).parse() {
                        Ok(i) if i == 24. => println!("you made it!"),
                        Ok(i) => println!("you entered {}, try again!", i),
                        Err(s) => println!("{}", s),
                    };
                } else {
                    println!("unrecognized input, try again")
                }
            }
        }
    }
}

/// Returns true if the entered expression uses the values contained in sample
pub fn check_values(sample: &mut [u32], input: &str) -> bool {
    let lex = Lexer::new(input);

    let mut numbers_used = lex.filter_map(|(_,a)| {
                                  match a {
                                      Token::Int(i) => Some(i),
                                      _ => None,
                                  }
                              })
                              .collect::<Vec<u32>>();

    numbers_used.sort();
    sample.sort();
    numbers_used == sample
}

/// the tokens that our parser is going to recognize
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum Token {
    LParen,
    RParen,
    Plus,
    Minus,
    Slash,
    Star,
    Unknown,
    Int(u32),
}

impl Token {
    /// are tokens associated to a binary operation?
    fn is_binary(&self) -> bool {
        match *self {
            Token::Plus | Token::Minus | Token::Slash | Token::Star => true,
            _ => false,
        }
    }
}

pub struct Lexer<'a> {
    input: Peekable<CharIndices<'a>>,
}

impl<'a> Lexer<'a> {
    pub fn new(input: &str) -> Lexer {
        Lexer {
            input: input.char_indices().peekable(),
        }
    }

    fn expect<I>(iter: &mut I, expected: &[Token]) -> Result<Token, String>
                            where I: Iterator<Item = (usize, Token)> {
        match iter.next() {
            Some((_, a)) if expected.contains(&a) => Ok(a),
            Some((n, other)) =>
                Err(format!("Parsing error: {:?} was unexpected at offset {}",
                other, n)),
            None => Err("unexpected end of token list".into()),
        }
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = (usize, Token);

    fn next(&mut self) -> Option<(usize, Token)> {
        if let Some((idx, c)) = self.input.by_ref()
                .skip_while(|&(_, c)| c.is_whitespace()).next() {
            let ret = match c {
                '(' => Token::LParen,
                ')' => Token::RParen,
                '+' => Token::Plus,
                '-' => Token::Minus,
                '/' => Token::Slash,
                '*' => Token::Star,
                d @ '0'...'9' => {
                        let mut val = d.to_digit(10). unwrap();
                        while let Some(dg) = self.input.by_ref().peek()
                                .and_then(|&(_, di)| di.to_digit(10)) {
                            val = val * 10 + dg;
                            self.input.by_ref().next();
                        }
                        Token::Int(val)
                    },
                _ => Token::Unknown,
            };
            Some((idx, ret))
        } else {
            None
        }
    }
}

/// Operators are a "higher level" concept than tokens as they define the semantics of the
/// expression language e.g. token "Minus" can correspond to the unary Neg Operator (-a) or to the
/// binary Sub operator (a - b)
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Operator {
    Neg,
    Add,
    Sub,
    Mul,
    Div,
    Sentinel,
}

impl Operator {
    fn precedence(&self) -> usize {
        match *self {
            Operator::Sentinel => 0,
            Operator::Add | Operator::Sub => 1,
            Operator::Neg => 2,
            Operator::Mul | Operator::Div => 3,
        }
    }
}

/// Operator precedence for binary operators:
/// * if x has higher precedence than y precedence for x > precedence for y
/// * if x and y have equal precedence the first one has precedence
/// e.g. in expression (4 / 2 * 2) operators * and / have the same precedence, but the operations
/// must be performed in the order they appear (division first, multiplication second) otherwise
/// results are different
impl PartialOrd for Operator {
    fn partial_cmp(&self, other: &Operator) -> Option<Ordering> {
        match (self.precedence(), other.precedence()) {
            (a, b) if a == b => Some(Greater),
            (a, b) => a.partial_cmp(&b),
        }
    }
}

/// recursive descent parser with the shunting yard algorithm as explained on
/// http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm. I followed the names of the methods as
/// closely as possible vs the pseudo-code that illustrates the algorithm
pub struct Parser<'a> {
    operators: Vec<Operator>,
    operands: Vec<f32>,
    lexer: Peekable<Lexer<'a>>,
}

impl<'a> Parser<'a> {
    pub fn new(input: &str) -> Parser {
        Parser {
            operators: vec![],
            operands: vec![],
            lexer: Lexer::new(input).peekable(),
        }
    }

    pub fn parse(&mut self) -> Result<f32, String> {
        self.operators.push(Operator::Sentinel);
        try!(self.e());
        return match self.operands.last() {
            Some(r) => Ok(*r),
            None => Err("something went wrong, got no result".to_string()),
        };
    }

    fn e(&mut self) -> Result<(), String> {
        try!(self.p());
        while let Some(&(_, x)) = self.lexer.by_ref().peek() {
            if ! x.is_binary() { break; }

            let op = match x {
                Token::Plus => Operator::Add,
                Token::Minus => Operator::Sub,
                Token::Star => Operator::Mul,
                Token::Slash => Operator::Div,
                // there are no other binary operators
                _ => unreachable!(),
            };
            self.push_operator(op);

            // Consume the peeked value
            self.lexer.by_ref().next();
            try!(self.p());
        }

        while let Some(&op) = self.operators.last() {
            if op == Operator::Sentinel { return Ok(()) }
            self.pop_operator();
        }
        unreachable!() // algorithm fail: reached the end without finding
                       // the sentinel
    }

    fn p(&mut self) -> Result<(), String> {
        match self.lexer.by_ref().next() {
            Some((_, Token::Int(n))) => self.operands.push(n as f32),
            Some((_, Token::LParen)) => {
                self.operators.push(Operator::Sentinel);
                try!(self.e());
                try!(Lexer::expect(&mut self.lexer, &[Token::RParen]));
                self.operators.pop();
            }
            Some((_, Token::Minus)) => {
                self.push_operator(Operator::Neg);
                try!(self.p());
            }
            Some((p, e)) => return Err(format!("unexpected token {:?} at pos {}", e, p)),
            _ => return Err("unexpected end of command".to_string()),
        }
        Ok(())
    }

    fn pop_operator(&mut self) {
        match self.operators.pop() {
            Some(Operator::Add) => self.binary_op(|t1, t2| t1 + t2),
            Some(Operator::Sub) => self.binary_op(|t1, t2| t1 - t2),
            Some(Operator::Mul) => self.binary_op(|t1, t2| t1 * t2),
            Some(Operator::Div) => self.binary_op(|t1, t2| t1 / t2),
            Some(Operator::Neg) => self.unary_op(|t1| -t1),
            _ => unreachable!(),
        }
    }

    fn push_operator(&mut self, op: Operator) {
        match self.operators.last() {
            Some(&last_op) if last_op > op => self.pop_operator(),
            _ => {}
        }
        self.operators.push(op);
    }

    #[inline]
    fn binary_op<F>(&mut self, op: F)
        where F: Fn(f32, f32) -> f32
    {
        match (self.operands.pop(), self.operands.pop()) {
            (Some(t1), Some(t2)) => self.operands.push(op(t2, t1)),
            _ => unreachable!(),
        }
    }

    #[inline]
    fn unary_op<F>(&mut self, op: F)
        where F: Fn(f32) -> f32
    {
        match self.operands.pop() {
            Some(t1) => self.operands.push(op(t1)),
            _ => unreachable!(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Token, Lexer, Parser};
    use super::Operator::{Add, Sub, Mul, Div};
    use super::check_values;
    use super::Token::{LParen, RParen, Plus, Slash, Star, Int};

    #[test]
    fn test_precedence() {
        assert!(Mul > Add);
        // Ordering matters for these pairs
        assert!(Mul > Div);
        assert!(Div > Mul);

        assert!(Add > Sub);
        assert!(Sub > Add);

        assert!(!(Mul < Div));
    }

    #[test]
    fn lexer_iter() {
        // test read token and character's offset in the iterator
        let t = |lex: &mut Lexer, exp_tok: Token, exp_pos: usize| {
            assert_eq!(lex.next(), Some((exp_pos,exp_tok)));
        };

        let tok = &mut Lexer::new("  15 + 4");
        t(tok, Int(15), 2);
        t(tok, Plus, 5);
        let read = Lexer::expect(tok, &[LParen, Int(4), RParen]);
        assert_eq!(read, Ok(Int(4)));

        let mut tok = Lexer::new("");
        assert_eq!(tok.next(), None);

        let tok = &mut Lexer::new("     ");
        assert_eq!(tok.next(), None);

        let tok = &mut Lexer::new("2 * (3+4/2)");
        t(tok, Int(2), 0);
        t(tok, Star, 2);
        t(tok, LParen, 4);
        t(tok, Int(3), 5);
        t(tok, Plus, 6);
        t(tok, Int(4), 7);
        t(tok, Slash, 8);
        t(tok, Int(2), 9);
        t(tok, RParen, 10);
    }

    #[test]
    fn parse() {
        fn t(input: &str, expected: Result<f32, String>) {
            assert_eq!(Parser::new(input).parse(), expected)
        }

        t("2+2", Ok(4.));
        t("2+3*4", Ok(14.));
        t("4*(3+2)", Ok(20.));
        t("5/(3+2)*3", Ok(3.));
        t("2++12", Err("unexpected token Plus at pos 2".to_string()));
        t("-2+12", Ok(10.));
        t("-2*(2+3)", Ok(-10.));

        // Testing precedence
        t("4 / 2 * 2", Ok(4.));
        t("2 * 2 / 4", Ok(1.));
    }

    #[test]
    fn try_check_values() {
        let m = &mut [1, 2, 3, 4];
        assert!(check_values(m, "1+3 -(4/2)"));
        // new testcase for #314
        assert!(check_values(m, "1+2+3+4"));
    }
}
<|endoftext|>


<commit_before>use std;
use libc::{c_int,size_t,close,munmap,c_void};
use vm::VirtualCPU;
use linux::error::*;
use linux::{kvm_create_vcpu, kvm_map_run, kvm_run, kvm_init_vcpu};
use linux::{kvm_get_regs, kvm_get_sregs, Regs, Sregs, KVMFD};
use linux::utils;
use linux::kvm::*;

#[derive(Debug)]
pub struct EhyveCPU
{
	id: u32,
	cpufd: c_int,
	run: *mut Run
}

impl EhyveCPU {
    pub fn new(id: u32, fd: c_int) -> EhyveCPU {
		unsafe {
			let cpufd = kvm_create_vcpu(fd, id as c_int);
			let run = kvm_map_run(KVMFD, cpufd);

			EhyveCPU {
				id: id,
				cpufd: cpufd,
				run: run as *mut Run
			}
		}
	}

	fn get_sregs(&self) -> Result<Sregs> {
		let mut sregs = Sregs::default();
		unsafe {
			let err = kvm_get_sregs(self.cpufd, (&mut sregs) as *mut Sregs);
			if err == -1 {
				return Err(Error::InternalError);
			}
		}

		Ok(sregs)
	}

	fn get_regs(&self) -> Result<Regs> {
		let mut regs = Regs::default();
		unsafe {
			let err = kvm_get_regs(self.cpufd, (&mut regs) as *mut Regs);
			if err == -1 {
				return Err(Error::InternalError);
			}
		}

		Ok(regs)
	}
}

impl VirtualCPU for EhyveCPU {
	fn init(&mut self, entry_point: u64) -> Result<()>
	{
		let ret = unsafe { kvm_init_vcpu(self.cpufd, self.id as c_int, entry_point as size_t) };
		if ret != 0 {
			return Err(Error::InternalError);
		}

		Ok(())
	}

	fn run(&mut self) -> Result<()>
	{
		self.print_registers();

		loop {
			let ret = unsafe { kvm_run(self.cpufd) };

			if ret != 0 {
				return Err(Error::InternalError);
			}

			match unsafe { (*self.run).exit_reason } {
				Exit::Io => {
					//debug!("IO Exit");
					unsafe {
						let port = (*(*self.run).io()).port;
						let data = self.run as *const u8;
						let data = data.offset((*(*self.run).io()).data_offset as isize);
						let cstr = std::str::from_utf8(std::slice::from_raw_parts(data, 1)).unwrap();

						self.io_exit(port, cstr.to_string())?;
					}
				},
				Exit::Hlt => {
						debug!("Halt Exit");
				},
				_ => {
					error!("Unknown exit reason: {:?}", unsafe { (*self.run).exit_reason });
					//self.print_registers();

					return Err(Error::UnknownExitReason(unsafe { (*self.run).exit_reason }));
				}
			}
		}
	}

	fn print_registers(&self)
	{
		utils::show_registers(self.id, &self.get_regs().unwrap(), &self.get_sregs().unwrap());
	}
}

impl Drop for EhyveCPU {
    fn drop(&mut self) {
		debug!("Drop vCPU {}", self.id);

		if self.cpufd >= 0 {
			unsafe {
         		close(self.cpufd);
				munmap(self.run as *mut c_void, std::mem::size_of::<Run>());
			}
		}
    }
}
<commit_msg>reduce the number of unsafe regions<commit_after>use std;
use libc::{c_int,size_t,close,munmap,c_void};
use vm::VirtualCPU;
use linux::error::*;
use linux::{kvm_create_vcpu, kvm_map_run, kvm_run, kvm_init_vcpu};
use linux::{kvm_get_regs, kvm_get_sregs, Regs, Sregs, KVMFD};
use linux::utils;
use linux::kvm::*;

#[derive(Debug)]
pub struct EhyveCPU
{
	id: u32,
	cpufd: c_int,
	run: *mut Run
}

impl EhyveCPU {
    pub fn new(id: u32, fd: c_int) -> EhyveCPU {
		unsafe {
			let cpufd = kvm_create_vcpu(fd, id as c_int);
			let run = kvm_map_run(KVMFD, cpufd);

			EhyveCPU {
				id: id,
				cpufd: cpufd,
				run: run as *mut Run
			}
		}
	}

	fn get_sregs(&self) -> Result<Sregs> {
		let mut sregs = Sregs::default();
		unsafe {
			let err = kvm_get_sregs(self.cpufd, (&mut sregs) as *mut Sregs);
			if err == -1 {
				return Err(Error::InternalError);
			}
		}

		Ok(sregs)
	}

	fn get_regs(&self) -> Result<Regs> {
		let mut regs = Regs::default();
		unsafe {
			let err = kvm_get_regs(self.cpufd, (&mut regs) as *mut Regs);
			if err == -1 {
				return Err(Error::InternalError);
			}
		}

		Ok(regs)
	}
}

impl VirtualCPU for EhyveCPU {
	fn init(&mut self, entry_point: u64) -> Result<()>
	{
		let ret = unsafe { kvm_init_vcpu(self.cpufd, self.id as c_int, entry_point as size_t) };
		if ret != 0 {
			return Err(Error::InternalError);
		}

		Ok(())
	}

	fn run(&mut self) -> Result<()>
	{
		self.print_registers();

		loop {
			let ret = unsafe { kvm_run(self.cpufd) };

			if ret != 0 {
				return Err(Error::InternalError);
			}

			let reason = unsafe { (*self.run).exit_reason };

			match reason {
				Exit::Io => {
					//debug!("IO Exit");
					unsafe {
						let port = (*(*self.run).io()).port;
						let data = self.run as *const u8;
						let data = data.offset((*(*self.run).io()).data_offset as isize);
						let cstr = std::str::from_utf8(std::slice::from_raw_parts(data, 1)).unwrap();

						self.io_exit(port, cstr.to_string())?;
					}
				},
				Exit::Hlt => {
						debug!("Halt Exit");
				},
				_ => {
					error!("Unknown exit reason: {:?}", reason );
					//self.print_registers();

					return Err(Error::UnknownExitReason(reason));
				}
			}
		}
	}

	fn print_registers(&self)
	{
		utils::show_registers(self.id, &self.get_regs().unwrap(), &self.get_sregs().unwrap());
	}
}

impl Drop for EhyveCPU {
    fn drop(&mut self) {
		debug!("Drop vCPU {}", self.id);

		if self.cpufd >= 0 {
			unsafe {
         		close(self.cpufd);
				munmap(self.run as *mut c_void, std::mem::size_of::<Run>());
			}
		}
    }
}
<|endoftext|>


<commit_before>//! A CLI tool for inspecting the contents of a DICOM file
//! by printing it in a human readable format.
use dicom::object::open_file;
use dicom_dump::{ColorMode, DumpOptions};
use snafu::ErrorCompat;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

/// Exit code for when an error emerged while reading the DICOM file.
const ERROR_READ: i32 = -2;
/// Exit code for when an error emerged while dumping the file.
const ERROR_PRINT: i32 = -3;

#[cfg(windows)]
fn os_compatibility() -> Result<(), ()> {
    control::set_virtual_terminal(true)
}

#[cfg(not(windows))]
fn os_compatibility() -> Result<(), ()> {
    Ok(())
}

/// Dump the contents of DICOM files
#[derive(Debug, StructOpt)]
struct App {
    /// The DICOM file to read
    file: PathBuf,
    /// whether text value width limit is disabled
    /// (limited to `width` by default)
    #[structopt(long = "no-text-limit")]
    no_text_limit: bool,
    /// the width of the display
    /// (default is to check automatically)
    #[structopt(short = "w", long = "width")]
    width: Option<u32>,
    /// color mode
    #[structopt(long = "color", default_value = "auto")]
    color: ColorMode,
}

fn main() {
    os_compatibility().unwrap_or_else(|_| {
        eprintln!("Error setting OS compatibility for colored output");
    });

    let App {
        file: filename,
        no_text_limit,
        width,
        color,
    } = App::from_args();

    let obj = open_file(filename).unwrap_or_else(|e| {
        report(e);
        std::process::exit(ERROR_READ);
    });

    let width = width
        .or_else(|| term_size::dimensions().map(|(width, _)| width as u32))
        .unwrap_or(120);

    let mut options = DumpOptions::new();
    match options
        .no_text_limit(no_text_limit)
        .width(width)
        .color_mode(color)
        .dump_file(&obj)
    {
        Err(ref e) if e.kind() == ErrorKind::BrokenPipe => {
            // handle broken pipe separately with a no-op
        }
        Err(e) => {
            eprintln!("[ERROR] {}", e);
            std::process::exit(ERROR_PRINT);
        }
        _ => {} // all good
    }
}

fn report<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }

    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}
<commit_msg>[dump] Enable dumping more than one file<commit_after>//! A CLI tool for inspecting the contents of a DICOM file
//! by printing it in a human readable format.
use dicom::object::open_file;
use dicom_dump::{ColorMode, DumpOptions};
use snafu::ErrorCompat;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

/// Exit code for when an error emerged while reading the DICOM file.
const ERROR_READ: i32 = -2;
/// Exit code for when an error emerged while dumping the file.
const ERROR_PRINT: i32 = -3;

#[cfg(windows)]
fn os_compatibility() -> Result<(), ()> {
    control::set_virtual_terminal(true)
}

#[cfg(not(windows))]
fn os_compatibility() -> Result<(), ()> {
    Ok(())
}

/// Dump the contents of DICOM files
#[derive(Debug, StructOpt)]
struct App {
    /// The DICOM file(s) to read
    files: Vec<PathBuf>,
    /// whether text value width limit is disabled
    /// (limited to `width` by default)
    #[structopt(long = "no-text-limit")]
    no_text_limit: bool,
    /// the width of the display
    /// (default is to check automatically)
    #[structopt(short = "w", long = "width")]
    width: Option<u32>,
    /// color mode
    #[structopt(long = "color", default_value = "auto")]
    color: ColorMode,
}

fn main() {
    os_compatibility().unwrap_or_else(|_| {
        eprintln!("Error setting OS compatibility for colored output");
    });

    let App {
        files: filenames,
        no_text_limit,
        width,
        color,
    } = App::from_args();

    let width = width
        .or_else(|| term_size::dimensions().map(|(width, _)| width as u32))
        .unwrap_or(120);

    let mut options = DumpOptions::new();

    for filename in filenames {
        let obj = open_file(filename).unwrap_or_else(|e| {
            report(e);
            std::process::exit(ERROR_READ);
        });

        match options
            .no_text_limit(no_text_limit)
            .width(width)
            .color_mode(color)
            .dump_file(&obj)
        {
            Err(ref e) if e.kind() == ErrorKind::BrokenPipe => {
                // handle broken pipe separately with a no-op
            }
            Err(e) => {
                eprintln!("[ERROR] {}", e);
                std::process::exit(ERROR_PRINT);
            }
            _ => {} // all good
        }
    }
}

fn report<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }

    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}
<|endoftext|>


<commit_before>//! Error Reporting for Anonymous Region Lifetime Errors
//! where both the regions are anonymous.

use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::SubregionOrigin;

use rustc_errors::{struct_span_err, ErrorReported};

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
    /// Print the error message for lifetime errors when both the concerned regions are anonymous.
    ///
    /// Consider a case where we have
    ///
    /// ```no_run
    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
    ///     x.push(y);
    /// }
    /// ```
    ///
    /// The example gives
    ///
    /// ```text
    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
    ///                    ---      --- these references are declared with different lifetimes...
    ///     x.push(y);
    ///     ^ ...but data from `y` flows into `x` here
    /// ```
    ///
    /// It has been extended for the case of structs too.
    ///
    /// Consider the example
    ///
    /// ```no_run
    /// struct Ref<'a> { x: &'a u32 }
    /// ```
    ///
    /// ```text
    /// fn foo(mut x: Vec<Ref>, y: Ref) {
    ///                   ---      --- these structs are declared with different lifetimes...
    ///     x.push(y);
    ///     ^ ...but data from `y` flows into `x` here
    /// }
    /// ```
    ///
    /// It will later be extended to trait objects.
    pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
        let (span, sub, sup) = self.regions()?;

        if let Some(RegionResolutionError::ConcreteFailure(
            SubregionOrigin::ReferenceOutlivesReferent(..),
            ..,
        )) = self.error
        {
            // This error doesn't make much sense in this case.
            return None;
        }

        // Determine whether the sub and sup consist of both anonymous (elided) regions.
        let anon_reg_sup = self.tcx().is_suitable_region(sup)?;

        let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
        let scope_def_id_sup = anon_reg_sup.def_id;
        let bregion_sup = anon_reg_sup.boundregion;
        let scope_def_id_sub = anon_reg_sub.def_id;
        let bregion_sub = anon_reg_sub.boundregion;

        let ty_sup = self.find_anon_type(sup, &bregion_sup)?;

        let ty_sub = self.find_anon_type(sub, &bregion_sub)?;

        debug!(
            "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
            ty_sub, sup, bregion_sup
        );
        debug!(
            "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
            ty_sup, sub, bregion_sub
        );

        let (ty_sup, ty_fndecl_sup) = ty_sup;
        let (ty_sub, ty_fndecl_sub) = ty_sub;

        let AnonymousParamInfo { param: anon_param_sup, .. } =
            self.find_param_with_region(sup, sup)?;
        let AnonymousParamInfo { param: anon_param_sub, .. } =
            self.find_param_with_region(sub, sub)?;

        let sup_is_ret_type =
            self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
        let sub_is_ret_type =
            self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);

        let span_label_var1 = match anon_param_sup.pat.simple_ident() {
            Some(simple_ident) => format!(" from `{}`", simple_ident),
            None => String::new(),
        };

        let span_label_var2 = match anon_param_sub.pat.simple_ident() {
            Some(simple_ident) => format!(" into `{}`", simple_ident),
            None => String::new(),
        };

        let (span_1, span_2, main_label, span_label, future_return_type) =
            match (sup_is_ret_type, sub_is_ret_type) {
                (None, None) => {
                    let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
                        (
                            "this type is declared with multiple lifetimes...".to_owned(),
                            "...but data with one lifetime flows into the other here".to_owned(),
                        )
                    } else {
                        (
                            "these two types are declared with different lifetimes...".to_owned(),
                            format!("...but data{} flows{} here", span_label_var1, span_label_var2),
                        )
                    };
                    (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None)
                }

                (Some(ret_span), _) => {
                    let sup_future = self.future_return_type(scope_def_id_sup);
                    let (return_type, action) = if let Some(_) = sup_future {
                        ("returned future", "held across an await point")
                    } else {
                        ("return type", "returned")
                    };

                    (
                        ty_sub.span,
                        ret_span,
                        format!(
                            "this parameter and the {} are declared with different lifetimes...",
                            return_type
                        ),
                        format!("...but data{} is {} here", span_label_var1, action),
                        sup_future,
                    )
                }
                (_, Some(ret_span)) => {
                    let sub_future = self.future_return_type(scope_def_id_sub);
                    let (return_type, action) = if let Some(_) = sub_future {
                        ("returned future", "held across an await point")
                    } else {
                        ("return type", "returned")
                    };

                    (
                        ty_sup.span,
                        ret_span,
                        format!(
                            "this parameter and the {} are declared with different lifetimes...",
                            return_type
                        ),
                        format!("...but data{} is {} here", span_label_var1, action),
                        sub_future,
                    )
                }
            };

        let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");

        e.span_label(span_1, main_label);
        e.span_label(span_2, String::new());
        e.span_label(span, span_label);

        if let Some(t) = future_return_type {
            let snip = self
                .tcx()
                .sess
                .source_map()
                .span_to_snippet(t.span)
                .ok()
                .and_then(|s| match (&t.kind, s.as_str()) {
                    (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()),
                    (_, "") => None,
                    _ => Some(s),
                })
                .unwrap_or("{unnamed_type}".to_string());

            e.span_label(
                t.span,
                &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
            );
        }
        e.emit();
        Some(ErrorReported)
    }
}
<commit_msg>simplify if let Some(_) = x  to  if x.is_some()  (clippy::redundant_pattern_matching)<commit_after>//! Error Reporting for Anonymous Region Lifetime Errors
//! where both the regions are anonymous.

use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::SubregionOrigin;

use rustc_errors::{struct_span_err, ErrorReported};

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
    /// Print the error message for lifetime errors when both the concerned regions are anonymous.
    ///
    /// Consider a case where we have
    ///
    /// ```no_run
    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
    ///     x.push(y);
    /// }
    /// ```
    ///
    /// The example gives
    ///
    /// ```text
    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
    ///                    ---      --- these references are declared with different lifetimes...
    ///     x.push(y);
    ///     ^ ...but data from `y` flows into `x` here
    /// ```
    ///
    /// It has been extended for the case of structs too.
    ///
    /// Consider the example
    ///
    /// ```no_run
    /// struct Ref<'a> { x: &'a u32 }
    /// ```
    ///
    /// ```text
    /// fn foo(mut x: Vec<Ref>, y: Ref) {
    ///                   ---      --- these structs are declared with different lifetimes...
    ///     x.push(y);
    ///     ^ ...but data from `y` flows into `x` here
    /// }
    /// ```
    ///
    /// It will later be extended to trait objects.
    pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
        let (span, sub, sup) = self.regions()?;

        if let Some(RegionResolutionError::ConcreteFailure(
            SubregionOrigin::ReferenceOutlivesReferent(..),
            ..,
        )) = self.error
        {
            // This error doesn't make much sense in this case.
            return None;
        }

        // Determine whether the sub and sup consist of both anonymous (elided) regions.
        let anon_reg_sup = self.tcx().is_suitable_region(sup)?;

        let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
        let scope_def_id_sup = anon_reg_sup.def_id;
        let bregion_sup = anon_reg_sup.boundregion;
        let scope_def_id_sub = anon_reg_sub.def_id;
        let bregion_sub = anon_reg_sub.boundregion;

        let ty_sup = self.find_anon_type(sup, &bregion_sup)?;

        let ty_sub = self.find_anon_type(sub, &bregion_sub)?;

        debug!(
            "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
            ty_sub, sup, bregion_sup
        );
        debug!(
            "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
            ty_sup, sub, bregion_sub
        );

        let (ty_sup, ty_fndecl_sup) = ty_sup;
        let (ty_sub, ty_fndecl_sub) = ty_sub;

        let AnonymousParamInfo { param: anon_param_sup, .. } =
            self.find_param_with_region(sup, sup)?;
        let AnonymousParamInfo { param: anon_param_sub, .. } =
            self.find_param_with_region(sub, sub)?;

        let sup_is_ret_type =
            self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
        let sub_is_ret_type =
            self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);

        let span_label_var1 = match anon_param_sup.pat.simple_ident() {
            Some(simple_ident) => format!(" from `{}`", simple_ident),
            None => String::new(),
        };

        let span_label_var2 = match anon_param_sub.pat.simple_ident() {
            Some(simple_ident) => format!(" into `{}`", simple_ident),
            None => String::new(),
        };

        let (span_1, span_2, main_label, span_label, future_return_type) =
            match (sup_is_ret_type, sub_is_ret_type) {
                (None, None) => {
                    let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
                        (
                            "this type is declared with multiple lifetimes...".to_owned(),
                            "...but data with one lifetime flows into the other here".to_owned(),
                        )
                    } else {
                        (
                            "these two types are declared with different lifetimes...".to_owned(),
                            format!("...but data{} flows{} here", span_label_var1, span_label_var2),
                        )
                    };
                    (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None)
                }

                (Some(ret_span), _) => {
                    let sup_future = self.future_return_type(scope_def_id_sup);
                    let (return_type, action) = if sup_future.is_some() {
                        ("returned future", "held across an await point")
                    } else {
                        ("return type", "returned")
                    };

                    (
                        ty_sub.span,
                        ret_span,
                        format!(
                            "this parameter and the {} are declared with different lifetimes...",
                            return_type
                        ),
                        format!("...but data{} is {} here", span_label_var1, action),
                        sup_future,
                    )
                }
                (_, Some(ret_span)) => {
                    let sub_future = self.future_return_type(scope_def_id_sub);
                    let (return_type, action) = if sub_future.is_some() {
                        ("returned future", "held across an await point")
                    } else {
                        ("return type", "returned")
                    };

                    (
                        ty_sup.span,
                        ret_span,
                        format!(
                            "this parameter and the {} are declared with different lifetimes...",
                            return_type
                        ),
                        format!("...but data{} is {} here", span_label_var1, action),
                        sub_future,
                    )
                }
            };

        let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");

        e.span_label(span_1, main_label);
        e.span_label(span_2, String::new());
        e.span_label(span, span_label);

        if let Some(t) = future_return_type {
            let snip = self
                .tcx()
                .sess
                .source_map()
                .span_to_snippet(t.span)
                .ok()
                .and_then(|s| match (&t.kind, s.as_str()) {
                    (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()),
                    (_, "") => None,
                    _ => Some(s),
                })
                .unwrap_or("{unnamed_type}".to_string());

            e.span_label(
                t.span,
                &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
            );
        }
        e.emit();
        Some(ErrorReported)
    }
}
<|endoftext|>


<commit_before>extern crate utf8parse;
//use ::utf8parse::*;
use utf8parse::Receiver;

use parking_lot::RwLock;
use std::rc::Rc;

use crate::core::codec::text::utf8;
use crate::core::view::ContentFilter;
use crate::core::view::FilterData;
use crate::core::view::FilterIo;
use crate::core::view::LayoutEnv;
use crate::core::view::Unicode;
use crate::core::view::View;
use crate::core::Editor;

use crate::core::codepointinfo::TextStyle;

// the consecutive offsets are derived from size
pub struct TextCodecFilter {
    // data
}

impl TextCodecFilter {
    pub fn new() -> Self {
        TextCodecFilter {}
    }
}

impl ContentFilter<'_> for TextCodecFilter {
    fn name(&self) -> &'static str {
        &"TextCodecFilter"
    }

    fn run(
        &mut self,
        _view: &View,
        _env: &mut LayoutEnv,
        filter_in: &[FilterIo],
        filter_out: &mut Vec<FilterIo>,
    ) {
        // ref ? in setup
        //        let _tm = view.mode_ctx::<TextModeContext>("text-mode");

        // put in common
        if filter_in.is_empty() {
            dbg_println!("TextCodecFilter : empty input !!!!");
            *filter_out = vec![];
            return;
        }

        dbg_println!(
            "TextCodecFilter : start @ offset {}",
            filter_in[0].offset.unwrap()
        );

        for d in filter_in.iter() {
            let base_offset = d.offset.unwrap();

            match &d.data {
                FilterData::ByteArray { vec } => {
                    //let mut decoded = vec![];
                    let mut decoded = Vec::with_capacity(vec.len());
                    unsafe {
                        decoded.set_len(vec.len());
                    }
                    for (idx, val) in vec.iter().enumerate() {
                        let new_io = Unicode {
                            size: 1,
                            cp: *val as u32,
                        };
                        // decoded.push(new_io);
                        // decoded[idx] = new_io;
                        unsafe {
                            *decoded.get_unchecked_mut(idx) = new_io;
                        }
                    }

                    // single bloc with base offset
                    filter_out.push(FilterIo {
                        // general info
                        metadata: false,
                        style: TextStyle::new(),
                        //
                        offset: Some(base_offset),
                        size: 0, // count(data) ?
                        data: FilterData::UnicodeArray { vec: decoded },
                    });
                }

                FilterData::EndOfStream | FilterData::CustomLimitReached => {
                    filter_out.push(d.clone());
                }

                _ => {
                    /* unexpected */
                    dbg_println!("receive unexpected io {:?}", d.data);
                    panic!("");
                }
            }
        }
    }
}

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

// TODO(ceg): pass codec in env
pub struct Utf8FilterCtx {
    cp_size: usize,
    state: u32,
    codep: u32,
    accum_size: u32,
    accum: [u8; 4],
    error: bool,

    //
    out: Vec<Unicode>,
}

impl Utf8FilterCtx {
    pub fn new() -> Self {
        Utf8FilterCtx {
            state: 0,
            codep: 0,
            cp_size: 0,
            accum: [0; 4],
            accum_size: 0,
            error: false,
            out: vec![],
        }
    }
}

// TODO(ceg): remove Option<>
// always ?
#[inline(always)]
fn filter_utf8_byte(ctx: &mut Utf8FilterCtx, val: u8) {
    ctx.accum[ctx.cp_size] = val;
    ctx.accum_size += 1;
    loop {
        // (re)decode current byte: restart on previous bytes if error
        ctx.state = utf8::decode_byte(ctx.state, ctx.accum[ctx.cp_size], &mut ctx.codep);
        /*
                if DEBUG {
                    dbg_println!("utf8 decode byte  '0x{:x}'", ctx.accum[ctx.cp_size - 1]);
                    dbg_println!(
                        "utf8 ACCUM {:x?}' accum_size {} cp_size = {}",
                        ctx.accum,
                        ctx.accum_size,
                        ctx.cp_size
                    );
                }
        */
        match ctx.state {
            utf8::UTF8_ACCEPT => {
                /*
                                if DEBUG {
                                    dbg_println!(
                                ">>> utf8 decode cp OK current_offset = {:?} from_offset = {:?} ctx.cp_size {} cp:u32 {}",
                                ctx.current_offset,
                                ctx.from_offset,
                                ctx.cp_size, ctx.codep);
                                }
                */
                ctx.out.push(Unicode {
                    cp: ctx.codep,
                    size: 1 + ctx.cp_size as u32,
                });

                // restart
                ctx.state = 0;
                ctx.codep = 0;
                ctx.cp_size = 0;

                ctx.accum_size = 0;
                // drop accum debug only  ?
                // ctx.accum.fill(0);
                break;
            }

            utf8::UTF8_REJECT => {
                /*
                                if DEBUG {
                                    dbg_println!(
                                        "utf8 decode cp ERROR current_offset = {:?} from_offset = {:?} cp_size {}",
                                        ctx.current_offset,
                                        ctx.from_offset,
                                        ctx.cp_size
                                    );
                                }
                */
                // decode error : invalid sequence
                //let io = utf8_default_codepoint(ctx.from_offset, 1, 0xfffd);
                ctx.out.push(Unicode {
                    cp: 0xfffd,
                    size: 1,
                });

                // restart @ next byte
                ctx.codep = 0;
                ctx.cp_size = 0;
                ctx.state = 0; // reset state on error

                // TODO(ceg) use raw_data[pos] to restart
                // accum is an extract of raw data: to handle truncated input
                // shift accum
                ctx.accum.rotate_left(1);
                // ctx.accum[3] = 0; debug

                /* restart decoder at accum[ctx.cp_size-1] */
                ctx.accum_size -= 1;
                if ctx.accum_size == 0 {
                    return;
                }
                continue;
            }

            _ => {
                ctx.cp_size += 1; // valid intermediate state, need more data
                break;
            }
        }
    }
}

impl Receiver for Utf8FilterCtx {
    fn codepoint(&mut self, c: char) {
        self.error = false;
        self.codep = 0;
        self.cp_size = 0;
        self.accum_size = 0;
        self.out.push(Unicode {
            cp: c as u32,
            size: 1 + self.cp_size as u32,
        });
    }

    fn invalid_sequence(&mut self) {
        // restart @ next byte
        self.error = true;
        self.codep = 0;
        self.cp_size = 0;

        // TODO(ceg) use raw_data[pos] to restart
        // accum is an extract of raw data: to handle truncated input
        // shift accum
        self.accum.rotate_left(1);

        // ctx.accum[3] = 0; debug
        /* restart decoder at accum[ctx.cp_size-1] */
        self.accum_size -= 1;
        self.out.push(Unicode {
            cp: 0xfffd,
            size: 1,
        });
    }
}

// if no encoding error found and first input byte is "utf8" synchronized
#[inline]
pub fn filter_utf8_bytearray_shift_accum(
    mut ctx: &mut Utf8FilterCtx,
    vec: &Vec<u8>,
    _filter_out: &mut Vec<FilterIo>,
) {
    for b in vec {
        let val = *b as u32;

        //        dbg_println!("read val  {:x}", val);
        if val < 0b10000000 {
            // flush previous ?
            if ctx.cp_size > 1 {
                ctx.out.push(Unicode {
                    cp: ctx.codep as u32,
                    size: ctx.cp_size as u32,
                });
            }

            //            dbg_println!("decoded ctx.codep({}) as '{}'", ctx.codep, unsafe {
            //                char::from_u32_unchecked(val)
            //            });

            ctx.out.push(Unicode { cp: val, size: 1 });

            // reset
            ctx.codep = 0;
            ctx.cp_size = 0;
            continue;
        }

        //          mmxxxxxx   continuation
        if (val & 0b11000000) == 0b10000000 {
            ctx.codep = (ctx.codep << 6) | (val & 0b00111111);
            ctx.cp_size += 1;
        } else {
            // flush
            if ctx.cp_size > 1 {
                ctx.out.push(Unicode {
                    cp: ctx.codep as u32,
                    size: ctx.cp_size as u32,
                });

                //                dbg_println!("decoded ctx.codep({}) as '{}'", ctx.codep, unsafe {
                //                    char::from_u32_unchecked(ctx.codep)
                //                });
            }

            ctx.cp_size += 1;
            // check seq len
            if (val & 0b11000000) == 0b11000000 {
                ctx.codep = val & 0b00011111;
            }
            if (val & 0b11100000) == 0b11100000 {
                ctx.codep = val & 0b00001111;
            }
            if (val & 0b11110000) == 0b00000111 {
                ctx.codep = val & 0b00111111;
            }
        }
    }
}

#[inline]
pub fn filter_utf8_bytearray(
    ctx: &mut Utf8FilterCtx,
    vec: &Vec<u8>,
    filter_out: &mut Vec<FilterIo>,
) {
    //    dbg_println!("filter_utf8_bytearray : input len =  {}", vec.len());

    ctx.out.clear();

    let mut ctx = ctx;

    // TODO(ceg): move accum between state structs
    if true {
        for val in vec {
            filter_utf8_byte(&mut ctx, *val);
        }
    } else {
        let mut parser = utf8parse::Parser::new();
        for val in vec {
            ctx.accum[ctx.cp_size] = *val;
            ctx.accum_size += 1;
            let pos = ctx.cp_size;
            let b = ctx.accum[pos];
            ctx.cp_size += 1;
            parser.advance(ctx, b);
            // no error handling on truncated input
        }
    }

    let new_io = FilterIo {
        // general info
        metadata: false,
        style: TextStyle::new(),
        offset: None, // not here
        size: 0,      // count(data) ?
        data: FilterData::UnicodeArray {
            vec: ctx.out.clone(),
        },
        // TODO(ceg): add style infos ?
    };

    filter_out.push(new_io);
}

pub struct Utf8Filter {
    // data
    ctx: Utf8FilterCtx,
}

impl Utf8Filter {
    pub fn new() -> Self {
        Utf8Filter {
            ctx: Utf8FilterCtx::new(),
        }
    }
}

impl ContentFilter<'_> for Utf8Filter {
    fn name(&self) -> &'static str {
        &"Utf8Filter"
    }

    fn setup(
        &mut self,
        _editor: &Editor,
        _env: &mut LayoutEnv,
        _view: &Rc<RwLock<View>>,
        _parent_view: Option<&View<'static>>,
    ) {
        self.ctx = Utf8FilterCtx::new();
    }

    fn run(
        &mut self,
        _view: &View,
        _env: &mut LayoutEnv,
        filter_in: &[FilterIo],
        mut filter_out: &mut Vec<FilterIo>,
    ) {
        // put in common
        if filter_in.is_empty() {
            dbg_println!("Utf8Filter : empty input !!!!");
            *filter_out = vec![];
            return;
        }

        self.ctx.out.clear();

        for d in filter_in {
            match &d.data {
                FilterData::ByteArray { vec } => {
                    filter_utf8_bytearray(&mut self.ctx, vec, &mut filter_out);
                    //filter_utf8_bytearray_shift_accum(&mut self.ctx, vec, &mut filter_out);
                }

                FilterData::EndOfStream | FilterData::CustomLimitReached => {
                    // NB: accumulated bytes means incomplete sequence
                    // flush each byte as invalid char
                    for _i in 0..self.ctx.cp_size {
                        // let io = utf8_default_codepoint(self.ctx.from_offset + i as u64, 1, 0xfffd);
                        // filter_out.push(io);
                        self.ctx.out.push(Unicode {
                            cp: 0xfffd,
                            size: 1,
                        });
                    }

                    // TODO(ceg): flush remaining bytes
                    filter_out.push(d.clone());
                }

                _ => {
                    /* unexpected */
                    dbg_println!("receive unexpected io {:?}", d.data);
                    panic!("");
                }
            }
        }
    }
}
<commit_msg>cleanup: remove useless code<commit_after>extern crate utf8parse;
//use ::utf8parse::*;
use utf8parse::Receiver;

use parking_lot::RwLock;
use std::rc::Rc;

use crate::core::codec::text::utf8;
use crate::core::view::ContentFilter;
use crate::core::view::FilterData;
use crate::core::view::FilterIo;
use crate::core::view::LayoutEnv;
use crate::core::view::Unicode;
use crate::core::view::View;
use crate::core::Editor;

use crate::core::codepointinfo::TextStyle;

// the consecutive offsets are derived from size
pub struct TextCodecFilter {
    // data
}

impl TextCodecFilter {
    pub fn new() -> Self {
        TextCodecFilter {}
    }
}

impl ContentFilter<'_> for TextCodecFilter {
    fn name(&self) -> &'static str {
        &"TextCodecFilter"
    }

    fn run(
        &mut self,
        _view: &View,
        _env: &mut LayoutEnv,
        filter_in: &[FilterIo],
        filter_out: &mut Vec<FilterIo>,
    ) {
        for d in filter_in.iter() {
            let base_offset = d.offset.unwrap();

            match &d.data {
                FilterData::ByteArray { vec } => {
                    //let mut decoded = vec![];
                    let mut decoded = Vec::with_capacity(vec.len());
                    unsafe {
                        decoded.set_len(vec.len());
                    }
                    for (idx, val) in vec.iter().enumerate() {
                        let new_io = Unicode {
                            size: 1,
                            cp: *val as u32,
                        };
                        // decoded.push(new_io);
                        // decoded[idx] = new_io;
                        unsafe {
                            *decoded.get_unchecked_mut(idx) = new_io;
                        }
                    }

                    // single bloc with base offset
                    filter_out.push(FilterIo {
                        // general info
                        metadata: false,
                        style: TextStyle::new(),
                        //
                        offset: Some(base_offset),
                        size: 0, // count(data) ?
                        data: FilterData::UnicodeArray { vec: decoded },
                    });
                }

                FilterData::EndOfStream | FilterData::CustomLimitReached => {
                    filter_out.push(d.clone());
                }

                _ => {
                    /* unexpected */
                    dbg_println!("receive unexpected io {:?}", d.data);
                    panic!("");
                }
            }
        }
    }
}

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

// TODO(ceg): pass codec in env
pub struct Utf8FilterCtx {
    cp_size: usize,
    state: u32,
    codep: u32,
    accum_size: u32,
    accum: [u8; 4],
    error: bool,

    //
    out: Vec<Unicode>,
}

impl Utf8FilterCtx {
    pub fn new() -> Self {
        Utf8FilterCtx {
            state: 0,
            codep: 0,
            cp_size: 0,
            accum: [0; 4],
            accum_size: 0,
            error: false,
            out: vec![],
        }
    }
}

// TODO(ceg): remove Option<>
// always ?
#[inline(always)]
fn filter_utf8_byte(ctx: &mut Utf8FilterCtx, val: u8) {
    ctx.accum[ctx.cp_size] = val;
    ctx.accum_size += 1;
    loop {
        // (re)decode current byte: restart on previous bytes if error
        ctx.state = utf8::decode_byte(ctx.state, ctx.accum[ctx.cp_size], &mut ctx.codep);
        match ctx.state {
            utf8::UTF8_ACCEPT => {
                ctx.out.push(Unicode {
                    cp: ctx.codep,
                    size: 1 + ctx.cp_size as u32,
                });

                // restart
                ctx.state = 0;
                ctx.codep = 0;
                ctx.cp_size = 0;

                ctx.accum_size = 0;
                // drop accum debug only  ?
                // ctx.accum.fill(0);
                break;
            }

            utf8::UTF8_REJECT => {
                // decode error : invalid sequence
                //let io = utf8_default_codepoint(ctx.from_offset, 1, 0xfffd);
                ctx.out.push(Unicode {
                    cp: 0xfffd,
                    size: 1,
                });

                // restart @ next byte
                ctx.codep = 0;
                ctx.cp_size = 0;
                ctx.state = 0; // reset state on error

                // TODO(ceg) use raw_data[pos] to restart
                // accum is an extract of raw data: to handle truncated input
                // shift accum
                ctx.accum.rotate_left(1);
                // ctx.accum[3] = 0; debug

                /* restart decoder at accum[ctx.cp_size-1] */
                ctx.accum_size -= 1;
                if ctx.accum_size == 0 {
                    return;
                }
                continue;
            }

            _ => {
                ctx.cp_size += 1; // valid intermediate state, need more data
                break;
            }
        }
    }
}

impl Receiver for Utf8FilterCtx {
    fn codepoint(&mut self, c: char) {
        self.error = false;
        self.codep = 0;
        self.cp_size = 0;
        self.accum_size = 0;
        self.out.push(Unicode {
            cp: c as u32,
            size: 1 + self.cp_size as u32,
        });
    }

    fn invalid_sequence(&mut self) {
        // restart @ next byte
        self.error = true;
        self.codep = 0;
        self.cp_size = 0;

        // TODO(ceg) use raw_data[pos] to restart
        // accum is an extract of raw data: to handle truncated input
        // shift accum
        self.accum.rotate_left(1);

        // ctx.accum[3] = 0; debug
        /* restart decoder at accum[ctx.cp_size-1] */
        self.accum_size -= 1;
        self.out.push(Unicode {
            cp: 0xfffd,
            size: 1,
        });
    }
}

#[inline]
pub fn filter_utf8_bytearray(
    ctx: &mut Utf8FilterCtx,
    vec: &Vec<u8>,
    filter_out: &mut Vec<FilterIo>,
) {
    //    dbg_println!("filter_utf8_bytearray : input len =  {}", vec.len());

    ctx.out.clear();

    let mut ctx = ctx;

    // TODO(ceg): move accum between state structs
    if true {
        for val in vec {
            filter_utf8_byte(&mut ctx, *val);
        }
    } else {
        let mut parser = utf8parse::Parser::new();
        for val in vec {
            ctx.accum[ctx.cp_size] = *val;
            ctx.accum_size += 1;
            let pos = ctx.cp_size;
            let b = ctx.accum[pos];
            ctx.cp_size += 1;
            parser.advance(ctx, b);
            // no error handling on truncated input
        }
    }

    let new_io = FilterIo {
        // general info
        metadata: false,
        style: TextStyle::new(),
        offset: None, // not here
        size: 0,      // count(data) ?
        data: FilterData::UnicodeArray {
            vec: ctx.out.clone(),
        },
        // TODO(ceg): add style infos ?
    };

    filter_out.push(new_io);
}

pub struct Utf8Filter {
    // data
    ctx: Utf8FilterCtx,
}

impl Utf8Filter {
    pub fn new() -> Self {
        Utf8Filter {
            ctx: Utf8FilterCtx::new(),
        }
    }
}

impl ContentFilter<'_> for Utf8Filter {
    fn name(&self) -> &'static str {
        &"Utf8Filter"
    }

    fn setup(
        &mut self,
        _editor: &Editor,
        _env: &mut LayoutEnv,
        _view: &Rc<RwLock<View>>,
        _parent_view: Option<&View<'static>>,
    ) {
        self.ctx = Utf8FilterCtx::new();
    }

    fn run(
        &mut self,
        _view: &View,
        _env: &mut LayoutEnv,
        filter_in: &[FilterIo],
        mut filter_out: &mut Vec<FilterIo>,
    ) {
        // put in common
        if filter_in.is_empty() {
            dbg_println!("Utf8Filter : empty input !!!!");
            *filter_out = vec![];
            return;
        }

        self.ctx.out.clear();

        for d in filter_in {
            match &d.data {
                FilterData::ByteArray { vec } => {
                    filter_utf8_bytearray(&mut self.ctx, vec, &mut filter_out);
                }

                FilterData::EndOfStream | FilterData::CustomLimitReached => {
                    // NB: accumulated bytes means incomplete sequence
                    // flush each byte as invalid char
                    for _i in 0..self.ctx.cp_size {
                        // let io = utf8_default_codepoint(self.ctx.from_offset + i as u64, 1, 0xfffd);
                        // filter_out.push(io);
                        self.ctx.out.push(Unicode {
                            cp: 0xfffd,
                            size: 1,
                        });
                    }

                    // TODO(ceg): flush remaining bytes
                    filter_out.push(d.clone());
                }

                _ => {
                    /* unexpected */
                    dbg_println!("receive unexpected io {:?}", d.data);
                    panic!("");
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: (Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(&reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // if any of the coefs are 0, then an element in that molecule is missing on the other side
    // of the reaction
    if let Some(pos) = coefs.iter().position(|&c| c == 0.0) {
        let (ref lhs, ref rhs) = reaction;
        let molecule = lhs.iter().chain(rhs.iter()).nth(pos).unwrap();
        let begin = molecule.first().unwrap().pos;
        let len = molecule.last().unwrap().pos + molecule.last().unwrap().len - begin;
        return Err(CTError {
            kind: InputError,
            desc: format!("An element in {} is missing on the other side of the reaction", molecule),
            pos: Some((begin, len)),
        })
    }

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let &(ref lhs, ref rhs) = reaction;
        let mut names = Vec::<&str>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            for elem in molecule.iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name.as_slice());
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<commit_msg>Change balance_reaction to take a reference<commit_after>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // if any of the coefs are 0, then an element in that molecule is missing on the other side
    // of the reaction
    if let Some(pos) = coefs.iter().position(|&c| c == 0.0) {
        let &(ref lhs, ref rhs) = reaction;
        let molecule = lhs.iter().chain(rhs.iter()).nth(pos).unwrap();
        let begin = molecule.first().unwrap().pos;
        let len = molecule.last().unwrap().pos + molecule.last().unwrap().len - begin;
        return Err(CTError {
            kind: InputError,
            desc: format!("An element in {} is missing on the other side of the reaction", molecule),
            pos: Some((begin, len)),
        })
    }

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction(reaction: &(Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let &(ref lhs, ref rhs) = reaction;
        let mut names = Vec::<&str>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            for elem in molecule.iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name.as_slice());
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(&reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(&reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<|endoftext|>


<commit_before>extern crate transitfeed;

use transitfeed::{Agency, Calendar, CalendarDate, FareAttribute, FareRule, FeedInfo, Frequency,
                  GTFSIterator, Route, ShapePoint, Stop, StopTime, Transfer, Trip};

#[test]
fn test_read_agencies() {
    let iter: GTFSIterator<_, Agency> =
        GTFSIterator::from_path("./examples/good_feed/agency.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stops() {
    let iter: GTFSIterator<_, Stop> =
        GTFSIterator::from_path("./examples/good_feed/stops.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_routes() {
    let iter: GTFSIterator<_, Route> =
        GTFSIterator::from_path("./examples/good_feed/routes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_trips() {
    let iter: GTFSIterator<_, Trip> =
        GTFSIterator::from_path("./examples/good_feed/trips.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stop_times() {
    let iter: GTFSIterator<_, StopTime> =
        GTFSIterator::from_path("./examples/good_feed/stop_times.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar() {
    let iter: GTFSIterator<_, Calendar> =
        GTFSIterator::from_path("./examples/good_feed/calendar.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar_dates() {
    let iter: GTFSIterator<_, CalendarDate> =
        GTFSIterator::from_path("./examples/good_feed/calendar_dates.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_attributes() {
    let iter: GTFSIterator<_, FareAttribute> =
        GTFSIterator::from_path("./examples/good_feed/fare_attributes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_rules() {
    let iter: GTFSIterator<_, FareRule> =
        GTFSIterator::from_path("./examples/good_feed/fare_rules.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_shapes() {
    let iter: GTFSIterator<_, ShapePoint> =
        GTFSIterator::from_path("./examples/good_feed/shapes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_frequencies() {
    let iter: GTFSIterator<_, Frequency> =
        GTFSIterator::from_path("./examples/good_feed/frequencies.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_transfers() {
    let iter: GTFSIterator<_, Transfer> =
        GTFSIterator::from_path("./examples/good_feed/transfers.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

/*
#[test]
fn test_read_feed_info() {
    let iter: GTFSIterator<_, FeedInfo> =
        GTFSIterator::from_path("./examples/good_feed/feed_info.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}
*/
<commit_msg>Revert "Remove feed_info test as its not in the sample data"<commit_after>extern crate transitfeed;

use transitfeed::{Agency, Calendar, CalendarDate, FareAttribute, FareRule, FeedInfo, Frequency,
                  GTFSIterator, Route, ShapePoint, Stop, StopTime, Transfer, Trip};

#[test]
fn test_read_agencies() {
    let iter: GTFSIterator<_, Agency> =
        GTFSIterator::from_path("./examples/good_feed/agency.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stops() {
    let iter: GTFSIterator<_, Stop> =
        GTFSIterator::from_path("./examples/good_feed/stops.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_routes() {
    let iter: GTFSIterator<_, Route> =
        GTFSIterator::from_path("./examples/good_feed/routes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_trips() {
    let iter: GTFSIterator<_, Trip> =
        GTFSIterator::from_path("./examples/good_feed/trips.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stop_times() {
    let iter: GTFSIterator<_, StopTime> =
        GTFSIterator::from_path("./examples/good_feed/stop_times.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar() {
    let iter: GTFSIterator<_, Calendar> =
        GTFSIterator::from_path("./examples/good_feed/calendar.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar_dates() {
    let iter: GTFSIterator<_, CalendarDate> =
        GTFSIterator::from_path("./examples/good_feed/calendar_dates.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_attributes() {
    let iter: GTFSIterator<_, FareAttribute> =
        GTFSIterator::from_path("./examples/good_feed/fare_attributes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_rules() {
    let iter: GTFSIterator<_, FareRule> =
        GTFSIterator::from_path("./examples/good_feed/fare_rules.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_shapes() {
    let iter: GTFSIterator<_, ShapePoint> =
        GTFSIterator::from_path("./examples/good_feed/shapes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_frequencies() {
    let iter: GTFSIterator<_, Frequency> =
        GTFSIterator::from_path("./examples/good_feed/frequencies.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_transfers() {
    let iter: GTFSIterator<_, Transfer> =
        GTFSIterator::from_path("./examples/good_feed/transfers.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_feed_info() {
    let iter: GTFSIterator<_, FeedInfo> =
        GTFSIterator::from_path("./examples/good_feed/feed_info.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}
<|endoftext|>