<commit_before>#[macro_use]
extern crate chomp;

use std::fs::File;
use std::io::Read;
use std::str;
use chomp::{Input, U8Result, parse_only};
use chomp::{count, eof, option, or, sep_by, string, take_while, take_while1, token};
use chomp::ascii::{digit};
use chomp::buffer::{Source, Stream, StreamError};

fn to_i32(slice: Vec<u8>) -> i32 {
    slice.iter().fold(0, |acc, &d| (acc * 10) + ((d - ('0' as u8)) as i32))
}

fn year(i: Input<u8>) -> U8Result<i32> {
    count(i, 4, |i| digit(i)).map(to_i32)
}

fn month(i: Input<u8>) -> U8Result<i32> {
    count(i, 2, |i| digit(i)).map(to_i32)
}

fn day(i: Input<u8>) -> U8Result<i32> {
    count(i, 2, |i| digit(i)).map(to_i32)
}

fn date(i: Input<u8>) -> U8Result<(i32, i32, i32)> {
    parse!{i;
        let year =  year();
                    token(b'-');
        let month = month();
                    token(b'-');
        let day =   day();
        ret (year, month, day)
    }
}

fn is_whitespace(c: u8) -> bool {
    c == b'\t' || c == b' '
}

fn whitespace(i: Input<u8>) -> U8Result<bool> {
    take_while(i, is_whitespace).map(|ws| ws.len() > 0)
}

fn mandatory_whitespace(i: Input<u8>) -> U8Result<()> {
    take_while1(i, is_whitespace).map(|_| ())
}

fn is_quoted_symbol_char(c: u8) -> bool {
    c != b'\"' && c != b'\r' && c != b'\n'
}

fn quoted_symbol(i: Input<u8>) -> U8Result<&str> {
    parse!{i;
        token(b'\"');
        let symbol = take_while1(is_quoted_symbol_char);
        token(b'\"');
        ret str::from_utf8(symbol).unwrap()
    }
}

fn is_digit(c: u8) -> bool {
    b'0' <= c && c <= b'9'
}

fn is_newline(c: u8) -> bool {
    c == b'\r' && c == b'\n'
}

fn is_unquoted_symbol_char(c: u8) -> bool {
    //"-0123456789; \"\t\r\n".as_bytes().iter().all(|b| b != c))
    c != b'-' && c != b';' && c != b'\"' && !is_newline(c)
     && !is_digit(c) && !is_whitespace(c)
}

fn unquoted_symbol(i: Input<u8>) -> U8Result<&str> {
    take_while1(i, is_unquoted_symbol_char).map(|b| str::from_utf8(b).unwrap())
}

fn symbol(i: Input<u8>) -> U8Result<&str> {
    or(i, quoted_symbol, unquoted_symbol)
}

fn is_quantity_char(c: u8) -> bool {
    is_digit(c) || c == b'.' || c == b','
}

fn make_quantity(sign: u8, number: &[u8]) -> String {
    let mut qty = String::new();
    if sign == b'-' {
        qty.push_str(str::from_utf8(&[sign]).unwrap());
    }
    qty.push_str(str::from_utf8(number).unwrap());
    qty.replace(",", "");
    qty
}

fn quantity(i: Input<u8>) -> U8Result<String> {
    parse!{i;
        let sign = option(|i| token(i, b'-'), b'+');
        let number = take_while1(is_quantity_char);
        ret make_quantity(sign, number)
    }
}

fn amount_symbol_then_quantity(i: Input<u8>) -> U8Result<(String, &str)> {
    parse!{i;
        let symbol = symbol();
        whitespace();
        let quantity = quantity();
        ret (quantity, symbol)
    }
}

fn amount_quantity_then_symbol(i: Input<u8>) -> U8Result<(String, &str)> {
    parse!{i;
        let quantity = quantity();
        whitespace();
        let symbol = symbol();
        ret (quantity, symbol)
    }
}

fn amount(i: Input<u8>) -> U8Result<(String, &str)> {
    or(i, amount_symbol_then_quantity, amount_quantity_then_symbol)
}

fn price(i: Input<u8>) -> U8Result<((i32, i32, i32), &str, (String, &str))> {
    parse!{i;
        token(b'P');
        mandatory_whitespace();
        let date = date();
        mandatory_whitespace();
        let symbol = symbol();
        mandatory_whitespace();
        let amount = amount();
        ret (date, symbol, amount)
    }
}

fn line_ending(i: Input<u8>) -> U8Result<()> {
    or(i,
        |i| token(i, b'\n').map(|_| ()),
        |i| string(i, b"\r\n").map(|_| ()))
}

fn price_line(i: Input<u8>) -> U8Result<((i32, i32, i32), &str, (String, &str))> {
    parse!{i;
        let price = price();
        line_ending();
        ret price
    }
}

// fn price_db(i: Input<u8>) -> U8Result<Vec<((i32, i32, i32), &str, (String, &str))>> {
//     parse!{i;
//         let prices = sep_by(price, line_ending);
//         eof();
//         ret prices
//     }
// }

fn main() {
    // println!("{:?}", parse_only(mandatory_whitespace, b" "));
    // println!("{:?}", parse_only(date, b"2016-02-06"));
    // println!("{:?}", parse_only(symbol, b"\"AIM1651\""));
    // println!("{:?}", parse_only(symbol, b"$"));
    // println!("{:?}", parse_only(amount, b"$-5.82"));
    // println!("{:?}", parse_only(price, b"P 2016-02-06 \"AIM1651\" $5.82"));
    // println!("{:?}", parse_only(price_db, b"P 2016-02-06 \"AIM1651\" $5.82\r\nP 2016-02-07 \"AIM1651\" $5.85"));

    let price_db_filepath = "/Users/mark/Nexus/Documents/finances/ledger/.pricedb";
    let file = File::open(price_db_filepath).ok().expect("Failed to open file");

    let mut source = Source::new(file);
    let mut n = 0;

    loop {
        match source.parse(price_line) {
            Ok(_)                        => n += 1,
            Err(StreamError::Retry)      => {}, // Needed to refill buffer when necessary
            Err(StreamError::EndOfInput) => break,
            Err(e)                       => { panic!("{:?}", e); }
        }
    }

    println!("Parsed {} prices", n);

    // match source.parse(price_db) {
    //     Ok(prices)  => println!("Parsed {} prices", prices.len()),
    //     Err(e)      => println!("Uhm, wat? {:?}", e)
    // }
}
<commit_msg>Code cleanup<commit_after>#[macro_use]
extern crate chomp;

use std::fs::File;
use std::str;
use chomp::{Input, U8Result, parse_only};
use chomp::{count, option, or, string, take_while, take_while1, token};
use chomp::ascii::{digit};
use chomp::buffer::{Source, Stream, StreamError};

// HELPERS

fn to_i32(slice: Vec<u8>) -> i32 {
    slice.iter().fold(0, |acc, &d| (acc * 10) + ((d - ('0' as u8)) as i32))
}

fn make_quantity(sign: u8, number: &[u8]) -> String {
    let mut qty = String::new();
    if sign == b'-' {
        qty.push_str(str::from_utf8(&[sign]).unwrap());
    }
    qty.push_str(str::from_utf8(number).unwrap());
    qty.replace(",", "");
    qty
}

fn is_whitespace_char(c: u8) -> bool {
    c == b'\t' || c == b' '
}

fn is_quoted_symbol_char(c: u8) -> bool {
    c != b'\"' && c != b'\r' && c != b'\n'
}

fn is_digit_char(c: u8) -> bool {
    b'0' <= c && c <= b'9'
}

fn is_newline_char(c: u8) -> bool {
    c == b'\r' && c == b'\n'
}

fn is_unquoted_symbol_char(c: u8) -> bool {
    c != b'-' && c != b';' && c != b'\"' && !is_newline_char(c)
     && !is_digit_char(c) && !is_whitespace_char(c)
}

fn is_quantity_char(c: u8) -> bool {
    is_digit_char(c) || c == b'.' || c == b','
}

// PARSERS

fn whitespace(i: Input<u8>) -> U8Result<bool> {
    take_while(i, is_whitespace_char).map(|ws| ws.len() > 0)
}

fn mandatory_whitespace(i: Input<u8>) -> U8Result<()> {
    take_while1(i, is_whitespace_char).map(|_| ())
}

fn line_ending(i: Input<u8>) -> U8Result<()> {
    or(i,
        |i| token(i, b'\n').map(|_| ()),
        |i| string(i, b"\r\n").map(|_| ()))
}

fn year(i: Input<u8>) -> U8Result<i32> {
    count(i, 4, |i| digit(i)).map(to_i32)
}

fn month(i: Input<u8>) -> U8Result<i32> {
    count(i, 2, |i| digit(i)).map(to_i32)
}

fn day(i: Input<u8>) -> U8Result<i32> {
    count(i, 2, |i| digit(i)).map(to_i32)
}

fn date(i: Input<u8>) -> U8Result<(i32, i32, i32)> {
    parse!{i;
        let year =  year();
                    token(b'-');
        let month = month();
                    token(b'-');
        let day =   day();
        ret (year, month, day)
    }
}

fn quoted_symbol(i: Input<u8>) -> U8Result<&str> {
    parse!{i;
        token(b'\"');
        let symbol = take_while1(is_quoted_symbol_char);
        token(b'\"');
        ret str::from_utf8(symbol).unwrap()
    }
}

fn unquoted_symbol(i: Input<u8>) -> U8Result<&str> {
    take_while1(i, is_unquoted_symbol_char).map(|b| str::from_utf8(b).unwrap())
}

fn symbol(i: Input<u8>) -> U8Result<&str> {
    or(i, quoted_symbol, unquoted_symbol)
}

fn quantity(i: Input<u8>) -> U8Result<String> {
    parse!{i;
        let sign = option(|i| token(i, b'-'), b'+');
        let number = take_while1(is_quantity_char);
        ret make_quantity(sign, number)
    }
}

