<commit_before>#![feature(float_from_str_radix, convert, collections)]
#![allow(unused_variables)]

use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::io;
use std::io::prelude::*;
use std::rc::Rc;

type Dictionary = HashMap<String, Rc<Entry>>;
type Statement = Vec<Op>;
type NativeFn = Box<Fn(&mut Vec<Op>, &mut Interpreter)>;

#[derive(Clone)]
enum Op {
	Number(f64),
	Word(Rc<Entry>),
}

enum Code {
	Native(NativeFn),
	Forth(Statement),
}

#[derive(Clone)]
struct Entry {
	name: String,
	code: Rc<Code>,
}

impl PartialEq for Entry {
	fn eq(&self, other: &Self) -> bool { self.name == other.name }
}

impl Eq for Entry {}

impl Hash for Entry {
	fn hash<H>(&self, state: &mut H) where H: Hasher {
		self.name.hash(state)
	}
}

impl Entry {
	fn new(name: String, code: Code) -> Entry {
		Entry {
			name: name,
			code: Rc::new(code),
		}
	}
}

impl Code {
	fn run(&self, stack: &mut Statement, interp: &mut Interpreter) {
		match self {
			&Code::Native(ref f) => {
				f(stack, interp);
			},
			&Code::Forth(ref statement) => {
				for ref op in statement {
					match *op {
						&Op::Number(ref n) => { break; }
						&Op::Word(ref w) => {
							(*w).code.run(stack, interp);
						},
					}
				}
			},
		}
	}
}

trait StatementExt {
	fn pop_number(&mut self, &mut Interpreter) -> f64;
	fn run(&mut self, &mut Interpreter) -> f64;
}

impl StatementExt for Statement {
	fn pop_number(&mut self, interp: &mut Interpreter) -> f64 {
		loop {
			match self.pop() {
				Some(Op::Number(n)) => { return n; },
				Some(Op::Word(s)) => s.code.run(self, interp),
				None => { panic!("Popped empty statement"); },
			}
		}
	}
	fn run(&mut self, interp: &mut Interpreter) -> f64 {
		while self.len() > 0 {
			match self.pop() {
				Some(Op::Number(n)) => { return n },
				Some(Op::Word(w)) => {
					let code = interp.dictionary[w.name.as_str()].code.clone();
					code.run(self, interp);
				},
				None => { panic!("Empty Statement") },
			};
		}
		unreachable!();
	}
}

trait DictionaryExt {
	fn insert_entry(&mut self, Entry);
}

impl DictionaryExt for Dictionary {
	fn insert_entry(&mut self, entry: Entry) {
		self.insert(entry.name.clone(), Rc::new(entry));
	}
}

struct Interpreter {
    dictionary: Dictionary,
}

macro_rules! binary_entry {
	($name:expr, $o:expr) => {
		Entry::new(
				String::from_str($name),
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let b = stack.pop_number(interp);
					let a = stack.pop_number(interp);
					stack.push(Op::Number($o(a, b)));
				})),
			)
	}
}

macro_rules! unary_entry {
	($name:expr, $o:expr) => {
		Entry::new(
				String::from_str($name),
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let b = stack.pop_number(interp);
					stack.push(Op::Number($o(a)));
				})),
			)
	}
}

macro_rules! nonary_entry {
	($name:expr, $o:expr) => {
		Entry::new(
				String::from_str($name),
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					Op::Number($o);
				})),
			)
	}
}

impl Interpreter {
	fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		dict.insert_entry(binary_entry!("/", ::std::ops::Div::div));
		dict.insert_entry(binary_entry!("*", ::std::ops::Mul::mul));
		dict.insert_entry(binary_entry!("+", ::std::ops::Add::add));
		dict.insert_entry(binary_entry!("-", ::std::ops::Sub::sub));
		dict.insert_entry(binary_entry!("%", ::std::ops::Rem::rem));

		dict.insert_entry(nonary_entry!("QUIT", ::std::process::exit(0)));
		dict.insert_entry(nonary_entry!("bye", ::std::process::exit(0)));

		dict.insert_entry(Entry::new(
				String::from_str("DUP"),
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop().unwrap();
					stack.push(x.clone());
					stack.push(x);
				})),
			));

		Interpreter {
			dictionary: dict,
		}
	}

	fn lex(&mut self, statement: String) -> Statement {
		let words = statement.split(' ');
		let mut ret = Statement::new();
		for word in words {
			if let Some(n) = f64::from_str_radix(word, 10).ok() {
				ret.push(Op::Number(n));
			} else {
				ret.push(Op::Word(self.dictionary[word].clone()));
			}
		};
		ret
	}

	fn exec(&mut self, statement: String) -> f64 {
		let mut statement = self.lex(statement);
		return statement.run(self);
	}
}

fn main() {
	println!("forth-rs version 0.1.0");
	println!("Type 'bye' to exit");
    let mut interp = Interpreter::new();
    let mut stdin = io::stdin();
    loop {
    	print!("> ");
    	io::stdout().flush().ok().expect("Could not flush stdout");
    	let mut line = String::new();
    	stdin.read_line(&mut line).ok().expect("Unable to read from stdin");
    	let result = interp.exec(String::from_str(line.trim_right()));
    	println!("{}", result);
    }
}
<commit_msg>Change number type to i32 for now. Add OVER, ROT, MOD, AND, OR.<commit_after>#![feature(convert, collections)]
#![allow(unused_variables)]

use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::io;
use std::io::prelude::*;
use std::rc::Rc;
use std::fmt;

type Dictionary = HashMap<String, Rc<Entry>>;
type Statement = Vec<Op>;
type NativeFn = Box<Fn(&mut Vec<Op>, &mut Interpreter)>;

#[derive(Clone, Debug)]
enum Op {
	Number(i32),
	Word(Rc<Entry>),
}

enum Code {
	Native(NativeFn),
	Forth(Statement),
}

#[derive(Clone)]
struct Entry {
	name: String,
	code: Rc<Code>,
}

impl PartialEq for Entry {
	fn eq(&self, other: &Self) -> bool { self.name == other.name }
}

impl Eq for Entry {}

impl Hash for Entry {
	fn hash<H>(&self, state: &mut H) where H: Hasher {
		self.name.hash(state)
	}
}

impl fmt::Debug for Entry {
	fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.name.fmt(fmt)
	}
}

impl Entry {
	fn new(name: &str, code: Code) -> Entry {
		Entry {
			name: String::from_str(name),
			code: Rc::new(code),
		}
	}
}

impl Code {
	fn run(&self, stack: &mut Statement, interp: &mut Interpreter) {
		match self {
			&Code::Native(ref f) => {
				f(stack, interp);
			},
			&Code::Forth(ref statement) => {
				for ref op in statement {
					match *op {
						&Op::Number(ref n) => { break; }
						&Op::Word(ref w) => {
							(*w).code.run(stack, interp);
						},
					}
				}
			},
		}
	}
}

trait StatementExt {
	fn pop_number(&mut self, &mut Interpreter) -> i32;
	fn run(&mut self, &mut Interpreter) -> Result<i32, Statement>;
}

impl StatementExt for Statement {
	fn pop_number(&mut self, interp: &mut Interpreter) -> i32 {
		loop {
			match self.pop() {
				Some(Op::Number(n)) => { return n; },
				Some(Op::Word(s)) => s.code.run(self, interp),
				None => panic!("Popped empty statement"),
			}
		}
	}
	fn run(&mut self, interp: &mut Interpreter) -> Result<i32, Statement> {
		while self.len() > 0 {
			match self.pop() {
				Some(Op::Number(n)) => {
					if self.len() == 0 {
						return Ok(n)
					} else {
						self.push(Op::Number(n));
						return Err(self.clone())
					}
				},
				Some(Op::Word(w)) => {
					let code = interp.dictionary[w.name.as_str()].code.clone();
					code.run(self, interp);
				},
				None => unreachable!(),
			};
		}
		Ok(0)
	}
}

trait DictionaryExt {
	fn insert_entry(&mut self, Entry);
}

impl DictionaryExt for Dictionary {
	fn insert_entry(&mut self, entry: Entry) {
		self.insert(entry.name.clone(), Rc::new(entry));
	}
}