fn amount_symbol_then_quantity(i: Input<u8>) -> U8Result<(String, &str)> {
    parse!{i;
        let symbol = symbol();
        whitespace();
        let quantity = quantity();
        ret (quantity, symbol)
    }
}

fn amount_quantity_then_symbol(i: Input<u8>) -> U8Result<(String, &str)> {
    parse!{i;
        let quantity = quantity();
        whitespace();
        let symbol = symbol();
        ret (quantity, symbol)
    }
}

fn amount(i: Input<u8>) -> U8Result<(String, &str)> {
    or(i, amount_symbol_then_quantity, amount_quantity_then_symbol)
}

fn price(i: Input<u8>) -> U8Result<((i32, i32, i32), &str, (String, &str))> {
    parse!{i;
        token(b'P');
        mandatory_whitespace();
        let date = date();
        mandatory_whitespace();
        let symbol = symbol();
        mandatory_whitespace();
        let amount = amount();
        ret (date, symbol, amount)
    }
}

fn price_line(i: Input<u8>) -> U8Result<((i32, i32, i32), &str, (String, &str))> {
    parse!{i;
        let price = price();
        line_ending();
        ret price
    }
}

// MAIN

fn main() {
    // println!("{:?}", parse_only(mandatory_whitespace, b" "));
    // println!("{:?}", parse_only(date, b"2016-02-06"));
    // println!("{:?}", parse_only(symbol, b"\"AIM1651\""));
    // println!("{:?}", parse_only(symbol, b"$"));
    // println!("{:?}", parse_only(amount, b"$-5.82"));
    // println!("{:?}", parse_only(price, b"P 2016-02-06 \"AIM1651\" $5.82"));
    // println!("{:?}", parse_only(price_db, b"P 2016-02-06 \"AIM1651\" $5.82\r\nP 2016-02-07 \"AIM1651\" $5.85"));

    let price_db_filepath = "/Users/mark/Nexus/Documents/finances/ledger/.pricedb";
    let file = File::open(price_db_filepath).ok().expect("Failed to open file");

    let mut source = Source::new(file);
    let mut n = 0;

    loop {
        match source.parse(price_line) {
            Ok(_)                        => n += 1,
            Err(StreamError::Retry)      => {}, // Needed to refill buffer when necessary
            Err(StreamError::EndOfInput) => break,
            Err(e)                       => { panic!("{:?}", e); }
        }
    }

    println!("Parsed {} prices", n);

    // match source.parse(price_db) {
    //     Ok(prices)  => println!("Parsed {} prices", prices.len()),
    //     Err(e)      => println!("Uhm, wat? {:?}", e)
    // }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate regex;
use regex::Regex;

use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Comma,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
	Abs,
    Sqrt,
    Ln,
    Log,
    Sin,
    Csc,
    Cos,
    Sec,
    Tan,
    Cot,
    Asin,
    Acsc,
    Acos,
    Asec,
    Atan,
    Acot,
    Sinh,
    Csch,
    Cosh,
    Sech,
    Tanh,
    Coth,
    Asinh,
    Acsch,
    Acosh,
    Asech,
    Atanh,
    Acoth,
    Max,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Operator {
    Add=0,
    Sub=1,
    Div=2,
    Mul=3,
    Pow=4, // Right
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
}

struct ExpressionIter<'a> {
	expr: &'a Expression,
	count: usize,
}

impl<'a> Iterator for ExpressionIter<'a> {
	type Item = &'a Token;
    fn next(&mut self) -> Option<&'a Token> {
    	let token = self.expr.get_tokens().get(self.count);
    	self.count += 1;
    	token
    }
}

impl Expression {
	fn new(tokens: Vec<Token>) -> Self {
		Expression {tokens: tokens}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn get_token(&self, index: usize) -> &Token {
		self.tokens.get(index).unwrap()
	}

	fn get_mut_token(&mut self, index: usize) -> &mut Token {
		self.tokens.get_mut(index).unwrap()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

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

	fn iter(&self) -> ExpressionIter {
		ExpressionIter {expr: &self, count: 0}
	}
}

fn main() {
	let numeric_regex: Regex = Regex::new(r"\d+\.\d+|\d+").unwrap();
	let function_regex: Regex = Regex::new(r"\w{2,}").unwrap();
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
        	println!("There was a problem reading stdin: {:?}", x);
        	print!("Exiting...");;
        	break;
        }
        input = strip_white_space(&input).to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = parse_input(&input, &numeric_regex, &function_regex);
        if expr.is_ok() {
        	println!("{:?}", &expr.unwrap());
        } else {
        	println!("Encountered an error while parsing: {:?}", expr.unwrap_err());
        	println!("Try Again...(type 'quit' to exit)");
        	continue;
        }
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String, numeric_regex: &Regex, function_regex: &Regex) -> Result<Expression, String> {
	// 1. Replace everthing except letters/numbers with their enums
	// 2. Then go through and replace things with Literals or functions
	let mut expr: Expression = Expression::new(Vec::new());
	let mut builder: String = String::new();
	for c in input.chars() {
		match c {
		    '(' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Open);
		    },
		    ')' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Close);
		    },
		    '+' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Add));
		    },
		    '-' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Sub));
		    },
		    '*' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Mul));
		    },
		    '/' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Div));
		    },
		    '^' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Pow));
		    },
		    ',' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Comma);
		    },
		    _ => {
		    	builder.push(c);
		    }
		}
	}
	if builder.len() > 0 {
		if numeric_regex.is_match(&builder[..]) {
			expr.push(Token::Literal(builder.clone()));
		} else if function_regex.is_match(&builder[..]) {
			expr.push(map_string_to_func(&builder));
		}
		builder = String::new();
	}
	let mut op_stack: Vec<Token> = Vec::with_capacity(input.len());
	let mut out_queue: Vec<Token> = Vec::with_capacity(input.len());
	//println!("EXPR {:?}", &expr);
	for i in 0..expr.len() {
		let current_token = expr.get_token(i);
		//println!("BEFORE current_token: {:?}, OPSTACK {:?}, out_queue {:?}", &current_token, &op_stack, &out_queue);
		match current_token {
		    &Token::Literal(ref x) => out_queue.push(Token::Literal(x.clone())),
		    &Token::Func(ref x) => op_stack.push(Token::Func(x.clone())),
		    &Token::Comma => {
		    	let mut found_open = false;
		    	loop {
			    	let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
			    	match stack_token {
			    	    Token::Open => {op_stack.push(stack_token); found_open=true; break;},
			    	    _ => out_queue.push(stack_token),
			    	}
		    	}
		    	if !found_open {return Err(String::from("Mismatch Parenthesis"))}
			},
		    &Token::Op(ref o1) =>  {
		    	loop {
			    	if op_stack.len() < 1 {
						break;
					}
			    	let o2 = try!{op_stack.pop().ok_or("Malformed Expression")}; // top of stack
			    	match o1 {
			    	    &Operator::Pow => match o2 {
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Mul | &Operator::Div => match o2 {
			    	    	Token::Op(Operator::Pow) | Token::Op(Operator::Mul) | Token::Op(Operator::Div) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Add | &Operator::Sub => match o2 {
			    	    	Token::Op(Operator::Add) | Token::Op(Operator::Sub) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    }
			    	}
		    	};
		    	op_stack.push(Token::Op(o1.clone()));
			},
			&Token::Open => op_stack.push(Token::Open),
			&Token::Close => {
				let mut found_open = false;
				loop {
					let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
					match stack_token {
						Token::Open => {op_stack.push(stack_token); found_open=true; break;},
						_ => out_queue.push(stack_token),
					}
				};
				if !found_open {return Err(String::from("Mismatch Parenthesis"))}
				let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				let next_stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				match next_stack_token {
					Token::Func(ref x) => out_queue.push(Token::Func(x.clone())),
					_ => op_stack.push(next_stack_token),
				}
			},
			&Token::Unknown(ref x) => {
				let mut message: String = "You either misspelled a function, or it is not yet implemented. The unknown string was: ".to_owned();
				message.push_str(x);
				return Err(message);
			},
		    _ => break,
		}
		//println!("AFTER current_token: {:?}, OPSTACK {:?}, out_queue {:?}\n\n\n", &current_token, &op_stack, &out_queue);
	}
	//println!("OPSTACK {:?}", &op_stack);
	while op_stack.len() > 0 {
	    out_queue.push(try!{op_stack.pop().ok_or("Malformed Expression")});
	}
	Ok(Expression::new(out_queue))
}

fn map_string_to_func(input: &String) -> Token {
	match &(input.to_lowercase())[..] {
		"abs" => Token::Func(Function::Abs),
	    "sqrt" => Token::Func(Function::Sqrt),
	    "ln" => Token::Func(Function::Ln),
	    "log" => Token::Func(Function::Log),
	    "sin" => Token::Func(Function::Sin),
	    "csc" => Token::Func(Function::Csc),
	    "cos" => Token::Func(Function::Cos),
	    "sec" => Token::Func(Function::Sec),
	    "tan" => Token::Func(Function::Tan),
	    "cot" => Token::Func(Function::Cot),
	    "asin" => Token::Func(Function::Asin),
	    "acsc" => Token::Func(Function::Acsc),
	    "acos" => Token::Func(Function::Acos),
	    "asec" => Token::Func(Function::Asec),
	    "atan" => Token::Func(Function::Atan),
	    "acot" => Token::Func(Function::Acot),
	    "sinh" => Token::Func(Function::Sinh),
	    "csch" => Token::Func(Function::Csch),
	    "cosh" => Token::Func(Function::Cosh),
	    "sech" => Token::Func(Function::Sech),
	    "tanh" => Token::Func(Function::Tanh),
	    "coth" => Token::Func(Function::Coth),
	    "asinh" => Token::Func(Function::Asinh),
	    "acsch" => Token::Func(Function::Acsch),
	    "acosh" => Token::Func(Function::Acosh),
	    "asech" => Token::Func(Function::Asech),
	    "atanh" => Token::Func(Function::Atanh),
	    "acoth" => Token::Func(Function::Acoth),
	    "max" => Token::Func(Function::Max),
	    _ => Token::Unknown(input.clone()),
	}
}
<commit_msg>Removed Trailing Space<commit_after>#![allow(dead_code)]

extern crate regex;
use regex::Regex;

use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Comma,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
	Abs,
    Sqrt,
    Ln,
    Log,
    Sin,
    Csc,
    Cos,
    Sec,
    Tan,
    Cot,
    Asin,
    Acsc,
    Acos,
    Asec,
    Atan,
    Acot,
    Sinh,
    Csch,
    Cosh,
    Sech,
    Tanh,
    Coth,
    Asinh,
    Acsch,
    Acosh,
    Asech,
    Atanh,
    Acoth,
    Max,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Operator {
    Add=0,
    Sub=1,
    Div=2,
    Mul=3,
    Pow=4, // Right
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
}

struct ExpressionIter<'a> {
	expr: &'a Expression,
	count: usize,
}