struct Interpreter {
    dictionary: Dictionary,
}

macro_rules! binary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let b = stack.pop_number(interp);
					let a = stack.pop_number(interp);
					stack.push(Op::Number($o(a, b)));
				})),
			)
	}
}

macro_rules! unary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let b = stack.pop_number(interp);
					stack.push(Op::Number($o(a)));
				})),
			)
	}
}

macro_rules! nonary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					Op::Number($o);
				})),
			)
	}
}

impl Interpreter {
	fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		dict.insert_entry(binary_entry!("/", ::std::ops::Div::div));
		dict.insert_entry(binary_entry!("*", ::std::ops::Mul::mul));
		dict.insert_entry(binary_entry!("+", ::std::ops::Add::add));
		dict.insert_entry(binary_entry!("-", ::std::ops::Sub::sub));
		dict.insert_entry(binary_entry!("MOD", ::std::ops::Rem::rem));
		dict.insert_entry(binary_entry!("AND", ::std::ops::BitAnd::bitand));
		dict.insert_entry(binary_entry!("OR", ::std::ops::BitOr::bitor));

		dict.insert_entry(nonary_entry!("QUIT", ::std::process::exit(0)));
		dict.insert_entry(nonary_entry!("bye", ::std::process::exit(0)));

		dict.insert_entry(Entry::new("DUP",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop().unwrap();
					stack.push(x.clone());
					stack.push(x);
				})),
			));

		dict.insert_entry(Entry::new("OVER",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop().unwrap();
					let y = stack.pop().unwrap();
					stack.push(x.clone());
					stack.push(y);
					stack.push(x);
				})),
			));

		dict.insert_entry(Entry::new("ROT",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop().unwrap();
					let y = stack.pop().unwrap();
					let z = stack.pop().unwrap();
					stack.push(y);
					stack.push(x);
					stack.push(z);
				})),
			));

		Interpreter {
			dictionary: dict,
		}
	}

	fn lex(&mut self, statement: &str) -> Statement {
		let words = statement.split(' ');
		let mut ret = Statement::new();
		for word in words {
			if let Some(n) = i32::from_str_radix(word, 10).ok() {
				ret.push(Op::Number(n));
			} else {
				ret.push(Op::Word(self.dictionary[word].clone()));
			}
		};
		ret
	}

	fn exec(&mut self, statement: &str) -> Result<i32, Statement> {
		let mut statement = self.lex(statement);
		return statement.run(self);
	}
}

fn main() {
	println!("forth-rs version 0.1.0");
	println!("Type 'bye' to exit");
    let mut interp = Interpreter::new();
    let mut stdin = io::stdin();
    loop {
    	print!("> ");
    	io::stdout().flush().ok().expect("Could not flush stdout");
    	let mut line = String::new();
    	stdin.read_line(&mut line).ok().expect("Unable to read from stdin");
    	match interp.exec(line.trim_right()) {
    		Err(s) => {
    			println!("{:?}", s);
    		},
    		Ok(n) => {
    			println!("{}", n);
    		},
    	}
    }
}
<|endoftext|>


<commit_before>#![feature(io, slice_patterns, vec_resize)]
use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;
use std::thread;