impl<'a> Iterator for ExpressionIter<'a> {
	type Item = &'a Token;
    fn next(&mut self) -> Option<&'a Token> {
    	let token = self.expr.get_tokens().get(self.count);
    	self.count += 1;
    	token
    }
}

impl Expression {
	fn new(tokens: Vec<Token>) -> Self {
		Expression {tokens: tokens}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn get_token(&self, index: usize) -> &Token {
		self.tokens.get(index).unwrap()
	}

	fn get_mut_token(&mut self, index: usize) -> &mut Token {
		self.tokens.get_mut(index).unwrap()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

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

	fn iter(&self) -> ExpressionIter {
		ExpressionIter {expr: &self, count: 0}
	}
}

fn main() {
	let numeric_regex: Regex = Regex::new(r"\d+\.\d+|\d+").unwrap();
	let function_regex: Regex = Regex::new(r"\w{2,}").unwrap();
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
        	println!("There was a problem reading stdin: {:?}", x);
        	print!("Exiting...");;
        	break;
        }
        input = strip_white_space(&input).to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = parse_input(&input, &numeric_regex, &function_regex);
        if expr.is_ok() {
        	println!("{:?}", &expr.unwrap());
        } else {
        	println!("Encountered an error while parsing: {:?}", expr.unwrap_err());
        	println!("Try Again...(type 'quit' to exit)");
        	continue;
        }
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String, numeric_regex: &Regex, function_regex: &Regex) -> Result<Expression, String> {
	// 1. Replace everthing except letters/numbers with their enums
	// 2. Then go through and replace things with Literals or functions
	let mut expr: Expression = Expression::new(Vec::new());
	let mut builder: String = String::new();
	for c in input.chars() {
		match c {
		    '(' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Open);
		    },
		    ')' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Close);
		    },
		    '+' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Add));
		    },
		    '-' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Sub));
		    },
		    '*' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Mul));
		    },
		    '/' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Div));
		    },
		    '^' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Op(Operator::Pow));
		    },
		    ',' => {
		    	if builder.len() > 0 {
		    		if numeric_regex.is_match(&builder[..]) {
		    			expr.push(Token::Literal(builder.clone()));
		    		} else if function_regex.is_match(&builder[..]) {
		    			expr.push(map_string_to_func(&builder));
		    		}
		    		builder = String::new();
		    	}
		    	expr.push(Token::Comma);
		    },
		    _ => {
		    	builder.push(c);
		    }
		}
	}
	if builder.len() > 0 {
		if numeric_regex.is_match(&builder[..]) {
			expr.push(Token::Literal(builder.clone()));
		} else if function_regex.is_match(&builder[..]) {
			expr.push(map_string_to_func(&builder));
		}
		builder = String::new();
	}
	let mut op_stack: Vec<Token> = Vec::with_capacity(input.len());
	let mut out_queue: Vec<Token> = Vec::with_capacity(input.len());
	//println!("EXPR {:?}", &expr);
	for i in 0..expr.len() {
		let current_token = expr.get_token(i);
		//println!("BEFORE current_token: {:?}, OPSTACK {:?}, out_queue {:?}", &current_token, &op_stack, &out_queue);
		match current_token {
		    &Token::Literal(ref x) => out_queue.push(Token::Literal(x.clone())),
		    &Token::Func(ref x) => op_stack.push(Token::Func(x.clone())),
		    &Token::Comma => {
		    	let mut found_open = false;
		    	loop {
			    	let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
			    	match stack_token {
			    	    Token::Open => {op_stack.push(stack_token); found_open=true; break;},
			    	    _ => out_queue.push(stack_token),
			    	}
		    	}
		    	if !found_open {return Err(String::from("Mismatch Parenthesis"))}
			},
		    &Token::Op(ref o1) =>  {
		    	loop {
			    	if op_stack.len() < 1 {
						break;
					}
			    	let o2 = try!{op_stack.pop().ok_or("Malformed Expression")}; // top of stack
			    	match o1 {
			    	    &Operator::Pow => match o2 {
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Mul | &Operator::Div => match o2 {
			    	    	Token::Op(Operator::Pow) | Token::Op(Operator::Mul) | Token::Op(Operator::Div) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    },
			    	    &Operator::Add | &Operator::Sub => match o2 {
			    	    	Token::Op(Operator::Add) | Token::Op(Operator::Sub) => out_queue.push(o2),
			    	    	_ => { op_stack.push(o2); break; },
			    	    }
			    	}
		    	};
		    	op_stack.push(Token::Op(o1.clone()));
			},
			&Token::Open => op_stack.push(Token::Open),
			&Token::Close => {
				let mut found_open = false;
				loop {
					let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
					match stack_token {
						Token::Open => {op_stack.push(stack_token); found_open=true; break;},
						_ => out_queue.push(stack_token),
					}
				};
				if !found_open {return Err(String::from("Mismatch Parenthesis"))}
				let stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				let next_stack_token = try!{op_stack.pop().ok_or("Malformed Expression")};
				match next_stack_token {
					Token::Func(ref x) => out_queue.push(Token::Func(x.clone())),
					_ => op_stack.push(next_stack_token),
				}
			},
			&Token::Unknown(ref x) => {
				let mut message: String = "You either misspelled a function, or it is not yet implemented. The unknown string was: ".to_owned();
				message.push_str(x);
				return Err(message);
			},
		    _ => break,
		}
		//println!("AFTER current_token: {:?}, OPSTACK {:?}, out_queue {:?}\n\n\n", &current_token, &op_stack, &out_queue);
	}
	//println!("OPSTACK {:?}", &op_stack);
	while op_stack.len() > 0 {
	    out_queue.push(try!{op_stack.pop().ok_or("Malformed Expression")});
	}
	Ok(Expression::new(out_queue))
}

fn map_string_to_func(input: &String) -> Token {
	match &(input.to_lowercase())[..] {
		"abs" => Token::Func(Function::Abs),
	    "sqrt" => Token::Func(Function::Sqrt),
	    "ln" => Token::Func(Function::Ln),
	    "log" => Token::Func(Function::Log),
	    "sin" => Token::Func(Function::Sin),
	    "csc" => Token::Func(Function::Csc),
	    "cos" => Token::Func(Function::Cos),
	    "sec" => Token::Func(Function::Sec),
	    "tan" => Token::Func(Function::Tan),
	    "cot" => Token::Func(Function::Cot),
	    "asin" => Token::Func(Function::Asin),
	    "acsc" => Token::Func(Function::Acsc),
	    "acos" => Token::Func(Function::Acos),
	    "asec" => Token::Func(Function::Asec),
	    "atan" => Token::Func(Function::Atan),
	    "acot" => Token::Func(Function::Acot),
	    "sinh" => Token::Func(Function::Sinh),
	    "csch" => Token::Func(Function::Csch),
	    "cosh" => Token::Func(Function::Cosh),
	    "sech" => Token::Func(Function::Sech),
	    "tanh" => Token::Func(Function::Tanh),
	    "coth" => Token::Func(Function::Coth),
	    "asinh" => Token::Func(Function::Asinh),
	    "acsch" => Token::Func(Function::Acsch),
	    "acosh" => Token::Func(Function::Acosh),
	    "asech" => Token::Func(Function::Asech),
	    "atanh" => Token::Func(Function::Atanh),
	    "acoth" => Token::Func(Function::Acoth),
	    "max" => Token::Func(Function::Max),
	    _ => Token::Unknown(input.clone()),
	}
}
<|endoftext|>


<commit_before>extern crate glob;
#[macro_use]
extern crate lazy_static;
extern crate log;
#[macro_use]
extern crate serde;
extern crate serde_json;
extern crate structopt;
extern crate syslog;
extern crate toml;

mod applog;
mod connection;
mod error;
mod message;
mod statics;
mod structs;

use log::debug;
use message::*;
use std::env;
use std::process;
use structopt::StructOpt;
use structs::Config;

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum Command {
    /// Gets user public key
    Key {
        #[structopt(parse(from_str))]
        user: String,
    },
    /// Executes pam check
    Pam,
    /// Check configuration
    Check {
        #[structopt(parse(from_os_str))]
        confpath: std::path::PathBuf,
    },
    /// Cleans caches up
    #[structopt(alias = "cleanup")]
    CleanUp,
    /// Get rate limit for github api
    #[structopt(alias = "ratelimit")]
    RateLimit,
    /// Displays version details
    Version,
    /// Displays completion
    Completion {
        #[structopt(subcommand)]
        shell: Shell,
    },
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum Shell {
    Bash,
    Fish,
    Zsh,
    PowerShell,
    Elvish,
}

fn main() {
    let command = Command::from_args();
    let conn = connection::Connection::new(&format!("{:?}", command)).unwrap_or_else(|_| process::exit(11));
    debug!("connected to socket: {:?}", conn);

    match command {
        Command::Check { confpath } => match Config::from_path(&confpath) {
            Ok(_) => process::exit(0),
            Err(_) => process::exit(11),
        },
        Command::Key { user } => match conn.communicate(ClientMessage::Key { user }) {
            Ok(DaemonMessage::Key { keys }) => {
                println!("{}", keys);
                process::exit(0)
            }
            _ => process::exit(21),
        },
        Command::Pam => match env::var("PAM_USER") {
            Ok(user) => match conn.communicate(ClientMessage::Pam { user }) {
                Ok(DaemonMessage::Pam { result }) => process::exit(if result { 0 } else { 1 }),
                _ => process::exit(31),
            },
            Err(_) => process::exit(41),
        },
        Command::CleanUp => match conn.communicate(ClientMessage::CleanUp) {
            Ok(_) => process::exit(0),
            Err(_) => process::exit(51),
        },
        Command::RateLimit => match conn.communicate(ClientMessage::RateLimit) {
            Ok(DaemonMessage::RateLimit { limit }) => {
                println!("{:?}", limit);
                process::exit(0)
            }
            _ => process::exit(61),
        },
        Command::Version => {
            println!("{}",
                     concat!(env!("CARGO_PKG_VERSION"),
                             include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))));
        }
        Command::Completion { shell } => {
            let shell = match shell {
                Shell::Bash => structopt::clap::Shell::Bash,
                Shell::Fish => structopt::clap::Shell::Fish,
                Shell::Zsh => structopt::clap::Shell::Zsh,
                Shell::PowerShell => structopt::clap::Shell::PowerShell,
                Shell::Elvish => structopt::clap::Shell::Elvish,
            };
            Command::clap().gen_completions_to("sectora", shell, &mut std::io::stdout());
        }
    };
}
<commit_msg>Use the return to properly drop the connection<commit_after>extern crate glob;
#[macro_use]
extern crate lazy_static;
extern crate log;
#[macro_use]
extern crate serde;
extern crate serde_json;
extern crate structopt;
extern crate syslog;
extern crate toml;

mod applog;
mod connection;
mod error;
mod message;
mod statics;
mod structs;

use log::debug;
use message::*;
use std::env;
use std::io::{Error, ErrorKind};
use std::process;
use structopt::StructOpt;
use structs::Config;

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum Command {
    /// Gets user public key
    Key {
        #[structopt(parse(from_str))]
        user: String,
    },
    /// Executes pam check
    Pam,
    /// Check configuration
    Check {
        #[structopt(parse(from_os_str))]
        confpath: std::path::PathBuf,
    },
    /// Cleans caches up
    #[structopt(alias = "cleanup")]
    CleanUp,
    /// Get rate limit for github api
    #[structopt(alias = "ratelimit")]
    RateLimit,
    /// Displays version details
    Version,
    /// Displays completion
    Completion {
        #[structopt(subcommand)]
        shell: Shell,
    },
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum Shell {
    Bash,
    Fish,
    Zsh,
    PowerShell,
    Elvish,
}

fn main() -> Result<(), Error> {
    let command = Command::from_args();
    let conn = connection::Connection::new(&format!("{:?}", command)).unwrap_or_else(|_| process::exit(11));
    debug!("connected to socket: {:?}", conn);

    match command {
        Command::Check { confpath } => match Config::from_path(&confpath) {
            Ok(_) => return Ok(()),
            Err(_) => return Err(Error::new(ErrorKind::Other, "check failed")),
        },
        Command::Key { user } => match conn.communicate(ClientMessage::Key { user }) {
            Ok(DaemonMessage::Key { keys }) => {
                println!("{}", keys);
                return Ok(());
            }
            _ => return Err(Error::new(ErrorKind::PermissionDenied, "key check failed")),
        },
        Command::Pam => match env::var("PAM_USER") {
            Ok(user) => match conn.communicate(ClientMessage::Pam { user }) {
                Ok(DaemonMessage::Pam { result }) => {
                    if result {
                        return Ok(());
                    } else {
                        return Err(Error::new(ErrorKind::NotFound, "user not found"));
                    }
                }
                _ => return Err(Error::new(ErrorKind::Other, "faild")),
            },
            Err(_) => return Err(Error::new(ErrorKind::ConnectionRefused, "failed")),
        },
        Command::CleanUp => match conn.communicate(ClientMessage::CleanUp) {
            Ok(_) => return Ok(()),
            Err(_) => return Err(Error::new(ErrorKind::Other, "failed")),
        },
        Command::RateLimit => match conn.communicate(ClientMessage::RateLimit) {
            Ok(DaemonMessage::RateLimit { limit }) => {
                println!("{:?}", limit);
            }
            _ => return Err(Error::new(ErrorKind::Other, "failed")),
        },
        Command::Version => {
            println!("{}",
                     concat!(env!("CARGO_PKG_VERSION"),
                             include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))));
        }
        Command::Completion { shell } => {
            let shell = match shell {
                Shell::Bash => structopt::clap::Shell::Bash,
                Shell::Fish => structopt::clap::Shell::Fish,
                Shell::Zsh => structopt::clap::Shell::Zsh,
                Shell::PowerShell => structopt::clap::Shell::PowerShell,
                Shell::Elvish => structopt::clap::Shell::Elvish,
            };
            Command::clap().gen_completions_to("sectora", shell, &mut std::io::stdout());
        }
    };
    return Ok(());
}
<|endoftext|>


<commit_before>// Copyright (C) 2016, 2017 Mark Lee

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate env_logger;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate redis;
extern crate regex;
extern crate reqwest;
extern crate rquery;
extern crate semver;
extern crate serde;
extern crate serde_json;

use hyper::{Get, StatusCode};
use hyper::header::{Accept, ContentType};
use hyper::server::{Http, Request, Response, Service};
use redis::{Commands, RedisError, RedisResult};
use regex::Regex;
use rquery::Document;
use semver::Version;
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;

const DEFAULT_SERVER_PORT: u32 = 9000;
const DEFAULT_MIN_BUNDLER_VERSION: &str = "1.12.0";
const RUBY_LANGPACK_RELEASES_URL: &str =
    "https://github.com/heroku/heroku-buildpack-ruby/releases.atom";

fn download_url(url: &str) -> io::Result<String> {
    let mut resp = reqwest::get(url).expect("Could not send HTTP request");
    let mut body = String::new();
    match resp.read_to_string(&mut body) {
        Err(error) => Err(error),
        _ => Ok(body),
    }
}

fn download_latest_buildpack_release() -> String {
    let xml = download_url(RUBY_LANGPACK_RELEASES_URL).expect("Could not download Atom releases!");
    let atom_doc = Document::new_from_xml_string(&xml[..]).expect("Could not parse Atom releases!");
    atom_doc
        .select("entry id")
        .expect("Could not find latest buildpack tag!")
        .text()
        .rsplitn(2, '/')
        .next()
        .expect("No slashes in the GitHub release ID!")
        .to_string()
}

fn redis_cache_value(redis: &redis::Connection, key: &str, value: &str) -> String {
    let set_result: RedisResult<()> = redis.set_ex(key, value, 3600);
    if set_result.is_err() {
        warn!("Cannot set {} in Redis, ignoring", key);
    }
    value.to_owned()
}

fn redis_cache_hash_value(redis: &redis::Connection, hash_name: &str, key: &str, value: &str) {
    let set_result: RedisResult<()> = redis.hset_nx(hash_name, key, value);
    if set_result.is_err() {
        warn!("Cannot set {} in Redis, ignoring", key);
    }
}

fn latest_buildpack_release(redis_result: &RedisResult<redis::Connection>) -> String {
    if let Ok(ref redis) = *redis_result {
        if let Ok(buildpack_release) = redis.get("latest_buildpack_release") {
            buildpack_release
        } else {
            let buildpack_release = download_latest_buildpack_release();
            redis_cache_value(redis, "latest_buildpack_release", &buildpack_release[..])
        }
    } else {
        download_latest_buildpack_release()
    }
}

fn cached_version_from_buildpack_release(
    buildpack_release: &str,
    redis_result: &RedisResult<redis::Connection>,
) -> Option<String> {
    if let Ok(ref redis) = *redis_result {
        if let Ok(version) = redis.hget("bundler_version", buildpack_release) {
            Some(version)
        } else {
            None
        }
    } else {
        None
    }
}