#[derive(Debug)]
enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    // extra optimized ops
    Transfer(u8, Vec<(isize, u8)>)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    let mut maybe_new_op = None;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match op {
                &Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                &Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        match map.remove(&0) {
            Some(summand) => Some(Transfer(summand, map.into_iter().collect())),
            None => None
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            &Mov(n) => {
                self.index = self.rel_index(n);
            }
            &In => {
                let mut c = [0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            &Out => {
                io::stdout().write(&[self[0]]).unwrap();
            }
            &Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            &Transfer(d, ref map) => {
                if self[0] == 0 {
                    return true
                }

                let mut _v = self[0];
                let mut _n = 0;

                while _v != 0 {
                    _v = _v.wrapping_add(d);
                    if _v == self[0] {
                        // stalled: the current transfer will never complete
                        loop {
                            thread::park()
                        }
                    }
                    _n += 1
                }

                self[0] = 0;
                for &(k, v) in &map[..] {
                    self[k] = self[k].wrapping_add(v.wrapping_mul(_n));
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(0x01)),
            '-' => Something(Add(0xff)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) => c != ']',
                    _ => panic!("Unterminated loop")
                } {
                    if let Something(op) = parse(&mut chars) {
                        childstream.add(op)
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    fs::File::open(path).map(|f| io::BufReader::new(f))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use super::{parse, ParserResult, State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_index() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_state_step_transfer() {
        let mut state = State::new();
        state[0] = 15;
        state[1] = 7;
        state.step(&Transfer(5, vec![(1, 2)]));
        assert_eq!(0, state[0]);
        assert_eq!(1, state[1]);
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(0x01));
        opstream.add(Add(0xff));
        opstream.add(Add(0xff));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(0xff), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        let mut chars = io::BufReader::new(&input[..]).chars().peekable();
        assert_let!(ParserResult::Something(Add(0x01)), parse(&mut chars));
        assert_let!(ParserResult::Something(Add(0xff)), parse(&mut chars));
        assert_let!(ParserResult::Something(Loop(loop_op)), parse(&mut chars), {
            assert_let!([Add(1), Out, In], &loop_op.ops[..]);
        });
        assert_let!(ParserResult::Something(Add(1)), parse(&mut chars));
    }
}
<commit_msg>style: proper use of Option<commit_after>#![feature(io, slice_patterns, vec_resize)]
use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;
use std::thread;

#[derive(Debug)]
enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    // extra optimized ops
    Transfer(u8, Vec<(isize, u8)>)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    let mut maybe_new_op = None;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match op {
                &Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                &Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        map.remove(&0).map(|summand| Transfer(summand, map.into_iter().collect()))
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            &Mov(n) => {
                self.index = self.rel_index(n);
            }
            &In => {
                let mut c = [0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            &Out => {
                io::stdout().write(&[self[0]]).unwrap();
            }
            &Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            &Transfer(d, ref map) => {
                if self[0] == 0 {
                    return true
                }

                let mut _v = self[0];
                let mut _n = 0;

                while _v != 0 {
                    _v = _v.wrapping_add(d);
                    if _v == self[0] {
                        // stalled: the current transfer will never complete
                        loop {
                            thread::park()
                        }
                    }
                    _n += 1
                }

                self[0] = 0;
                for &(k, v) in &map[..] {
                    self[k] = self[k].wrapping_add(v.wrapping_mul(_n));
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(0x01)),
            '-' => Something(Add(0xff)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) => c != ']',
                    _ => panic!("Unterminated loop")
                } {
                    if let Something(op) = parse(&mut chars) {
                        childstream.add(op)
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    fs::File::open(path).map(|f| io::BufReader::new(f))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use super::{parse, ParserResult, State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_index() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_state_step_transfer() {
        let mut state = State::new();
        state[0] = 15;
        state[1] = 7;
        state.step(&Transfer(5, vec![(1, 2)]));
        assert_eq!(0, state[0]);
        assert_eq!(1, state[1]);
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(0x01));
        opstream.add(Add(0xff));
        opstream.add(Add(0xff));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(0xff), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        let mut chars = io::BufReader::new(&input[..]).chars().peekable();
        assert_let!(ParserResult::Something(Add(0x01)), parse(&mut chars));
        assert_let!(ParserResult::Something(Add(0xff)), parse(&mut chars));
        assert_let!(ParserResult::Something(Loop(loop_op)), parse(&mut chars), {
            assert_let!([Add(1), Out, In], &loop_op.ops[..]);
        });
        assert_let!(ParserResult::Something(Add(1)), parse(&mut chars));
    }
}
<|endoftext|>


<commit_before>use std::cmp::Reverse;
use std::fs::File;
use std::io::Read;

fn main() {
    println!("{:?}", find_synonyms("mesa"));
}

fn find_synonyms(term: &str) -> Vec<String> {
    let mut file = File::open("dict/th_es_ANY_v2.dat").expect("Failed opening file");
    let mut contents = String::new();
    file.read_to_string(&mut contents);
    let synonyms = match contents.find(format!("\n{}", term).as_str()) {
        Some(pos) => read_synonyms(&contents, pos),
        None => vec![],
    };
    synonyms
}

fn read_synonyms(contents: &str, position: usize) -> Vec<String> {
    let mut synonyms: Vec<_> = contents[position + 1 ..].lines().skip(1)
        .take_while(|line| &line[..1] == "-" || &line[..1] == "(")
        .flat_map(|line| line.split("|").skip(1))
        .map(String::from).collect();
    synonyms.sort_by_key(|word| Reverse(word.len()));
    synonyms.dedup();
    synonyms
}

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

    #[test]
    fn it_finds_synonyms_for_a_known_term() {
        assert_eq!(vec!["izquierdo", "siniestro"], find_synonyms("zurdo"));
        assert_eq!(vec!["retrato", "foto"], find_synonyms("fotografía"));
        assert_eq!(vec!["zarzamora"], find_synonyms("zarza"));
    }

    #[test]
    fn it_reads_synonyms_in_multiple_lines() {
        assert_eq!(vec!["abundante", "copioso", "suelto"], find_synonyms("granel"));
    }

    #[test]
    fn it_sorts_by_longest_first_and_removes_duplicates() {
        assert_eq!(vec!["arcilla", "marga", "gres"], find_synonyms("greda"));
    }
}
<commit_msg>Get longest synonym if exists<commit_after>use std::cmp::Reverse;
use std::fs::File;
use std::io::Read;

fn main() {
    println!("{:?}", find_synonyms("mesa"));
    println!("{:?}", longest_synonym("mesa"));
}

pub fn longest_synonym(term: &str) -> Option<String> {
    let synonyms = find_synonyms(term);
    if synonyms.is_empty() { None } else { Some(synonyms[0].clone()) }
}

fn find_synonyms(term: &str) -> Vec<String> {
    let mut file = File::open("dict/th_es_ANY_v2.dat").expect("Failed opening file");
    let mut contents = String::new();
    file.read_to_string(&mut contents);
    let synonyms = match contents.find(format!("\n{}", term).as_str()) {
        Some(pos) => read_synonyms(&contents, pos),
        None => vec![],
    };
    synonyms
}

fn read_synonyms(contents: &str, position: usize) -> Vec<String> {
    let mut synonyms: Vec<_> = contents[position + 1 ..].lines().skip(1)
        .take_while(|line| &line[..1] == "-" || &line[..1] == "(")
        .flat_map(|line| line.split("|").skip(1))
        .map(String::from).collect();
    synonyms.sort_by_key(|word| Reverse(word.len()));
    synonyms.dedup();
    synonyms
}

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

    #[test]
    fn it_finds_synonyms_for_a_known_term() {
        assert_eq!(vec!["izquierdo", "siniestro"], find_synonyms("zurdo"));
        assert_eq!(vec!["retrato", "foto"], find_synonyms("fotografía"));
        assert_eq!(vec!["zarzamora"], find_synonyms("zarza"));
    }

    #[test]
    fn it_reads_synonyms_in_multiple_lines() {
        assert_eq!(vec!["abundante", "copioso", "suelto"], find_synonyms("granel"));
    }

    #[test]
    fn it_sorts_by_longest_first_and_removes_duplicates() {
        assert_eq!(vec!["arcilla", "marga", "gres"], find_synonyms("greda"));
    }

    #[test]
    fn it_gets_the_longest_synonym() {
        assert_eq!(Some("abundante".to_string()), longest_synonym("granel"));
        assert_eq!(Some("arcilla".to_string()), longest_synonym("greda"));
    }

    #[test]
    fn it_returns_none_if_no_synonym_was_found() {
        assert_eq!(None, longest_synonym("noexiste"));
    }
}
<|endoftext|>


<commit_before>extern crate dive;

extern crate getopts;

use std::env;
use std::path::Path;
use std::process;
use getopts::Options;

const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} path ... [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = Path::new(&args[0])
        .file_name()
        .and_then(|o| o.to_str())
        .unwrap();

    let mut opts = Options::new();
    opts.optmulti("m", "match", "Filter by basic substring matching", "STRING");
    opts.optmulti("n", "name", "Filter by file name", "PATTERN");
    opts.optmulti("p", "path", "Filter by file path", "PATTERN");
    opts.optmulti("r", "regex", "Filter by regular expression", "REGEX");
    opts.optflag("a", "all", "Show files whose names begin with a dot (.)");
    opts.optflag("C", "case-sensitive", "Force case-sensitive matching");
    opts.optflag("h", "help", "Print this help menu");
    opts.optflag("V", "version", "Print version info and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}: {}\n", program, f.to_string());
            print_usage(&program, opts);
            process::exit(1);
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    if matches.opt_present("V") {
        println!("{} version {}", program, VERSION.unwrap_or("unknown"));
        return;
    }

    let config = match dive::Config::new(&matches) {
        Ok(c) => c,
        Err(e) => {
            println!("Unable to parse all match rules: {}", e);
            process::exit(1);
        }
    };

    let start_paths = if !matches.free.is_empty() {
        matches.free.clone()
    } else {
        vec![".".to_string()]
    };

    if let Err(e) = dive::run(start_paths, config) {
        println!("ERROR: {}", e);
        process::exit(1);
    }
}
<commit_msg>Remove an unwrap (from calculating program name)<commit_after>extern crate dive;

extern crate getopts;

use std::env;
use std::path::Path;
use std::process;
use getopts::Options;

const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} path ... [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let program_name = match Path::new(&args[0])
        .file_name()
        .and_then(|o| o.to_str()) {
        Some(s) => s,
        None => "dive",
    };

    let mut opts = Options::new();
    opts.optmulti("m", "match", "Filter by basic substring matching", "STRING");
    opts.optmulti("n", "name", "Filter by file name", "PATTERN");
    opts.optmulti("p", "path", "Filter by file path", "PATTERN");
    opts.optmulti("r", "regex", "Filter by regular expression", "REGEX");
    opts.optflag("a", "all", "Show files whose names begin with a dot (.)");
    opts.optflag("C", "case-sensitive", "Force case-sensitive matching");
    opts.optflag("h", "help", "Print this help menu");
    opts.optflag("V", "version", "Print version info and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}: {}\n", program_name, f.to_string());
            print_usage(&program_name, opts);
            process::exit(1);
        }
    };

    if matches.opt_present("h") {
        print_usage(&program_name, opts);
        return;
    }

    if matches.opt_present("V") {
        println!("{} version {}", program_name, VERSION.unwrap_or("unknown"));
        return;
    }

    let config = match dive::Config::new(&matches) {
        Ok(c) => c,
        Err(e) => {
            println!("Unable to parse all match rules: {}", e);
            process::exit(1);
        }
    };

    let start_paths = if !matches.free.is_empty() {
        matches.free.clone()
    } else {
        vec![".".to_string()]
    };

    if let Err(e) = dive::run(start_paths, config) {
        println!("ERROR: {}", e);
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate diesel;

mod db;
mod homectl_core;
mod integrations;

use db::{actions::find_floorplans, establish_connection};
use homectl_core::{
    devices_manager::DevicesManager, events::*, groups_manager::GroupsManager,
    integrations_manager::IntegrationsManager, rules_engine::RulesEngine, scene::{CycleScenesDescriptor, SceneDescriptor},
    scenes_manager::ScenesManager,
};
use std::error::Error;

// https://github.com/actix/examples/blob/master/diesel/src/main.rs
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let (config, opaque_integrations_configs) = homectl_core::config::read_config();

    println!("Using config:");
    println!("{:#?}", config);

    let (sender, receiver) = mk_channel();

    let integrations_manager = IntegrationsManager::new(sender.clone());
    let groups_manager = GroupsManager::new(config.groups);
    let scenes_manager = ScenesManager::new(config.scenes, groups_manager);
    let mut devices_manager = DevicesManager::new(sender.clone(), scenes_manager);
    let rules_engine = RulesEngine::new(config.routines, sender.clone());

    for (id, integration_config) in &config.integrations {
        let opaque_integration_config: &config::Value =
            opaque_integrations_configs.get(id).unwrap();

        integrations_manager
            .load_integration(&integration_config.plugin, id, opaque_integration_config)
            .unwrap();
    }

    let connection = establish_connection();
    let results = find_floorplans(&connection);
    println!("Floorplans in DB: {:?}", results);

    let _result: Result<(), ()> = {
        integrations_manager.run_register_pass().await?;
        integrations_manager.run_start_pass().await?;

        Ok(())
    };

    loop {
        let msg = receiver.recv()?;

        // println!("got msg: {:?}", msg);

        match msg {
            Message::IntegrationDeviceRefresh { device } => {
                devices_manager.handle_integration_device_refresh(device)
            }
            Message::DeviceUpdate {
                old_state,
                new_state,
                old,
                new,
            } => rules_engine.handle_device_update(old_state, new_state, old, new),
            Message::SetDeviceState { device } => {
                devices_manager.set_device_state(&device, false);
            }
            Message::SetIntegrationDeviceState { device } => {
                integrations_manager
                    .set_integration_device_state(device)
                    .await;
            }
            Message::ActivateScene(SceneDescriptor { scene_id }) => {
                devices_manager.activate_scene(&scene_id);
            }
            Message::CycleScenes(CycleScenesDescriptor { scenes }) => {
                devices_manager.cycle_scenes(&scenes);
            }
        }
    }
}
<commit_msg>comment out unused db stuff<commit_after>#[macro_use]
extern crate diesel;

mod db;
mod homectl_core;
mod integrations;

// use db::{actions::find_floorplans, establish_connection};
use homectl_core::{
    devices_manager::DevicesManager,
    events::*,
    groups_manager::GroupsManager,
    integrations_manager::IntegrationsManager,
    rules_engine::RulesEngine,
    scene::{CycleScenesDescriptor, SceneDescriptor},
    scenes_manager::ScenesManager,
};
use std::error::Error;

// https://github.com/actix/examples/blob/master/diesel/src/main.rs
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let (config, opaque_integrations_configs) = homectl_core::config::read_config();

    // println!("Using config:");
    // println!("{:#?}", config);

    let (sender, receiver) = mk_channel();

    let integrations_manager = IntegrationsManager::new(sender.clone());
    let groups_manager = GroupsManager::new(config.groups);
    let scenes_manager = ScenesManager::new(config.scenes, groups_manager);
    let mut devices_manager = DevicesManager::new(sender.clone(), scenes_manager);
    let rules_engine = RulesEngine::new(config.routines, sender.clone());

    for (id, integration_config) in &config.integrations {
        let opaque_integration_config: &config::Value =
            opaque_integrations_configs.get(id).unwrap();

        integrations_manager
            .load_integration(&integration_config.plugin, id, opaque_integration_config)
            .unwrap();
    }

    // let connection = establish_connection();
    // let results = find_floorplans(&connection);
    // println!("Floorplans in DB: {:?}", results);

    let _result: Result<(), ()> = {
        integrations_manager.run_register_pass().await?;
        integrations_manager.run_start_pass().await?;

        Ok(())
    };

    loop {
        let msg = receiver.recv()?;

        // println!("got msg: {:?}", msg);

        match msg {
            Message::IntegrationDeviceRefresh { device } => {
                devices_manager.handle_integration_device_refresh(device)
            }
            Message::DeviceUpdate {
                old_state,
                new_state,
                old,
                new,
            } => rules_engine.handle_device_update(old_state, new_state, old, new),
            Message::SetDeviceState { device } => {
                devices_manager.set_device_state(&device, false);
            }
            Message::SetIntegrationDeviceState { device } => {
                integrations_manager
                    .set_integration_device_state(device)
                    .await;
            }
            Message::ActivateScene(SceneDescriptor { scene_id }) => {
                devices_manager.activate_scene(&scene_id);
            }
            Message::CycleScenes(CycleScenesDescriptor { scenes }) => {
                devices_manager.cycle_scenes(&scenes);
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate assimp;
extern crate cgmath;

use assimp::Importer;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Point;
use sdl2::render::Renderer;
use std::cmp::Ordering;
use cgmath::InnerSpace;
use cgmath::Vector3;
use cgmath::Zero;

use assimp::Vector3D;

static WIDTH: u32 = 700;
static HEIGHT: u32 = 700;
static mut Z_BUFFER: [f32; 700 * 700] = [-1.; 700 * 700];

fn sort_points_by_y(points: &mut Vec<Vector3<f32>>) {
    for _ in 0..(points.len() - 1) {
        for j in 0..(points.len() - 1) {
            if points[j].y > points[j + 1].y {
                points.swap(j, j + 1);
            }
        }
    }
}

fn clamp<N>(a: N, min: N, max: N) -> N where N: PartialOrd {
    if a < min { return min }
    if a > max { return max }
    a
}

fn interpolate(min: f32, max: f32, gradient: f32) -> f32 {
    min + (max - min) * clamp(gradient, 0., 1.)
}

fn get_line_points(start: Point, end: Point) -> Vec<Point> {
    let mut x0 = start.x();
    let mut y0 = start.y();
    let mut x1 = end.x();
    let mut y1 = end.y();

    let steep = (y1 - y0).abs() > (x1 - x0).abs();

    if steep {
        std::mem::swap(&mut x0, &mut y0);
        std::mem::swap(&mut x1, &mut y1);
    }

    let reverse = x0 > x1;

    if reverse {
        std::mem::swap(&mut x0, &mut x1);
        std::mem::swap(&mut y0, &mut y1);
    }

    let dx = x1 - x0;
    let dy = (y1 - y0).abs();

    let mut err = dx / 2;
    let mut y = y0;
    let ystep = match y0.cmp(&y1) {
        Ordering::Less => 1,
        _ => -1
    };

    let mut points: Vec<Point> = vec![];

    for x in x0..x1 {
        if steep {
            points.push(Point::new(y, x));
        } else {
            points.push(Point::new(x, y));
        }

        err -= dy;

        if err < 0 {
            y += ystep;
            err += dx;
        }
    }

    points
}

trait TinyRenderer {
    fn pixel(&mut self, i32, i32, f32, Color);
    fn point(&mut self, Vector3<f32>, Color);
    fn line(&mut self, Point, Point, Color);
    fn process_scan_line(&mut self, i32, Vector3<f32>, Vector3<f32>, Vector3<f32>, Vector3<f32>, Color);
    fn triangle(&mut self, Vector3<f32>, Vector3<f32>, Vector3<f32>, Color);
}

impl<'a> TinyRenderer for Renderer<'a> {
    fn pixel(&mut self, x: i32, y: i32, z: f32, c: Color, ) {
        let index = (x + y * WIDTH as i32) as usize;

        if unsafe { Z_BUFFER[index] < z } {
            let current_color = self.draw_color();
            self.set_draw_color(c);

            self.draw_point(Point::new(x, y)).unwrap();

            unsafe {
                Z_BUFFER[index] = z;
            }

            self.set_draw_color(current_color);
        }
    }

    fn point(&mut self, p: Vector3<f32>, c: Color) {
        if p.x >= 0. && p.y >= 0. && p.x < WIDTH as f32 && p.y < HEIGHT as f32 {
            self.pixel(p.x as i32, p.y as i32, p.z, c);
        }
    }

    fn line(&mut self, start: Point, end: Point, c: Color) {
        let current_color = self.draw_color();
        self.set_draw_color(c);

        let points = get_line_points(start, end);

        for p in 0..points.len() {
            self.draw_point(points[p]).unwrap();
        }

        self.set_draw_color(current_color);
    }

    fn process_scan_line(&mut self, y: i32, pa: Vector3<f32>, pb: Vector3<f32>, pc: Vector3<f32>, pd: Vector3<f32>, c: Color) {
        let grad1 = match (pa.y as i32).cmp(&(pb.y as i32)) {
            Ordering::Equal => 1.,
            _ => (y as f32 - pa.y) / (pb.y - pa.y)
        };

        let grad2 = match (pc.y as i32).cmp(&(pd.y as i32)) {
            Ordering::Equal => 1.,
            _ => (y as f32 - pc.y) / (pd.y - pc.y)
        };

        let mut sx = interpolate(pa.x, pb.x, grad1) as i32;
        let mut ex = interpolate(pc.x, pd.x, grad2) as i32;

        if sx > ex {
            std::mem::swap(&mut sx, &mut ex);
        }

        let z1 = interpolate(pa.z, pb.z, grad1);
        let z2 = interpolate(pc.z, pd.z, grad2);

        for x in sx..ex {
            let gradient = (x - sx) as f32 / (ex - sx) as f32;

            let z = interpolate(z1, z2, gradient);
            self.point(Vector3::<f32>::new(x as f32, y as f32, z), c);
        }
    }

    fn triangle(&mut self, p0: Vector3<f32>, p1: Vector3<f32>, p2: Vector3<f32>, c: Color) {
        let mut points = vec![p0, p1, p2];
        sort_points_by_y(&mut points);

        let dp0p1 = match ((points[1].y - points[0].y) as i32).cmp(&0) {
            Ordering::Greater => (points[1].x - points[0].x) / (points[1].y - points[0].y),
            _ => 0.
        };

        let dp0p2 = match ((points[2].y - points[0].y) as i32).cmp(&0) {
            Ordering::Greater => (points[2].x - points[0].x) / (points[2].y - points[0].y),
            _ => 0.
        };

        for y in points[0].y as i32..points[2].y as i32 {
            if y < points[1].y as i32 {
                if dp0p1 > dp0p2 {
                    self.process_scan_line(y, points[0], points[2], points[0], points[1], c);
                } else {
                    self.process_scan_line(y, points[0], points[1], points[0], points[2], c);
                }
            } else {
                if dp0p1 > dp0p2 {
                    self.process_scan_line(y, points[0], points[2], points[1], points[2], c);
                } else {
                    self.process_scan_line(y, points[1], points[2], points[0], points[2], c);
                }
            }
        }
    }
}

fn main() {
    let importer = Importer::new();
    let scene = importer.read_file("resources/model.obj").unwrap();

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("tinyrenderer-rs", WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();

    let light_dir = Vector3::new(0., 0., -1.);

    for mesh in scene.mesh_iter() {
        for face in mesh.face_iter() {
            let mut screen_coords: [Vector3<f32>; 3] = [Vector3::zero(); 3];
            let mut world_coords: [Vector3<f32>; 3] = [Vector3::zero(); 3];

            for j in 0..3 {
                let v = match mesh.get_vertex(face[j]) {
                    Some(x) => x,
                    None => Vector3D::new(0., 0., 0.)
                };

                let (p1, p2) = ((v.x + 1.) * WIDTH as f32 / 2., (v.y + 1.) * HEIGHT as f32 / 2.);
                screen_coords[j as usize] = Vector3::<f32>::new(p1, (HEIGHT as f32 - p2), v.z);

                world_coords[j as usize] = v.into();
            }

            let n = (world_coords[2] - world_coords[0]).cross(world_coords[1] - world_coords[0]).normalize();
            let intensity = n.dot(light_dir);

            if intensity > 0.0 { // back-face culling
                renderer.triangle(
                    screen_coords[0],
                    screen_coords[1],
                    screen_coords[2],
                    Color::RGB(
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8
                    )
                );
            }
        }
    }

    renderer.present();

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        //code here
    }
}
<commit_msg>Dirty perspective projection implementation<commit_after>extern crate sdl2;
extern crate assimp;
extern crate cgmath;

use assimp::Importer;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Point;
use sdl2::render::Renderer;
use std::cmp::Ordering;
use cgmath::InnerSpace;
use cgmath::Vector3;
use cgmath::Vector4;
use cgmath::Zero;
use cgmath::Matrix4;
use cgmath::SquareMatrix;

static WIDTH: u32 = 700;
static HEIGHT: u32 = 700;
static mut Z_BUFFER: [f32; 800 * 800] = [-1.; 800 * 800];

fn sort_points_by_y(points: &mut Vec<Vector3<f32>>) {
    for _ in 0..(points.len() - 1) {
        for j in 0..(points.len() - 1) {
            if points[j].y > points[j + 1].y {
                points.swap(j, j + 1);
            }
        }
    }
}

fn clamp<N>(a: N, min: N, max: N) -> N where N: PartialOrd {
    if a < min { return min }
    if a > max { return max }
    a
}

fn interpolate(min: f32, max: f32, gradient: f32) -> f32 {
    min + (max - min) * clamp(gradient, 0., 1.)
}

fn get_line_points(start: Point, end: Point) -> Vec<Point> {
    let mut x0 = start.x();
    let mut y0 = start.y();
    let mut x1 = end.x();
    let mut y1 = end.y();

    let steep = (y1 - y0).abs() > (x1 - x0).abs();

    if steep {
        std::mem::swap(&mut x0, &mut y0);
        std::mem::swap(&mut x1, &mut y1);
    }

    let reverse = x0 > x1;

    if reverse {
        std::mem::swap(&mut x0, &mut x1);
        std::mem::swap(&mut y0, &mut y1);
    }

    let dx = x1 - x0;
    let dy = (y1 - y0).abs();

    let mut err = dx / 2;
    let mut y = y0;
    let ystep = match y0.cmp(&y1) {
        Ordering::Less => 1,
        _ => -1
    };

    let mut points: Vec<Point> = vec![];

    for x in x0..x1 {
        if steep {
            points.push(Point::new(y, x));
        } else {
            points.push(Point::new(x, y));
        }

        err -= dy;

        if err < 0 {
            y += ystep;
            err += dx;
        }
    }

    points
}

trait TinyRenderer {
    fn pixel(&mut self, i32, i32, f32, Color);
    fn point(&mut self, Vector3<f32>, Color);
    fn line(&mut self, Point, Point, Color);
    fn process_scan_line(&mut self, i32, Vector3<f32>, Vector3<f32>, Vector3<f32>, Vector3<f32>, Color);
    fn triangle(&mut self, Vector3<f32>, Vector3<f32>, Vector3<f32>, Color);
}

impl<'a> TinyRenderer for Renderer<'a> {
    fn pixel(&mut self, x: i32, y: i32, z: f32, c: Color, ) {
        let index = (x + y * WIDTH as i32) as usize;

        if unsafe { Z_BUFFER[index] < z } {
            let current_color = self.draw_color();
            self.set_draw_color(c);

            self.draw_point(Point::new(x, y)).unwrap();

            unsafe {
                Z_BUFFER[index] = z;
            }

            self.set_draw_color(current_color);
        }
    }

    fn point(&mut self, p: Vector3<f32>, c: Color) {
        if p.x >= 0. && p.y >= 0. && p.x < WIDTH as f32 && p.y < HEIGHT as f32 {
            self.pixel(p.x as i32, p.y as i32, p.z, c);
        }
    }

    fn line(&mut self, start: Point, end: Point, c: Color) {
        let current_color = self.draw_color();
        self.set_draw_color(c);

        let points = get_line_points(start, end);

        for p in 0..points.len() {
            self.draw_point(points[p]).unwrap();
        }

        self.set_draw_color(current_color);
    }

    fn process_scan_line(&mut self, y: i32, pa: Vector3<f32>, pb: Vector3<f32>, pc: Vector3<f32>, pd: Vector3<f32>, c: Color) {
        let grad1 = match (pa.y as i32).cmp(&(pb.y as i32)) {
            Ordering::Equal => 1.,
            _ => (y as f32 - pa.y) / (pb.y - pa.y)
        };

        let grad2 = match (pc.y as i32).cmp(&(pd.y as i32)) {
            Ordering::Equal => 1.,
            _ => (y as f32 - pc.y) / (pd.y - pc.y)
        };

        let mut sx = interpolate(pa.x, pb.x, grad1) as i32;
        let mut ex = interpolate(pc.x, pd.x, grad2) as i32;

        if sx > ex {
            std::mem::swap(&mut sx, &mut ex);
        }

        let z1 = interpolate(pa.z, pb.z, grad1);
        let z2 = interpolate(pc.z, pd.z, grad2);

        for x in sx..ex {
            let gradient = (x - sx) as f32 / (ex - sx) as f32;

            let z = interpolate(z1, z2, gradient);
            self.point(Vector3::<f32>::new(x as f32, y as f32, z), c);
        }
    }

    fn triangle(&mut self, p0: Vector3<f32>, p1: Vector3<f32>, p2: Vector3<f32>, c: Color) {
        let mut points = vec![p0, p1, p2];
        sort_points_by_y(&mut points);

        let dp0p1 = match ((points[1].y - points[0].y) as i32).cmp(&0) {
            Ordering::Greater => (points[1].x - points[0].x) / (points[1].y - points[0].y),
            _ => 0.
        };

        let dp0p2 = match ((points[2].y - points[0].y) as i32).cmp(&0) {
            Ordering::Greater => (points[2].x - points[0].x) / (points[2].y - points[0].y),
            _ => 0.
        };

        for y in points[0].y as i32..points[2].y as i32 {
            if y < points[1].y as i32 {
                if dp0p1 > dp0p2 {
                    self.process_scan_line(y, points[0], points[2], points[0], points[1], c);
                } else {
                    self.process_scan_line(y, points[0], points[1], points[0], points[2], c);
                }
            } else {
                if dp0p1 > dp0p2 {
                    self.process_scan_line(y, points[0], points[2], points[1], points[2], c);
                } else {
                    self.process_scan_line(y, points[1], points[2], points[0], points[2], c);
                }
            }
        }
    }
}

fn main() {
    let importer = Importer::new();
    let scene = importer.read_file("resources/model.obj").unwrap();

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("tinyrenderer-rs", WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();

    let camera = Vector3::new(0., 0., 3.);
    let light_dir = Vector3::new(0., 0., -1.);
    let mut projection = Matrix4::<f32>::identity();
    let mut viewport = Matrix4::<f32>::identity();
    let (x, y, w, h) = (WIDTH as f32 / 8., HEIGHT as f32 / 8., WIDTH as f32 * 3. / 4., HEIGHT as f32 * 3. / 4.);
    viewport[3][0] = x + w / 2.;
    viewport[3][1] = y + h / 2.;
    viewport[3][2] = 255. / 2.; //depth

    viewport[0][0] = w / 2.;
    viewport[1][1] = h / 2.;
    viewport[2][2] = 255. / 2.;

    projection[2][3] = -1. / camera.z;

    for mesh in scene.mesh_iter() {
        for face in mesh.face_iter() {
            let mut screen_coords: [Vector3<f32>; 3] = [Vector3::zero(); 3];
            let mut world_coords: [Vector3<f32>; 3] = [Vector3::zero(); 3];

            for j in 0..3 {
                let v: Vector3<f32> = match mesh.get_vertex(face[j]) {
                    Some(x) => x.into(),
                    None => Vector3::<f32>::new(0., 0., 0.)
                };

                //let (p1, p2) = ((v.x + 1.) * WIDTH as f32 / 2., (v.y + 1.) * HEIGHT as f32 / 2.);
                // m2v(viewport * projection * v2m(v));
                let m = viewport * projection * Vector4::<f32>::new(v.x, v.y, v.z, 1.);
                let result_vector = Vector3::<f32>::new(m.x / m.w, HEIGHT as f32 - (m.y / m.w), m.z / m.w);

                screen_coords[j as usize] = result_vector;

                world_coords[j as usize] = v;
            }

            let n = (world_coords[2] - world_coords[0]).cross(world_coords[1] - world_coords[0]).normalize();
            let intensity = n.dot(light_dir);

            if intensity > 0.0 { // back-face culling
                renderer.triangle(
                    screen_coords[0],
                    screen_coords[1],
                    screen_coords[2],
                    Color::RGB(
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8
                    )
                );
            }
        }
    }

    renderer.present();

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        //code here
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::io::Cursor;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
use std::io::prelude::*;
use std::net::TcpStream;
use std::thread;
use std::sync::mpsc;

#[derive(Copy, Clone, Debug)]
struct RocketErr {
}

enum RocketState {
    NewCommand,
    IncompleteCommand(usize),
    CompleteCommand,
}

struct Rocket {
    stream: TcpStream,
    state: RocketState,
    cmd: Vec<u8>,
}

impl Rocket {
    pub fn new() -> Result<Rocket, RocketErr> {
        Rocket::connect("localhost", 1338)
    }

    pub fn connect(host: &str, port: u16) -> Result<Rocket, RocketErr> {
        let mut stream = TcpStream::connect((host, port)).expect("Failed to connect");

        let mut rocket = Rocket {
            stream: stream,
            state: RocketState::NewCommand,
            cmd: vec![],
        };

        rocket.handshake().expect("Failed to handshake");

        rocket.stream.set_nonblocking(true);

        Ok(rocket)
    }

    pub fn get_track(&mut self, track: &str) {
        let mut buf = vec![2];
        buf.write_u32::<BigEndian>(track.len() as u32);
        buf.extend_from_slice(&track.as_bytes());
        self.stream.write(&buf).unwrap();
    }

    pub fn set_row(&mut self, row: u32) {
        let mut buf = vec![3];
        buf.write_u32::<BigEndian>(row);
        self.stream.write(&buf).unwrap();
    }

    pub fn poll_events(&mut self) {
        match self.state {
            RocketState::NewCommand => {
                let mut buf = [0;1];
                if let Ok(_) = self.stream.read_exact(&mut buf) {
                    self.cmd.extend_from_slice(&buf);
                    match self.cmd[0] {
                        0 => self.state = RocketState::IncompleteCommand(4+4+4+1), //SET_KEY
                        1 => self.state = RocketState::IncompleteCommand(4+4), //DELETE_KEY
                        3 => self.state = RocketState::IncompleteCommand(4), //SET_ROW
                        4 => self.state = RocketState::IncompleteCommand(1), //PAUSE
                        5 => self.state = RocketState::CompleteCommand, //SAVE_TRACKS
                        _ => self.state = RocketState::CompleteCommand,
                    }
                }
            },
            RocketState::IncompleteCommand(bytes) => {
                let mut buf = vec![0;bytes];
                if let Ok(bytes_read) = self.stream.read(&mut buf) {
                    self.cmd.extend_from_slice(&buf);
                    if bytes-bytes_read > 0 {
                        self.state = RocketState::IncompleteCommand(bytes-bytes_read);
                    } else {
                        self.state = RocketState::CompleteCommand;
                    }
                }
            },
            RocketState::CompleteCommand => {
                {
                    let mut cursor = Cursor::new(&self.cmd);
                    let cmd = cursor.read_u8().unwrap();
                    match cmd {
                        0 => {
                            let track = cursor.read_u32::<BigEndian>().unwrap();
                            let row = cursor.read_u32::<BigEndian>().unwrap();
                            let value = cursor.read_f32::<BigEndian>().unwrap();
                            let interpolation = cursor.read_u8().unwrap();
                                // 0 == step
                                // 1 == linear
                                // 2 == smooth
                                // 3 == ramp
                            println!("SET_KEY (track: {:?}) (row: {:?}) (value: {:?}) (interpolation: {:?})", track, row, value, interpolation);
                        },
                        1 => {
                            let track = cursor.read_u32::<BigEndian>().unwrap();
                            let row = cursor.read_u32::<BigEndian>().unwrap();
                            println!("DELETE_KEY (track: {:?}) (row: {:?})", track, row);
                        },
                        3 => {
                            let row = cursor.read_u32::<BigEndian>().unwrap();
                            println!("SET_ROW (row: {:?})", row);
                        },
                        4 => {
                            let flag = cursor.read_u8().unwrap();
                                // 0 or 1
                            println!("PAUSE {:?}", flag);
                        },
                        5 => {
                            println!("SAVE_TRACKS");
                        },
                        _ => println!("Unknown {:?}", cmd),
                    }
                }

                self.cmd.clear();
                self.state = RocketState::NewCommand;
            },
        }
    }

    fn handshake(&mut self) -> Result<(), RocketErr> {
        let client_greeting = "hello, synctracker!";
        let server_greeting = "hello, demo!";

        self.stream.write(client_greeting.as_bytes()).expect("Failed to write client greeting");
        let mut buf = [0;12];
        self.stream.read_exact(&mut buf).expect("Failed to read server greeting");
        let read_greeting = std::str::from_utf8(&buf).expect("Failed to convert buf to utf8");
        if read_greeting == server_greeting {
            Ok(())
        } else {
            Err(RocketErr{})
        }
    }
}

fn main() {
    let mut rocket = Rocket::new().unwrap();
    rocket.get_track("test");
    rocket.get_track("test2");
    rocket.get_track("a:test2");
    rocket.set_row(5);

    loop {
        rocket.poll_events();
        std::thread::sleep_ms(1);
    }
    println!("Hello, world!");
}
<commit_msg>Fix warnings<commit_after>extern crate byteorder;

use std::io::Cursor;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use std::io::prelude::*;
use std::net::TcpStream;

#[derive(Copy, Clone, Debug)]
struct RocketErr {
}

enum RocketState {
    NewCommand,
    IncompleteCommand(usize),
    CompleteCommand,
}

struct Rocket {
    stream: TcpStream,
    state: RocketState,
    cmd: Vec<u8>,
}

impl Rocket {
    pub fn new() -> Result<Rocket, RocketErr> {
        Rocket::connect("localhost", 1338)
    }

    pub fn connect(host: &str, port: u16) -> Result<Rocket, RocketErr> {
        let stream = TcpStream::connect((host, port)).expect("Failed to connect");

        let mut rocket = Rocket {
            stream: stream,
            state: RocketState::NewCommand,
            cmd: vec![],
        };

        rocket.handshake().expect("Failed to handshake");

        rocket.stream.set_nonblocking(true).unwrap();

        Ok(rocket)
    }

    pub fn get_track(&mut self, track: &str) {
        let mut buf = vec![2];
        buf.write_u32::<BigEndian>(track.len() as u32).unwrap();
        buf.extend_from_slice(&track.as_bytes());
        self.stream.write(&buf).unwrap();
    }

    pub fn set_row(&mut self, row: u32) {
        let mut buf = vec![3];
        buf.write_u32::<BigEndian>(row).unwrap();
        self.stream.write(&buf).unwrap();
    }

    pub fn poll_events(&mut self) {
        match self.state {
            RocketState::NewCommand => {
                let mut buf = [0;1];
                if let Ok(_) = self.stream.read_exact(&mut buf) {
                    self.cmd.extend_from_slice(&buf);
                    match self.cmd[0] {
                        0 => self.state = RocketState::IncompleteCommand(4+4+4+1), //SET_KEY
                        1 => self.state = RocketState::IncompleteCommand(4+4), //DELETE_KEY
                        3 => self.state = RocketState::IncompleteCommand(4), //SET_ROW
                        4 => self.state = RocketState::IncompleteCommand(1), //PAUSE
                        5 => self.state = RocketState::CompleteCommand, //SAVE_TRACKS
                        _ => self.state = RocketState::CompleteCommand,
                    }
                }
            },
            RocketState::IncompleteCommand(bytes) => {
                let mut buf = vec![0;bytes];
                if let Ok(bytes_read) = self.stream.read(&mut buf) {
                    self.cmd.extend_from_slice(&buf);
                    if bytes-bytes_read > 0 {
                        self.state = RocketState::IncompleteCommand(bytes-bytes_read);
                    } else {
                        self.state = RocketState::CompleteCommand;
                    }
                }
            },
            RocketState::CompleteCommand => {
                {
                    let mut cursor = Cursor::new(&self.cmd);
                    let cmd = cursor.read_u8().unwrap();
                    match cmd {
                        0 => {
                            let track = cursor.read_u32::<BigEndian>().unwrap();
                            let row = cursor.read_u32::<BigEndian>().unwrap();
                            let value = cursor.read_f32::<BigEndian>().unwrap();
                            let interpolation = cursor.read_u8().unwrap();
                                // 0 == step
                                // 1 == linear
                                // 2 == smooth
                                // 3 == ramp
                            println!("SET_KEY (track: {:?}) (row: {:?}) (value: {:?}) (interpolation: {:?})", track, row, value, interpolation);
                        },
                        1 => {
                            let track = cursor.read_u32::<BigEndian>().unwrap();
                            let row = cursor.read_u32::<BigEndian>().unwrap();
                            println!("DELETE_KEY (track: {:?}) (row: {:?})", track, row);
                        },
                        3 => {
                            let row = cursor.read_u32::<BigEndian>().unwrap();
                            println!("SET_ROW (row: {:?})", row);
                        },
                        4 => {
                            let flag = cursor.read_u8().unwrap();
                                // 0 or 1
                            println!("PAUSE {:?}", flag);
                        },
                        5 => {
                            println!("SAVE_TRACKS");
                        },
                        _ => println!("Unknown {:?}", cmd),
                    }
                }

                self.cmd.clear();
                self.state = RocketState::NewCommand;
            },
        }
    }

    fn handshake(&mut self) -> Result<(), RocketErr> {
        let client_greeting = "hello, synctracker!";
        let server_greeting = "hello, demo!";

        self.stream.write(client_greeting.as_bytes()).expect("Failed to write client greeting");
        let mut buf = [0;12];
        self.stream.read_exact(&mut buf).expect("Failed to read server greeting");
        let read_greeting = std::str::from_utf8(&buf).expect("Failed to convert buf to utf8");
        if read_greeting == server_greeting {
            Ok(())
        } else {
            Err(RocketErr{})
        }
    }
}

fn main() {
    let mut rocket = Rocket::new().unwrap();
    rocket.get_track("test");
    rocket.get_track("test2");
    rocket.get_track("a:test2");
    rocket.set_row(5);

    loop {
        rocket.poll_events();
        std::thread::sleep_ms(1);
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2017, 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: MPL-2.0
//

#[macro_use]
extern crate log;
extern crate stderrlog;
#[macro_use]
extern crate structopt;
extern crate updatehub;

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(
    name = "updatehub",
    author = "O.S. Systems Software LTDA. <contact@ossystems.com.br>",
    about = "A generic and safe Firmware Over-The-Air agent."
)]
#[structopt(raw(version = "updatehub::version()"))]
struct Opt {
    /// Increase the verboseness level
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: usize,
}

fn run() -> updatehub::Result<()> {
    let opt = Opt::from_args();

    stderrlog::new().verbosity(opt.verbose + 1).init()?;

    info!("Starting UpdateHub Agent {}", updatehub::version());

    let settings = updatehub::Settings::load()?;
    Ok(updatehub::run(settings)?)
}

fn main() {
    if let Err(ref e) = run() {
        error!("{}", e);
        e.iter_causes()
            .skip(1)
            .for_each(|e| error!(" caused by: {}\n", e));

        std::process::exit(1);
    }
}
<commit_msg>main: Use unit literal when returning on `run()`<commit_after>// Copyright (C) 2017, 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: MPL-2.0
//

#[macro_use]
extern crate log;
extern crate stderrlog;
#[macro_use]
extern crate structopt;
extern crate updatehub;

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(
    name = "updatehub",
    author = "O.S. Systems Software LTDA. <contact@ossystems.com.br>",
    about = "A generic and safe Firmware Over-The-Air agent."
)]
#[structopt(raw(version = "updatehub::version()"))]
struct Opt {
    /// Increase the verboseness level
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: usize,
}

fn run() -> updatehub::Result<()> {
    let opt = Opt::from_args();

    stderrlog::new().verbosity(opt.verbose + 1).init()?;

    info!("Starting UpdateHub Agent {}", updatehub::version());

    let settings = updatehub::Settings::load()?;
    updatehub::run(settings)?;

    Ok(())
}

fn main() {
    if let Err(ref e) = run() {
        error!("{}", e);
        e.iter_causes()
            .skip(1)
            .for_each(|e| error!(" caused by: {}\n", e));

        std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>extern crate toml;

#[cfg(not(test))]
fn main() {
    let home_dir_bin = get_ship_dir();
    let target_name = build_target_name();

    let args = vec!["test".to_owned()];
    let test_exit_status = run_command("cargo".to_owned(), args);
    if !test_exit_status.success() {
        println!("Stopping ship due to tests.");
        exit_with_code(test_exit_status.code());
    }

    let build_args = vec!["build".to_owned(), "--release".to_owned()];
    let build_exit_status = run_command("cargo".to_owned(), build_args);
    if !build_exit_status.success() {
        println!("Stopping ship due to compilation error.");
        exit_with_code(build_exit_status.code());
    }

    let cp_args = vec![target_name, home_dir_bin];
    println!("copying {} to {}", cp_args[0], cp_args[1]);
    run_command("cp".to_owned(), cp_args);
}

#[cfg(not(test))]
fn build_target_name() -> String {
    let value = read_cargo_config();
    let release_name = value.lookup("release.name");
    let default_name = value.lookup("package.name");
    "./target/release/".to_owned() + release_name.or(default_name).expect("unable to determine target name").as_str().unwrap()
}

#[cfg(not(test))]
fn get_ship_dir() -> String {
    use std::env;
    env::home_dir().expect("unable to determine publish directory").to_str().unwrap().to_owned() + "/.bin/"
}

#[cfg(not(test))]
fn read_cargo_config() -> toml::Value {
    use std::io::prelude::*;
    use std::fs::File;

    let mut f = File::open("Cargo.toml").unwrap();
    let mut toml = String::new();
    f.read_to_string(&mut toml).ok();

    //toml::Parser::new(&toml).parse().unwrap()
    toml.parse().unwrap()
}

#[cfg(not(test))]
fn exit_with_code(code: Option<i32>) {
    use std::process::{self};
    process::exit(code.unwrap_or(0));
}

#[cfg(not(test))]
fn run_command(command: String, args: Vec<String>) -> std::process::ExitStatus {
    use std::process::{Command};

    let mut command = Command::new(command);
    command.args(&args);
    let mut child = command.spawn().unwrap_or_else(|e| panic!("{}", e));
    child.wait().unwrap_or_else(|e| panic!("{}", e))
}
<commit_msg>fix: use the bin name if it exists<commit_after>extern crate toml;

#[cfg(not(test))]
fn main() {
    let home_dir_bin = get_ship_dir();
    let target_name = build_target_name();

    let args = vec!["test".to_owned()];
    let test_exit_status = run_command("cargo".to_owned(), args);
    if !test_exit_status.success() {
        println!("Stopping ship due to tests.");
        exit_with_code(test_exit_status.code());
    }

    let build_args = vec!["build".to_owned(), "--release".to_owned()];
    let build_exit_status = run_command("cargo".to_owned(), build_args);
    if !build_exit_status.success() {
        println!("Stopping ship due to compilation error.");
        exit_with_code(build_exit_status.code());
    }

    let cp_args = vec![target_name, home_dir_bin];
    println!("copying {} to {}", cp_args[0], cp_args[1]);
    run_command("cp".to_owned(), cp_args);
}

#[cfg(not(test))]
fn build_target_name() -> String {
    let value = read_cargo_config();
    let binary_name  = value.lookup("bin.0.name");
    let release_name = value.lookup("release.name");
    let default_name = value.lookup("package.name");
    "./target/release/".to_owned() + binary_name.or(release_name).or(default_name).expect("unable to determine target name").as_str().unwrap()
}

#[cfg(not(test))]
fn get_ship_dir() -> String {
    use std::env;
    env::home_dir().expect("unable to determine publish directory").to_str().unwrap().to_owned() + "/.bin/"
}

#[cfg(not(test))]
fn read_cargo_config() -> toml::Value {
    use std::io::prelude::*;
    use std::fs::File;

    let mut f = File::open("Cargo.toml").unwrap();
    let mut toml = String::new();
    f.read_to_string(&mut toml).ok();

    //toml::Parser::new(&toml).parse().unwrap()
    toml.parse().unwrap()
}

#[cfg(not(test))]
fn exit_with_code(code: Option<i32>) {
    use std::process::{self};
    process::exit(code.unwrap_or(0));
}

#[cfg(not(test))]
fn run_command(command: String, args: Vec<String>) -> std::process::ExitStatus {
    use std::process::{Command};

    let mut command = Command::new(command);
    command.args(&args);
    let mut child = command.spawn().unwrap_or_else(|e| panic!("{}", e));
    child.wait().unwrap_or_else(|e| panic!("{}", e))
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate docopt;

use docopt::Docopt;

use std::net::{TcpListener, TcpStream, SocketAddr};
use std::thread;
use std::io::{BufRead, BufReader};

const USAGE: &'static str = "
Snooper

Usage:
  snooper [--ip <ip> --port <port>]

Options:
  -h --help          Show this screen.
  --version          Show version.
  --ip=<addr>   Network address to bind to [default: 127.0.0.1]
  --port=<port>  Port to bind to [default: 3128]
";

#[derive(RustcDecodable)]
struct Args {
  flag_port: u16,
  flag_ip: String,
}

fn main() {

  let args: Args = Docopt::new(USAGE)
    .and_then(|dopt| dopt.decode())
    .unwrap_or_else(|e| e.exit());

  let bind_address = format!("{}:{}", args.flag_ip, args.flag_port);
  let listener = TcpListener::bind(&*bind_address).unwrap();

  println!("Snooper has started and is bound to: {}", bind_address);

  fn handle_client(stream: TcpStream) {
    let lines = BufReader::new(stream.try_clone().unwrap()).lines();
    for line in lines {
      match line {
        Ok(text) => { println!("Received: {}", text) }
        Err(_) => { println!("Ohhhhhhh SHIT!!!!") }
      }
    }
	}

	// accept connections and process them, spawning a new thread for each one TODO: Update to metal IO event notifier
	for stream in listener.incoming() {
	  match stream {
      Ok(stream) => {
        match stream.peer_addr() {
          Ok(socket_addr) => {
            match socket_addr {
              SocketAddr::V4(ipv_4_socket) => {
                println!("New connection using IPv4 from: ip: {}, port: {}", ipv_4_socket.ip(), ipv_4_socket.port())
              }
              SocketAddr::V6(ipv_6_socket) => {
                println!("New connection using IPv6 from ip {} on poer {}", ipv_6_socket.ip(), ipv_6_socket.port())
              }
            }
          }
          Err(_) => panic!("Oh dear")
        };
        thread::spawn(move|| {
            // connection succeeded
            handle_client(stream)
        });
      }
      Err(e) => {
        println!("Shit be fooked!: {}", e)
      }
	  }
	}

	// close the socket server
	drop(listener);
}
<commit_msg>fix formatting<commit_after>extern crate rustc_serialize;
extern crate docopt;

use docopt::Docopt;

use std::net::{TcpListener, TcpStream, SocketAddr};
use std::thread;
use std::io::{BufRead, BufReader};

const USAGE: &'static str = "
Snooper

Usage:
  snooper [--ip <ip> --port <port>]

Options:
  -h --help          Show this screen.
  --version          Show version.
  --ip=<addr>   Network address to bind to [default: 127.0.0.1]
  --port=<port>  Port to bind to [default: 3128]
";

#[derive(RustcDecodable)]
struct Args {
  flag_port: u16,
  flag_ip: String,
}

fn main() {

  let args: Args = Docopt::new(USAGE)
    .and_then(|dopt| dopt.decode())
    .unwrap_or_else(|e| e.exit());

  let bind_address = format!("{}:{}", args.flag_ip, args.flag_port);
  let listener = TcpListener::bind(&*bind_address).unwrap();

  println!("Snooper has started and is bound to: {}", bind_address);

  fn handle_client(stream: TcpStream) {
    let lines = BufReader::new(stream.try_clone().unwrap()).lines();
    for line in lines {
      match line {
        Ok(text) => { println!("Received: {}", text) }
        Err(_) => { println!("Ohhhhhhh SHIT!!!!") }
      }
    }
  }

  // accept connections and process them, spawning a new thread for each one TODO: Update to metal IO event notifier
  for stream in listener.incoming() {
    match stream {
      Ok(stream) => {
        match stream.peer_addr() {
          Ok(socket_addr) => {
            match socket_addr {
              SocketAddr::V4(ipv_4_socket) => {
                println!("New connection using IPv4 from: ip: {}, port: {}", ipv_4_socket.ip(), ipv_4_socket.port())
              }
              SocketAddr::V6(ipv_6_socket) => {
                println!("New connection using IPv6 from ip {} on poer {}", ipv_6_socket.ip(), ipv_6_socket.port())
              }
            }
          }
          Err(_) => panic!("Oh dear")
        };
        thread::spawn(move|| {
            // connection succeeded
            handle_client(stream)
        });
      }
      Err(e) => {
        println!("Shit be fooked!: {}", e)
      }
    }
  }

  // close the socket server
  drop(listener);
}
<|endoftext|>