fn bundler_version_from_ruby_buildpack(
    redis_result: &RedisResult<redis::Connection>,
) -> Option<String> {
    let buildpack_release = latest_buildpack_release(redis_result);
    if let Some(cached_version) =
        cached_version_from_buildpack_release(&buildpack_release[..], redis_result)
    {
        return Some(cached_version);
    }
    let ruby_langpack_url = format!(
        "https://raw.githubusercontent.com/\
         heroku/heroku-buildpack-ruby/{}/lib/language_pack/\
         ruby.rb",
        buildpack_release
    );
    let ruby_file = &download_url(&ruby_langpack_url[..]).expect("Could not download ruby.rb!")[..];
    let regex = Regex::new(r#"BUNDLER_VERSION += "(.+?)""#).expect("Invalid regular expression!");
    if regex.is_match(ruby_file) {
        let captures = regex.captures(ruby_file).expect("Could not match?!");
        let version_match = captures.get(1).expect("Capture not found?!");
        let version = version_match.as_str();
        if let Ok(ref redis) = *redis_result {
            redis_cache_hash_value(redis, "bundler_version", &buildpack_release[..], version);
        }
        Some(version.to_owned())
    } else {
        None
    }
}

fn is_bundler_upgraded(redis_result: &RedisResult<redis::Connection>) -> bool {
    let bundler_version_result = bundler_version_from_ruby_buildpack(redis_result);
    if let Some(buildpack_bundler_version_str) = bundler_version_result {
        let min_version =
            Version::parse(&min_bundler_version()[..]).expect("Could not parse min version!");
        let new_version = Version::parse(&buildpack_bundler_version_str[..])
            .expect("Could not parse new version!");
        min_version < new_version
    } else {
        false
    }
}

fn determine_content_type(headers: &hyper::Headers) -> ContentType {
    use std::ops::Deref;
    if headers.has::<Accept>() {
        let accept = headers
            .get::<Accept>()
            .expect("Accept header not found?!")
            .deref();
        let use_json = accept
            .into_iter()
            .any(|qitem| qitem.item == "application/json");

        if use_json {
            ContentType::json()
        } else {
            ContentType::html()
        }
    } else {
        ContentType::html()
    }
}

fn result_to_json(result: bool) -> String {
    let mut map = HashMap::new();
    map.insert("result".to_owned(), result);
    serde_json::to_string(&map).expect("Could not serialize result!")
}

fn result_to_html(result: bool) -> String {
    let result_str = if result {
        r#"
Yes
"#
    } else {
        r#"
No
"#
    };
    match File::open("index.html") {
        Ok(mut html_file) => {
            let mut html = String::new();
            html_file
                .read_to_string(&mut html)
                .expect("Could not read HTML file!");
            html.replace("{{ is_bundler_upgraded }}", result_str)
                .replace("{{ MIN_BUNDLER_VERSION }}", &min_bundler_version()[..])
        }
        Err(error) => format!("HTML NOT FOUND: {}", error),
    }
}

fn min_bundler_version() -> String {
    match env::var("MIN_BUNDLER_VERSION") {
        Ok(version) => version,
        _ => String::from(DEFAULT_MIN_BUNDLER_VERSION),
    }
}

fn server_port() -> String {
    match env::var("PORT") {
        Ok(port) => port,
        _ => format!("{}", DEFAULT_SERVER_PORT),
    }
}

fn connect_to_redis() -> RedisResult<redis::Connection> {
    if let Ok(redis_url) = env::var("REDIS_URL") {
        let client = redis::Client::open(&redis_url[..]).expect("Cannot connect to Redis");
        client.get_connection()
    } else {
        Err(RedisError::from(io::Error::new(
            io::ErrorKind::Other,
            "REDIS_URL not found",
        )))
    }
}

struct HBBUYServer;

impl Service for HBBUYServer {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = futures::future::FutureResult<Self::Response, Self::Error>;

    fn call(&self, req: Request) -> Self::Future {
        let response = match (req.uri().path(), req.method()) {
            ("/", &Get) => {
                let redis = connect_to_redis();
                let result = is_bundler_upgraded(&redis);
                let content_type = determine_content_type(req.headers());
                let data = match &format!("{}", content_type)[..] {
                    "application/json" => result_to_json(result),
                    _ => result_to_html(result),
                };

                Response::new().with_header(content_type).with_body(data)
            }
            (_, &Get) => Response::new().with_status(StatusCode::NotFound),
            (_, _) => Response::new().with_status(StatusCode::MethodNotAllowed),
        };

        futures::future::ok(response)
    }
}

fn main() {
    env_logger::try_init().expect("Could not initialize env_logger!");
    let addr = format!("0.0.0.0:{}", server_port())
        .parse()
        .expect("Could not parse address/port");
    let server = Http::new()
        .bind(&addr, || Ok(HBBUYServer))
        .expect("Could not create server!");
    server
        .run()
        .expect("Could not set up HTTP request handler!");
}
<commit_msg>Rustfmt<commit_after>// Copyright (C) 2016, 2017 Mark Lee

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate env_logger;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate redis;
extern crate regex;
extern crate reqwest;
extern crate rquery;
extern crate semver;
extern crate serde;
extern crate serde_json;

use hyper::header::{Accept, ContentType};
use hyper::server::{Http, Request, Response, Service};
use hyper::{Get, StatusCode};
use redis::{Commands, RedisError, RedisResult};
use regex::Regex;
use rquery::Document;
use semver::Version;
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;

const DEFAULT_SERVER_PORT: u32 = 9000;
const DEFAULT_MIN_BUNDLER_VERSION: &str = "1.12.0";
const RUBY_LANGPACK_RELEASES_URL: &str =
    "https://github.com/heroku/heroku-buildpack-ruby/releases.atom";

fn download_url(url: &str) -> io::Result<String> {
    let mut resp = reqwest::get(url).expect("Could not send HTTP request");
    let mut body = String::new();
    match resp.read_to_string(&mut body) {
        Err(error) => Err(error),
        _ => Ok(body),
    }
}

fn download_latest_buildpack_release() -> String {
    let xml = download_url(RUBY_LANGPACK_RELEASES_URL).expect("Could not download Atom releases!");
    let atom_doc = Document::new_from_xml_string(&xml[..]).expect("Could not parse Atom releases!");
    atom_doc
        .select("entry id")
        .expect("Could not find latest buildpack tag!")
        .text()
        .rsplitn(2, '/')
        .next()
        .expect("No slashes in the GitHub release ID!")
        .to_string()
}

fn redis_cache_value(redis: &redis::Connection, key: &str, value: &str) -> String {
    let set_result: RedisResult<()> = redis.set_ex(key, value, 3600);
    if set_result.is_err() {
        warn!("Cannot set {} in Redis, ignoring", key);
    }
    value.to_owned()
}

fn redis_cache_hash_value(redis: &redis::Connection, hash_name: &str, key: &str, value: &str) {
    let set_result: RedisResult<()> = redis.hset_nx(hash_name, key, value);
    if set_result.is_err() {
        warn!("Cannot set {} in Redis, ignoring", key);
    }
}

fn latest_buildpack_release(redis_result: &RedisResult<redis::Connection>) -> String {
    if let Ok(ref redis) = *redis_result {
        if let Ok(buildpack_release) = redis.get("latest_buildpack_release") {
            buildpack_release
        } else {
            let buildpack_release = download_latest_buildpack_release();
            redis_cache_value(redis, "latest_buildpack_release", &buildpack_release[..])
        }
    } else {
        download_latest_buildpack_release()
    }
}

fn cached_version_from_buildpack_release(
    buildpack_release: &str,
    redis_result: &RedisResult<redis::Connection>,
) -> Option<String> {
    if let Ok(ref redis) = *redis_result {
        if let Ok(version) = redis.hget("bundler_version", buildpack_release) {
            Some(version)
        } else {
            None
        }
    } else {
        None
    }
}

fn bundler_version_from_ruby_buildpack(
    redis_result: &RedisResult<redis::Connection>,
) -> Option<String> {
    let buildpack_release = latest_buildpack_release(redis_result);
    if let Some(cached_version) =
        cached_version_from_buildpack_release(&buildpack_release[..], redis_result)
    {
        return Some(cached_version);
    }
    let ruby_langpack_url = format!(
        "https://raw.githubusercontent.com/\
         heroku/heroku-buildpack-ruby/{}/lib/language_pack/\
         ruby.rb",
        buildpack_release
    );
    let ruby_file = &download_url(&ruby_langpack_url[..]).expect("Could not download ruby.rb!")[..];
    let regex = Regex::new(r#"BUNDLER_VERSION += "(.+?)""#).expect("Invalid regular expression!");
    if regex.is_match(ruby_file) {
        let captures = regex.captures(ruby_file).expect("Could not match?!");
        let version_match = captures.get(1).expect("Capture not found?!");
        let version = version_match.as_str();
        if let Ok(ref redis) = *redis_result {
            redis_cache_hash_value(redis, "bundler_version", &buildpack_release[..], version);
        }
        Some(version.to_owned())
    } else {
        None
    }
}

fn is_bundler_upgraded(redis_result: &RedisResult<redis::Connection>) -> bool {
    let bundler_version_result = bundler_version_from_ruby_buildpack(redis_result);
    if let Some(buildpack_bundler_version_str) = bundler_version_result {
        let min_version =
            Version::parse(&min_bundler_version()[..]).expect("Could not parse min version!");
        let new_version = Version::parse(&buildpack_bundler_version_str[..])
            .expect("Could not parse new version!");
        min_version < new_version
    } else {
        false
    }
}

fn determine_content_type(headers: &hyper::Headers) -> ContentType {
    use std::ops::Deref;
    if headers.has::<Accept>() {
        let accept = headers
            .get::<Accept>()
            .expect("Accept header not found?!")
            .deref();
        let use_json = accept
            .into_iter()
            .any(|qitem| qitem.item == "application/json");

        if use_json {
            ContentType::json()
        } else {
            ContentType::html()
        }
    } else {
        ContentType::html()
    }
}

fn result_to_json(result: bool) -> String {
    let mut map = HashMap::new();
    map.insert("result".to_owned(), result);
    serde_json::to_string(&map).expect("Could not serialize result!")
}

fn result_to_html(result: bool) -> String {
    let result_str = if result {
        r#"
Yes
"#
    } else {
        r#"
No
"#
    };
    match File::open("index.html") {
        Ok(mut html_file) => {
            let mut html = String::new();
            html_file
                .read_to_string(&mut html)
                .expect("Could not read HTML file!");
            html.replace("{{ is_bundler_upgraded }}", result_str)
                .replace("{{ MIN_BUNDLER_VERSION }}", &min_bundler_version()[..])
        }
        Err(error) => format!("HTML NOT FOUND: {}", error),
    }
}

fn min_bundler_version() -> String {
    match env::var("MIN_BUNDLER_VERSION") {
        Ok(version) => version,
        _ => String::from(DEFAULT_MIN_BUNDLER_VERSION),
    }
}

fn server_port() -> String {
    match env::var("PORT") {
        Ok(port) => port,
        _ => format!("{}", DEFAULT_SERVER_PORT),
    }
}

fn connect_to_redis() -> RedisResult<redis::Connection> {
    if let Ok(redis_url) = env::var("REDIS_URL") {
        let client = redis::Client::open(&redis_url[..]).expect("Cannot connect to Redis");
        client.get_connection()
    } else {
        Err(RedisError::from(io::Error::new(
            io::ErrorKind::Other,
            "REDIS_URL not found",
        )))
    }
}

struct HBBUYServer;

impl Service for HBBUYServer {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = futures::future::FutureResult<Self::Response, Self::Error>;

    fn call(&self, req: Request) -> Self::Future {
        let response = match (req.uri().path(), req.method()) {
            ("/", &Get) => {
                let redis = connect_to_redis();
                let result = is_bundler_upgraded(&redis);
                let content_type = determine_content_type(req.headers());
                let data = match &format!("{}", content_type)[..] {
                    "application/json" => result_to_json(result),
                    _ => result_to_html(result),
                };

                Response::new().with_header(content_type).with_body(data)
            }
            (_, &Get) => Response::new().with_status(StatusCode::NotFound),
            (_, _) => Response::new().with_status(StatusCode::MethodNotAllowed),
        };

        futures::future::ok(response)
    }
}

fn main() {
    env_logger::try_init().expect("Could not initialize env_logger!");
    let addr = format!("0.0.0.0:{}", server_port())
        .parse()
        .expect("Could not parse address/port");
    let server = Http::new()
        .bind(&addr, || Ok(HBBUYServer))
        .expect("Could not create server!");
    server
        .run()
        .expect("Could not set up HTTP request handler!");
}
<|endoftext|>


<commit_before>/*
  Declare main function
*/
fn main() {

    // Metaprogramming calling a macro and passing staticaly allocated string arg
    println!("Hello, world!");

    // Variable binding
    let x = 5;
}<commit_msg>Added Mutable and Immutable Bindings. Used Macro with Interpolation<commit_after>/*
  Declare main function
*/
fn main() {

    // Metaprogramming calling a macro and passing staticaly allocated string arg
    println!("Hello, world!");

    /*
      Variable binding expression.
      <let expression> is Full Pattern for Pattern Matching.
      Rust's Type Inference automatically determines an expression's Type.
      Alternatively be explicit and supply an expression's Type after a colon.
      Or simply annotate the Type in a comment to understand the Type Rust infers.
      Rust Bindings are immutable by Default.
      Mutable Bindings require 'mut' prefix for Type Safety.
    */
    let a: i32 = 5; // assign immutable binding 'a' with Type i32 and Value 5
    let (x, y, z) = (1, 2, 3);  // assign immutable bindings x, y, z to 1, 2, 3

    let mut b: i32 = 10; // assign mutable binding 'b'
    b = 20; // re-assign to new Value

    println!("The value of b is: {}", b); // Interpret interpolation with moustaches
}<|endoftext|>


<commit_before>extern crate clap;

use clap::{Arg, App, Error};

mod workfile;
mod srt;
mod txt_rep;
mod rules;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

///////////////////////////////////////////////////////////////////////////////
fn do_replacements(subtitles: &mut Vec<srt::Subtitle>, language: &str) {

	for subtitle in subtitles.iter_mut() {
		for text_index in 0..subtitle.text_count as usize {
			subtitle.texts[text_index] = txt_rep::replace_one(&subtitle.texts[text_index], &language);
		}
		//print!("{}", subtitle.to_string());
	}
}

fn do_time_changes(subtitles: &mut Vec<srt::Subtitle>,
                   time_shift_ms: i32, time_stretch_ms: i32) {

	if time_shift_ms == 0 && time_stretch_ms == 0 {
		return;
	}
	let sub_count = subtitles.len();
	if sub_count == 0 {
		return;
	}

	if sub_count > std::i32::MAX as usize {
		eprintln!("Too many subtitles");
		return;
	};

	// Compute the limit for stretching
	let sub_count_i32 = if srt::should_keep_last_sub(subtitles) {
		sub_count as i32
	}
	else {
		println!("last not kept");
		(sub_count - 1) as i32
	};

	let mut sub_index = 0;
	for subtitle in subtitles.iter_mut() {

		subtitle.time_from += time_shift_ms;
		subtitle.time_to += time_shift_ms;

		if time_stretch_ms > 0 && sub_count_i32 > 1 && sub_index < sub_count_i32 {
			let stretching = (sub_index * time_stretch_ms) / (sub_count_i32 - 1);
			subtitle.time_from += stretching;
			subtitle.time_to += stretching;
		}
		sub_index += 1;
	}
}

///////////////////////////////////////////////////////////////////////////////
fn main() {
	srt::parse_srt_time("-00:00:10,000");

	let matches = App::new("fixsrt")
		.version(VERSION)
		.author("Hadrien Nilsson")
		.about("Fix spelling and encoding mistakes in SRT subtitle files")
		.arg(Arg::with_name("nobak")
			.long("nobak")
			.help("Avoids creating a backup file"))
		.arg(Arg::with_name("SRTFILE")
			.required(true)
			.multiple(true)
			.help("SRT file to update"))
		.arg(Arg::with_name("out")
			.short("o")
			.long("out")
			.takes_value(true)
			.help("Outputs to another file (single input only)"))
		.arg(Arg::with_name("shift")
			.long("shift")
			.takes_value(true)
			.help("Shifts all subtitles of several seconds"))
		.arg(Arg::with_name("stretch")
			.long("stretch")
			.takes_value(true)
			.help("Stretches all subtitles after adding several seconds to the last one"))
		.arg(Arg::with_name("lang")
			.long("lang")
			.takes_value(true)
			.help("Selects the language of the SRT file(s) (fr/en)"))
		.get_matches();

	let no_backup = matches.is_present("nobak");
	let in_file_paths: Vec<_> = matches.values_of("SRTFILE").unwrap().collect();
	let out_file_path = matches.value_of("out");
	let time_shift_ms = match matches.value_of("shift") {
		Some(tos) => match srt::parse_srt_time(tos) {
			Some(tos_ms) => tos_ms,
			None => {
				let err = Error { message: "--shift invalid argument".into(),
					kind: clap::ErrorKind::TooManyValues,
					info: None };
				err.exit();
			}
		},
		None => 0
	};
	let time_stretch_ms = match matches.value_of("stretch") {
		Some(tos) => match srt::parse_srt_time(tos) {
			Some(tos_ms) => tos_ms,
			None => {
				let err = Error { message: "--stretch invalid argument".into(),
					kind: clap::ErrorKind::TooManyValues,
					info: None };
				err.exit();
			}
		},
		None => 0
	};
	let language = matches.value_of("lang").unwrap_or("fr");

	if language != "en" && language != "fr" {
		println!("Bad language");
		std::process::exit(1);
	}

	// Additional check. Is there a way to do it with clap?
	if out_file_path.is_some() && in_file_paths.len() > 1 {
		let err = Error { message: "--out works only with single input".into(),
			kind: clap::ErrorKind::TooManyValues,
			info: None};
		err.exit();
	}

	/////////////////////////////////////////////////////////////////
	for in_file_path in in_file_paths {
		print!("{} ... ", in_file_path);

		let subtitles_res = srt::load_subtitles(&in_file_path);
		match subtitles_res {
			Ok(_) => (),
			Err(ref err) => {
				println!("{}", err);
				std::process::exit(1);
			}
		}

		let mut subtitles = subtitles_res.unwrap();
		do_replacements(&mut subtitles, &language);
		do_time_changes(&mut subtitles, time_shift_ms, time_stretch_ms);

		// Do backup
		if !no_backup {
			let backup_file_path = format!("{}~", in_file_path);
			match std::fs::copy(&in_file_path, &backup_file_path) {
				Ok(_) => (),
				Err(err) => println!("Cannot create backup: {}", err)
			}
		}

		let final_out_file_path = if out_file_path.is_none() {
			in_file_path
		}
		else {
			out_file_path.unwrap()
		};

		match srt::save_subtitles(&subtitles, &final_out_file_path) {
			Ok(_) => (),
			Err(_) => {
				println!("Save failed");
				std::process::exit(1);
			}
		}
		println!("done: {} subtitles", subtitles.len());
	}
}
<commit_msg>Remove debug line<commit_after>extern crate clap;

use clap::{Arg, App, Error};

mod workfile;
mod srt;
mod txt_rep;
mod rules;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

///////////////////////////////////////////////////////////////////////////////
fn do_replacements(subtitles: &mut Vec<srt::Subtitle>, language: &str) {

	for subtitle in subtitles.iter_mut() {
		for text_index in 0..subtitle.text_count as usize {
			subtitle.texts[text_index] = txt_rep::replace_one(&subtitle.texts[text_index], &language);
		}
		//print!("{}", subtitle.to_string());
	}
}

fn do_time_changes(subtitles: &mut Vec<srt::Subtitle>,
                   time_shift_ms: i32, time_stretch_ms: i32) {

	if time_shift_ms == 0 && time_stretch_ms == 0 {
		return;
	}
	let sub_count = subtitles.len();
	if sub_count == 0 {
		return;
	}

	if sub_count > std::i32::MAX as usize {
		eprintln!("Too many subtitles");
		return;
	};

	// Compute the limit for stretching
	let sub_count_i32 = if srt::should_keep_last_sub(subtitles) {
		sub_count as i32
	}
	else {
		println!("last not kept");
		(sub_count - 1) as i32
	};

	let mut sub_index = 0;
	for subtitle in subtitles.iter_mut() {

		subtitle.time_from += time_shift_ms;
		subtitle.time_to += time_shift_ms;

		if time_stretch_ms > 0 && sub_count_i32 > 1 && sub_index < sub_count_i32 {
			let stretching = (sub_index * time_stretch_ms) / (sub_count_i32 - 1);
			subtitle.time_from += stretching;
			subtitle.time_to += stretching;
		}
		sub_index += 1;
	}
}

///////////////////////////////////////////////////////////////////////////////
fn main() {
	let matches = App::new("fixsrt")
		.version(VERSION)
		.author("Hadrien Nilsson")
		.about("Fix spelling and encoding mistakes in SRT subtitle files")
		.arg(Arg::with_name("nobak")
			.long("nobak")
			.help("Avoids creating a backup file"))
		.arg(Arg::with_name("SRTFILE")
			.required(true)
			.multiple(true)
			.help("SRT file to update"))
		.arg(Arg::with_name("out")
			.short("o")
			.long("out")
			.takes_value(true)
			.help("Outputs to another file (single input only)"))
		.arg(Arg::with_name("shift")
			.long("shift")
			.takes_value(true)
			.help("Shifts all subtitles of several seconds"))
		.arg(Arg::with_name("stretch")
			.long("stretch")
			.takes_value(true)
			.help("Stretches all subtitles after adding several seconds to the last one"))
		.arg(Arg::with_name("lang")
			.long("lang")
			.takes_value(true)
			.help("Selects the language of the SRT file(s) (fr/en)"))
		.get_matches();

	let no_backup = matches.is_present("nobak");
	let in_file_paths: Vec<_> = matches.values_of("SRTFILE").unwrap().collect();
	let out_file_path = matches.value_of("out");
	let time_shift_ms = match matches.value_of("shift") {
		Some(tos) => match srt::parse_srt_time(tos) {
			Some(tos_ms) => tos_ms,
			None => {
				let err = Error { message: "--shift invalid argument".into(),
					kind: clap::ErrorKind::TooManyValues,
					info: None };
				err.exit();
			}
		},
		None => 0
	};
	let time_stretch_ms = match matches.value_of("stretch") {
		Some(tos) => match srt::parse_srt_time(tos) {
			Some(tos_ms) => tos_ms,
			None => {
				let err = Error { message: "--stretch invalid argument".into(),
					kind: clap::ErrorKind::TooManyValues,
					info: None };
				err.exit();
			}
		},
		None => 0
	};
	let language = matches.value_of("lang").unwrap_or("fr");

	if language != "en" && language != "fr" {
		println!("Bad language");
		std::process::exit(1);
	}

	// Additional check. Is there a way to do it with clap?
	if out_file_path.is_some() && in_file_paths.len() > 1 {
		let err = Error { message: "--out works only with single input".into(),
			kind: clap::ErrorKind::TooManyValues,
			info: None};
		err.exit();
	}

	/////////////////////////////////////////////////////////////////
	for in_file_path in in_file_paths {
		print!("{} ... ", in_file_path);

		let subtitles_res = srt::load_subtitles(&in_file_path);
		match subtitles_res {
			Ok(_) => (),
			Err(ref err) => {
				println!("{}", err);
				std::process::exit(1);
			}
		}

		let mut subtitles = subtitles_res.unwrap();
		do_replacements(&mut subtitles, &language);
		do_time_changes(&mut subtitles, time_shift_ms, time_stretch_ms);

		// Do backup
		if !no_backup {
			let backup_file_path = format!("{}~", in_file_path);
			match std::fs::copy(&in_file_path, &backup_file_path) {
				Ok(_) => (),
				Err(err) => println!("Cannot create backup: {}", err)
			}
		}

		let final_out_file_path = if out_file_path.is_none() {
			in_file_path
		}
		else {
			out_file_path.unwrap()
		};

		match srt::save_subtitles(&subtitles, &final_out_file_path) {
			Ok(_) => (),
			Err(_) => {
				println!("Save failed");
				std::process::exit(1);
			}
		}
		println!("done: {} subtitles", subtitles.len());
	}
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(unsafe_no_drop_flag)]
#![feature(scoped)]

extern crate rand;

mod types;
mod config;
mod player;
mod zobrist;
mod cell;
mod field;
mod uct;
mod bot;

use std::io;
use std::io::Read;
use std::str::FromStr;
use types::Coord;
use bot::Bot;

fn main() {
  let mut input = io::stdin();
  let mut bot = None;
  let mut s = String::new();
  loop {
    input.read_to_string(&mut s);
    let mut split = s.split(' ').fuse();
    if let Some(id) = split.next() {
      match split.next() {
        Some("init") => {
          let x_option = split.next().and_then(|x_str| Coord::from_str(x_str).ok());
          let y_option = split.next().and_then(|y_str| Coord::from_str(y_str).ok());;
          let seed_option = split.next();
          if split.next().is_some() {

          } else if let (Some(x), Some(y), Some(seed)) = (x_option, y_option, seed_option) {
            bot = Some(Bot::new(x, y));
          } else {

          }
        },
        _ => {}
      }
    } else {

    }
  }
}
<commit_msg>Some more io implementation.<commit_after>#![allow(dead_code)]
#![feature(unsafe_no_drop_flag)]
#![feature(scoped)]

extern crate rand;

mod types;
mod config;
mod player;
mod zobrist;
mod cell;
mod field;
mod uct;
mod bot;

use std::io;
use std::io::{Read, Write};
use std::str::FromStr;
use std::string::ToString;
use types::Coord;
use bot::Bot;

fn write_author<T: Write>(output: &mut T, id: u32) {
  output.write_all("= ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" author kurnevsky_evgeny\n".as_bytes()).ok();
}

fn write_author_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? \n".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" author\n".as_bytes()).ok();
}

fn write_init<T: Write>(output: &mut T, id: u32) {
  output.write_all("= ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" init\n".as_bytes()).ok();
}

fn write_init_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? \n".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" init\n".as_bytes()).ok();
}

fn write_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? \n".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" input_error\n".as_bytes()).ok();
}

fn main() {
  let mut input = io::stdin();
  let mut output = io::stdout();
  let mut bot = None;
  let mut s = String::new();
  loop {
    input.read_to_string(&mut s).ok();
    let mut split = s.split(' ').fuse();
    if let Some(id) = split.next().and_then(|id_str| u32::from_str(id_str).ok()) {
      match split.next() {
        Some("author") => {
          if split.next().is_some() {
            write_author_error(&mut output, id);
          } else {
            write_author(&mut output, id);
          }
        },
        Some("init") => {
          let x_option = split.next().and_then(|x_str| Coord::from_str(x_str).ok());
          let y_option = split.next().and_then(|y_str| Coord::from_str(y_str).ok());;
          let seed_option = split.next();
          if split.next().is_some() {
            write_init_error(&mut output, id);
          } else if let (Some(x), Some(y), Some(seed)) = (x_option, y_option, seed_option) {
            bot = Some(Bot::new(x, y));
            write_init(&mut output, id);
          } else {
            write_init_error(&mut output, id);
          }
        },
        _ => {
          write_error(&mut output, id);
        }
      }
    } else {
      write_error(&mut output, 0);
    }
  }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate serde;
#[macro_use] extern crate serde_json;
#[macro_use] extern crate glob;
#[macro_use] extern crate uuid;
#[macro_use] extern crate regex;
#[macro_use] extern crate prettytable;
extern crate url;
extern crate config;
extern crate open;

pub use cli::CliConfig;
pub use configuration::Configuration;
pub use runtime::{ImagLogger, Runtime};
pub use clap::App;
pub use module::Module;

pub mod cli;
pub mod configuration;
pub mod runtime;
pub mod module;
pub mod storage;
pub mod ui;
pub mod util;

pub use module::bm::BM;

fn main() {
    let yaml          = load_yaml!("../etc/cli.yml");
    let app           = App::from_yaml(yaml);
    let config        = CliConfig::new(app);

    ImagLogger::init(&config);

    let configuration = Configuration::new(&config);

    debug!("Logger created!");
    debug!("CliConfig    : {:?}", &config);
    debug!("Configuration: {:?}", &configuration);

    let rt = Runtime::new(configuration, config);

    debug!("Runtime      : {:?}", &rt);

    if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") {
        let res = BM::new(&rt).exec(matches);
        info!("BM exited with {}", res);
    } else {
        info!("No commandline call...")
    }
}
<commit_msg>main: Include Notes module<commit_after>#[macro_use] extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate serde;
#[macro_use] extern crate serde_json;
#[macro_use] extern crate glob;
#[macro_use] extern crate uuid;
#[macro_use] extern crate regex;
#[macro_use] extern crate prettytable;
extern crate url;
extern crate config;
extern crate open;

pub use cli::CliConfig;
pub use configuration::Configuration;
pub use runtime::{ImagLogger, Runtime};
pub use clap::App;
pub use module::Module;

pub mod cli;
pub mod configuration;
pub mod runtime;
pub mod module;
pub mod storage;
pub mod ui;
pub mod util;

pub use module::bm::BM;
pub use module::notes::Notes;

fn main() {
    let yaml          = load_yaml!("../etc/cli.yml");
    let app           = App::from_yaml(yaml);
    let config        = CliConfig::new(app);

    ImagLogger::init(&config);

    let configuration = Configuration::new(&config);

    debug!("Logger created!");
    debug!("CliConfig    : {:?}", &config);
    debug!("Configuration: {:?}", &configuration);

    let rt = Runtime::new(configuration, config);

    debug!("Runtime      : {:?}", &rt);

    let res = match rt.config.cli_matches.subcommand_name() {
        Some("bm")    => BM::new(&rt).exec(rt.config.cli_matches.subcommand_matches("bm").unwrap()),
        Some("notes") => Notes::new(&rt).exec(rt.config.cli_matches.subcommand_matches("notes").unwrap()),
        _             => false,
    };

    info!("Module execution ended with {}", res);
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde;
extern crate serde_json;
extern crate term;
extern crate rand;
extern crate url;

use hyper::Client;
use hyper::client::Response;
use std::io::{BufReader, BufRead};
use std::sync::mpsc::channel;
use std::thread;
use std::process;

include!(concat!(env!("OUT_DIR"), "/main.rs"));

#[derive(Debug)]
struct Record {
    namespace: String,
    pod: String,
    container: String,
    color: term::color::Color,
    text: String,
}

#[derive(Default)]
pub struct Options {
    follow: bool,
    label: Option<String>
}

pub struct Logs {
    options: Options,
}

#[derive(Debug)]
pub enum Error {
    Http,
    Parse,
    Url
}

impl From<url::ParseError> for Error {
    fn from(_: url::ParseError) -> Error {
        Error::Url
    }
}

impl From<hyper::Error> for Error {
    fn from(_: hyper::Error) -> Error {
        Error::Http
    }
}

impl From<serde_json::Error> for Error {
    fn from(_: serde_json::Error) -> Error {
        Error::Parse
    }
}

impl Logs {
    pub fn new(options: Options) -> Logs {
        Logs { options: options }
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let colors = vec![term::color::CYAN,
                          term::color::MAGENTA,
                          term::color::GREEN,
                          term::color::YELLOW,
                          term::color::BRIGHT_BLUE];
        let client = Client::new();
        let mut pods_endpoint = try!(url::Url::parse("http://127.0.0.1:8001/api/v1/pods"));
        if let Some(ref label) = self.options.label {
            pods_endpoint.query_pairs_mut().append_pair("labelSelector", label);
        }
        let response = try!(client.get(pods_endpoint).send());
        let pods = try!(serde_json::from_reader::<Response, PodList>(response));
        let (tx, rx) = channel();
        let mut t = term::stdout().unwrap();
        thread::spawn(move || {
            loop {
                if let Ok(Record { namespace, pod, container, color, text }) = rx.recv() {
                    t.reset().unwrap();
                    t.fg(color).unwrap();
                    write!(t, "{}/{}/{}: ", namespace, pod, container).unwrap();
                    t.reset().unwrap();
                    writeln!(t, " {}", text).unwrap();
                }
            }
        });
        let mut rng = rand::thread_rng();
        for pod in pods.items {
            let containers = pod.spec.containers.iter().map(|c| c.name.clone()).collect::<Vec<_>>();
            let mut logs_endpoint = try!(url::Url::parse("http://127.0.0.1:8001/api/v1/namespaces/"))
                .join(format!("{}/", pod.metadata.namespace).as_ref()).unwrap()
                .join("pods/").unwrap()
                .join(format!("{}/log", pod.metadata.name).as_ref()).unwrap();
            logs_endpoint.query_pairs_mut().extend_pairs(vec![
                ("container", containers[0].as_str()),
                ("follow", self.options.follow.to_string().as_str())]);
            println!("url {}", logs_endpoint.as_str());
            let reader = BufReader::new(try!(client.get(logs_endpoint).send()));
            let px = tx.clone();
            let color = rand::sample(&mut rng, colors.clone(), 1)[0];
            thread::spawn(move || {
                for l in reader.lines() {
                    if let Ok(text) = l {
                        let _ = px.send(Record {
                            namespace: pod.metadata.namespace.clone(),
                            pod: pod.metadata.name.clone(),
                            container: containers[0].clone(),
                            color: color,
                            text: text,
                        });
                    }
                }
            });
        }
        Ok(())
    }
}

fn main() {
    if let Err(e) = Logs::new(Default::default()).fetch() {
        println!("error fetching logs: {:?}", e);
        process::exit(1);
    }
}
<commit_msg>remove debug url<commit_after>extern crate hyper;
extern crate serde;
extern crate serde_json;
extern crate term;
extern crate rand;
extern crate url;

use hyper::Client;
use hyper::client::Response;
use std::io::{BufReader, BufRead};
use std::sync::mpsc::channel;
use std::thread;
use std::process;

include!(concat!(env!("OUT_DIR"), "/main.rs"));

#[derive(Debug)]
struct Record {
    namespace: String,
    pod: String,
    container: String,
    color: term::color::Color,
    text: String,
}

#[derive(Default)]
pub struct Options {
    follow: bool,
    label: Option<String>
}

pub struct Logs {
    options: Options,
}

#[derive(Debug)]
pub enum Error {
    Http,
    Parse,
    Url
}

impl From<url::ParseError> for Error {
    fn from(_: url::ParseError) -> Error {
        Error::Url
    }
}

impl From<hyper::Error> for Error {
    fn from(_: hyper::Error) -> Error {
        Error::Http
    }
}

impl From<serde_json::Error> for Error {
    fn from(_: serde_json::Error) -> Error {
        Error::Parse
    }
}

impl Logs {
    pub fn new(options: Options) -> Logs {
        Logs { options: options }
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let colors = vec![term::color::CYAN,
                          term::color::MAGENTA,
                          term::color::GREEN,
                          term::color::YELLOW,
                          term::color::BRIGHT_BLUE];
        let client = Client::new();
        let mut pods_endpoint = try!(url::Url::parse("http://127.0.0.1:8001/api/v1/pods"));
        if let Some(ref label) = self.options.label {
            pods_endpoint.query_pairs_mut().append_pair("labelSelector", label);
        }
        let response = try!(client.get(pods_endpoint).send());
        let pods = try!(serde_json::from_reader::<Response, PodList>(response));
        let (tx, rx) = channel();
        let mut t = term::stdout().unwrap();
        thread::spawn(move || {
            loop {
                if let Ok(Record { namespace, pod, container, color, text }) = rx.recv() {
                    t.reset().unwrap();
                    t.fg(color).unwrap();
                    write!(t, "{}/{}/{}: ", namespace, pod, container).unwrap();
                    t.reset().unwrap();
                    writeln!(t, " {}", text).unwrap();
                }
            }
        });
        let mut rng = rand::thread_rng();
        for pod in pods.items {
            let containers = pod.spec.containers.iter().map(|c| c.name.clone()).collect::<Vec<_>>();
            let mut logs_endpoint = try!(url::Url::parse("http://127.0.0.1:8001/api/v1/namespaces/"))
                .join(format!("{}/", pod.metadata.namespace).as_ref()).unwrap()
                .join("pods/").unwrap()
                .join(format!("{}/log", pod.metadata.name).as_ref()).unwrap();
            logs_endpoint.query_pairs_mut().extend_pairs(vec![
                ("container", containers[0].as_str()),
                ("follow", self.options.follow.to_string().as_str())]);
            let reader = BufReader::new(try!(client.get(logs_endpoint).send()));
            let px = tx.clone();
            let color = rand::sample(&mut rng, colors.clone(), 1)[0];
            thread::spawn(move || {
                for l in reader.lines() {
                    if let Ok(text) = l {
                        let _ = px.send(Record {
                            namespace: pod.metadata.namespace.clone(),
                            pod: pod.metadata.name.clone(),
                            container: containers[0].clone(),
                            color: color,
                            text: text,
                        });
                    }
                }
            });
        }
        Ok(())
    }
}

fn main() {
    if let Err(e) = Logs::new(Default::default()).fetch() {
        println!("error fetching logs: {:?}", e);
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;

mod request;
mod turn;
mod region;
mod superregion;

use request::Request;
use turn::Turn;
use region::Region;
use superregion::SuperRegion;

fn main()
{
	let input = io::stdin();
	let input = BufReader::new(input);
	let input = input.lines();
	let input = input
		.map(Result::unwrap)
		.filter(|s|s.len()>0)
		.map(|s|s.parse::<Request>())
		.map(Result::unwrap);

	let mut name_you = String::new();
	let mut name_other = String::new();

	let mut sup_regions: HashMap<usize,SuperRegion> = HashMap::new();
	let mut regions: HashMap<usize,Region> = HashMap::new();

	for req in input
	{
		use request::Request::*;
		match req
		{
			ListSuperRegions(sregions) =>
			{
				sup_regions.extend(sregions.iter().map(|sr|(sr.id,sr.clone())));
			},
			ListRegions(regs) =>
			{
				regions.extend(regs.iter().map(|r|(r.id,r.clone())));
			},
			ListNeighbours(relations) =>
			{
				for (id,neighbours) in relations
				{
					regions.get_mut(&id).unwrap().neighbours.extend(neighbours.iter());
					for n in neighbours
					{
						regions.get_mut(&n).unwrap().neighbours.push(id);
					}
				}
			},
			RequestStartingRegions(_avail) =>
			{
				println!("give me randomly");
			},
			SettingNameYou(name) => name_you = name,
			SettingNameOther(name) => name_other = name,
			SettingArmies(count) =>
			{
			},
			UpdateMap(updates) =>
			{
			},
			TurnOther(turns) =>
			{
			},
			TurnPlace =>
			{
			},
			TurnArmies =>
			{
			},
		}
	}
}

<commit_msg>updates<commit_after>use std::io;
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;

mod request;
mod turn;
mod region;
mod superregion;

use request::Request;
use turn::Turn;
use region::Region;
use superregion::SuperRegion;

fn main()
{
	let input = io::stdin();
	let input = BufReader::new(input);
	let input = input.lines();
	let input = input
		.map(Result::unwrap)
		.filter(|s|s.len()>0)
		.map(|s|s.parse::<Request>())
		.map(Result::unwrap);

	let mut name_you = String::new();
	let mut name_other = String::new();

	let mut sup_regions: HashMap<usize,SuperRegion> = HashMap::new();
	let mut regions: HashMap<usize,Region> = HashMap::new();

	for req in input
	{
		use request::Request::*;
		match req
		{
			ListSuperRegions(sregions) =>
			{
				sup_regions.extend(sregions.iter().map(|sr|(sr.id,sr.clone())));
			},
			ListRegions(regs) =>
			{
				regions.extend(regs.iter().map(|r|(r.id,r.clone())));
			},
			ListNeighbours(relations) =>
			{
				for (id,neighbours) in relations
				{
					regions.get_mut(&id).unwrap().neighbours.extend(neighbours.iter());
					for n in neighbours
					{
						regions.get_mut(&n).unwrap().neighbours.push(id);
					}
				}
			},
			RequestStartingRegions(_avail) =>
			{
				println!("give me randomly");
			},
			SettingNameYou(name) => name_you = name,
			SettingNameOther(name) => name_other = name,
			SettingArmies(count) =>
			{
			},
			UpdateMap(updates) =>
			{
				for u in updates
				{
					let mut reg = regions.get_mut(&u.0).unwrap();
					reg.player = Some(u.1);
					reg.count = u.2;
				}
			},
			TurnOther(turns) =>
			{
			},
			TurnPlace =>
			{
			},
			TurnArmies =>
			{
			},
		}
	}
}

<|endoftext|>