<commit_before>#![feature(slice_patterns)]
#[macro_use]
extern crate nom;

use nom::{IResult, eof};
use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::thread;

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

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

use Op::*;

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

impl OpStream {
    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);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [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;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }

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

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 fs::File::open(filename)
                  .map(|f| io::BufReader::new(f))
                  .and_then(|mut reader| {
                      let mut buffer = Vec::new();
                      reader.read_to_end(&mut buffer).map(|_| buffer)
                  })
                  .map_err(|e| format!("{}", e))
                  .and_then(|buffer| {
                      match bf_parse_file(&buffer[..]) {
                          IResult::Done(_, o) => Ok(o),
                          IResult::Error(e) => Err(format!("Parsing error: {:?}", e)),
                          IResult::Incomplete(m) => Err(format!("Incomplete file: {:?}", m)),
                      }
                  }) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                opstream.optimize();
                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(),
                         "Error while processing {}: {}",
                         filename,
                         e)
                    .unwrap();
            }
        }
    }
}

named!(bf_parse_file<&[u8], Vec<Op> >, chain!(ops: bf_parse ~ eof, || ops));
named!(bf_parse<&[u8], Vec<Op> >,
    many0!(
        chain!(
            opt!(is_not!("+-<>.,[]")) ~
            op: alt!(
                chain!(tag!("+"), || Add(0x01)) |
                chain!(tag!("-"), || Add(0xff)) |
                chain!(tag!(">"), || Mov(1)) |
                chain!(tag!("<"), || Mov(-1)) |
                chain!(tag!("."), || Out) |
                chain!(tag!(","), || In) |
                chain!(subops: delimited!(tag!("["), bf_parse, tag!("]")), || Loop(OpStream { ops: subops }))
            ) ~
            opt!(is_not!("+-<>.,[]")), || op)
        )
    );

#[cfg(test)]
mod tests {
    use nom::IResult::Done;
    use super::{bf_parse_file, State, OpStream};
    use super::Op::*;

    #[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_optimize() {
        let mut opstream = OpStream {
            ops: vec![Mov(1),
                      Mov(1),
                      Add(0x01),
                      Add(0x0ff),
                      Add(0x0ff),
                      Mov(1),
                      Mov(-1),
                      Loop(OpStream { ops: vec![Mov(2), Mov(3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] })] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream {
            ops: vec![Loop(OpStream { ops: vec![Add(0x01), Mov(3), Add(0xff), Mov(-3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Transfer(1, vec![(3, 255)])] });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(bf_parse_file(&input[..]),
                   Done(&b""[..],
                        vec![Add(0x01),
                             Add(0xff),
                             Loop(OpStream { ops: vec![Add(1), Out, In] }),
                             Add(0x01)]));
    }
}
<commit_msg>refactor: mark unreachable case, remove unused initializer<commit_after>#![feature(slice_patterns)]
#[macro_use]
extern crate nom;

use nom::{IResult, eof};
use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::thread;

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

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

use Op::*;

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

impl OpStream {
    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);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [Loop(_), ..] => {
                    let maybe_new_op;

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

                    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;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }

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

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 fs::File::open(filename)
                  .map(|f| io::BufReader::new(f))
                  .and_then(|mut reader| {
                      let mut buffer = Vec::new();
                      reader.read_to_end(&mut buffer).map(|_| buffer)
                  })
                  .map_err(|e| format!("{}", e))
                  .and_then(|buffer| {
                      match bf_parse_file(&buffer[..]) {
                          IResult::Done(_, o) => Ok(o),
                          IResult::Error(e) => Err(format!("Parsing error: {:?}", e)),
                          IResult::Incomplete(m) => Err(format!("Incomplete file: {:?}", m)),
                      }
                  }) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                opstream.optimize();
                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(),
                         "Error while processing {}: {}",
                         filename,
                         e)
                    .unwrap();
            }
        }
    }
}

named!(bf_parse_file<&[u8], Vec<Op> >, chain!(ops: bf_parse ~ eof, || ops));
named!(bf_parse<&[u8], Vec<Op> >,
    many0!(
        chain!(
            opt!(is_not!("+-<>.,[]")) ~
            op: alt!(
                chain!(tag!("+"), || Add(0x01)) |
                chain!(tag!("-"), || Add(0xff)) |
                chain!(tag!(">"), || Mov(1)) |
                chain!(tag!("<"), || Mov(-1)) |
                chain!(tag!("."), || Out) |
                chain!(tag!(","), || In) |
                chain!(subops: delimited!(tag!("["), bf_parse, tag!("]")), || Loop(OpStream { ops: subops }))
            ) ~
            opt!(is_not!("+-<>.,[]")), || op)
        )
    );

#[cfg(test)]
mod tests {
    use nom::IResult::Done;
    use super::{bf_parse_file, State, OpStream};
    use super::Op::*;

    #[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_optimize() {
        let mut opstream = OpStream {
            ops: vec![Mov(1),
                      Mov(1),
                      Add(0x01),
                      Add(0x0ff),
                      Add(0x0ff),
                      Mov(1),
                      Mov(-1),
                      Loop(OpStream { ops: vec![Mov(2), Mov(3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] })] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream {
            ops: vec![Loop(OpStream { ops: vec![Add(0x01), Mov(3), Add(0xff), Mov(-3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Transfer(1, vec![(3, 255)])] });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(bf_parse_file(&input[..]),
                   Done(&b""[..],
                        vec![Add(0x01),
                             Add(0xff),
                             Loop(OpStream { ops: vec![Add(1), Out, In] }),
                             Add(0x01)]));
    }
}
<|endoftext|>


<commit_before>// #![feature(plugin)]
// #![plugin(clippy)]
// #![deny(clippy)]

extern crate rustc_serialize;
extern crate docopt;

mod cli;
mod yaml;
mod rules;

#[warn(unused_imports)]
use std::io::prelude::*;
use std::io::{self};
use std::fs::File;

use cli::*;

use docopt::Docopt;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USAGE: &'static str = "
Funzzy the watcher.

Usage:
  funzzy
  funzzy <command>
  funzzy watch [--verbose]
  funzzy watch [--verbose | -c | -s] <command>
  funzzy init
  funzzy run [--verbose] <command> <interval>
  funzzy [options]

Options:
  run               Execute command in a given interval (seconds)
  -h --help         Shows this message.
  -v --version      Shows version.
  --verbose         Use verbose output.
  -c                Execute given command for current folder.
";

#[derive(Debug, RustcDecodable)]
pub struct Args {
    // comand
    pub cmd_init: bool,
    pub cmd_watch: bool,
    pub cmd_run: bool,

    pub arg_command: String,
    pub arg_interval: u64,

    // options
    pub flag_c: bool,
    pub flag_h: bool,
    pub flag_v: bool,
    pub flag_verbose: bool,
}

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

    match args {
        // Metainfo
        Args { flag_v: true, .. } => show(VERSION),
        Args { flag_h: true, .. } => show(USAGE),

        // Commands
        Args { cmd_init: true, .. } =>
            execute(InitCommand::new(cli::watch::DEFAULT_FILENAME)),

        Args { cmd_run: true, .. } =>
            execute(RunCommand::new(args.arg_command, args.arg_interval)),

        Args { cmd_watch: true, flag_c: true, .. } => {
            let watches = Watches::from_args(args.arg_command);
            execute(WatchCommand::new(watches, args.flag_verbose))
        },

        Args { ref arg_command,.. } if !arg_command.is_empty() => {
            match from_stdin() {
                Some(content) => {
                   let watches = Watches::new(rules::from_string(content, arg_command));
                   execute(WatchCommand::new(watches, args.flag_verbose));
                },
                None => show("Nothing to run")
            };
        },

        _ => {
            let watches = Watches::from(&from_file());
            execute(WatchCommand::new(watches, args.flag_verbose));
        }
    }
}

fn execute<T: Command>(command: T) {
    if let Err(err) = command.execute() {
        println!("Error: {}", err);
    }
}

fn from_stdin() -> Option<String> {
    let mut buffer = String::new();
    let mut stdin = io::stdin();

    match stdin.read_to_string(&mut buffer) {
        Ok(bytes) => if bytes > 0 { Some(buffer) } else { None },
        Err(err) => panic!("Error while reading stdin {}", err)
    }
}

fn from_file() -> String {
    let mut file = match File::open(cli::watch::DEFAULT_FILENAME) {
        Ok(f) => f,
        Err(err) => show(format!("File {} cannot be opened. Cause: {}",
                         cli::watch::DEFAULT_FILENAME,
                         err).as_str()),
    };

    let mut content = String::new();
    if let Err(err) = file.read_to_string(&mut content) {
        panic!("Error while trying read file. {}",err);
    }

    content
}

fn show(text: &str) -> ! {
    println!("{}", text);
    std::process::exit(0)
}

<commit_msg>fix: avoid break on init command   fixes #33<commit_after>// #![feature(plugin)]
// #![plugin(clippy)]
// #![deny(clippy)]

extern crate rustc_serialize;
extern crate docopt;

mod cli;
mod yaml;
mod rules;

#[warn(unused_imports)]
use std::io::prelude::*;
use std::io::{self};
use std::fs::File;

use cli::*;

use docopt::Docopt;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USAGE: &'static str = "
Funzzy the watcher.

Usage:
  funzzy
  funzzy init
  funzzy <command>
  funzzy watch [--verbose]
  funzzy watch [--verbose | -c | -s] <command>
  funzzy run [--verbose] <command> <interval>
  funzzy [options]

Options:
  run               Execute command in a given interval (seconds)
  -h --help         Shows this message.
  -v --version      Shows version.
  --verbose         Use verbose output.
  -c                Execute given command for current folder.
";

#[derive(Debug, RustcDecodable)]
pub struct Args {
    // comand
    pub cmd_init: bool,
    pub cmd_watch: bool,
    pub cmd_run: bool,

    pub arg_command: String,
    pub arg_interval: u64,

    // options
    pub flag_c: bool,
    pub flag_h: bool,
    pub flag_v: bool,
    pub flag_verbose: bool,
}

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

    println!("{:?}", args);

    match args {
        // Metainfo
        Args { flag_v: true, .. } => show(VERSION),
        Args { flag_h: true, .. } => show(USAGE),

        // Commands
        Args { cmd_init: true, .. } =>
            execute(InitCommand::new(cli::watch::DEFAULT_FILENAME)),

        Args { cmd_run: true, .. } =>
            execute(RunCommand::new(args.arg_command, args.arg_interval)),

        Args { cmd_watch: true, flag_c: true, .. } => {
            let watches = Watches::from_args(args.arg_command);
            execute(WatchCommand::new(watches, args.flag_verbose))
        },

        Args { ref arg_command,.. } if !arg_command.is_empty() => {
            match from_stdin() {
                Some(content) => {
                   let watches = Watches::new(rules::from_string(content, arg_command));
                   execute(WatchCommand::new(watches, args.flag_verbose));
                },
                None => show("Nothing to run")
            };
        },

        _ => {
            let watches = Watches::from(&from_file());
            execute(WatchCommand::new(watches, args.flag_verbose));
        }
    }
}

fn execute<T: Command>(command: T) {
    if let Err(err) = command.execute() {
        println!("Error: {}", err);
    }
}

fn from_stdin() -> Option<String> {
    let mut buffer = String::new();
    let mut stdin = io::stdin();

    match stdin.read_to_string(&mut buffer) {
        Ok(bytes) => if bytes > 0 { Some(buffer) } else { None },
        Err(err) => panic!("Error while reading stdin {}", err)
    }
}

fn from_file() -> String {
    let mut file = match File::open(cli::watch::DEFAULT_FILENAME) {
        Ok(f) => f,
        Err(err) => show(format!("File {} cannot be opened. Cause: {}",
                         cli::watch::DEFAULT_FILENAME,
                         err).as_str()),
    };

    let mut content = String::new();
    if let Err(err) = file.read_to_string(&mut content) {
        panic!("Error while trying read file. {}",err);
    }

    content
}

fn show(text: &str) -> ! {
    println!("{}", text);
    std::process::exit(0)
}

<|endoftext|>


<commit_before>#![feature(libc)]
extern crate libc;
use std::ffi;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::interface::*;
use rustwlc::input::pointer;
use rustwlc::input::keyboard;
/*
struct CompositorAction {
    view: WlcView,
    grab: Point,
    edges: u32
}

static mut compositor: CompositorAction = CompositorAction {
    view: WlcView(0),
    grab: Point{ x: 0, y: 0},
    edges: 0
};
*/
fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: output_created,
            destroyed: output_destroyed,
            focus: output_focus,
            resolution: output_resolution,

            render: OutputRenderInterface {
                pre: output_render_pre,
                post: output_render_post
            }
        },
        view: ViewInterface {
            created: view_created,
            destroyed: view_destroyed,
            focus: view_focus,
            move_to_output: view_move_to_output,
            request: RequestInterface {
                geometry: view_request_geometry,
                state: view_request_state,
                move_: view_request_move,
                resize: view_request_resize,
                render: ViewRenderInterface {
                    pre: view_request_render_pre,
                    post: view_request_render_post
                }
            }
        },
        keyboard: KeyboardInterface {
            key: keyboard_key
        },
        pointer: PointerInterface {
            button: pointer_button,
            scroll: pointer_scroll,
            motion: pointer_motion
        },
        touch: TouchInterface {
            touch: touch_touch
        },
        compositor: CompositorInterface {
            ready: compositor_ready
        },
        input: InputInterface {
            created: input_created,
            destroyed: input_destroyed
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);
    rustwlc::log_set_handler(log_callback);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

extern fn log_callback(log_type: LogType, text: *const libc::c_char) {
    let string_text = rustwlc::pointer_to_string(text);
    println!("Wlc Log: {}", string_text);
}

// Important rendering functions copied from wlc/example/example.c

fn start_interactive_action(view: WlcView, origin: Point) -> bool {
    true
}

fn stop_interactive_action() {

}

fn start_interactive_move(view: WlcView, origin: Point) {

}

fn start_interactive_resize(view: WlcView, edges: u32, origin: Point) {

}

fn get_topmost_view(output: WlcOutput, offset: Size) {

}

/// From example.c:
/// very simple layout function
/// you probably don't want to layout certain type of windows in wm
fn render_output(output: WlcOutput) {
    use std::cmp;
    let resolution = output.get_resolution();
    let views = output.get_views();

    if views.len() == 0 { println!("Didn't find any views to render :/"); }

    for view in views {
        view.set_geometry(0,
                          Geometry {
                              size: Size {
                                  w: resolution.w as u32,
                                  h: resolution.h as u32
                              },
                              origin: Point {
                                  x: resolution.w as i32,
                                  y: resolution.h as i32
                              }
                          });
    }

    /*
    let mut toggle = false;
    let mut y = 0u32;
//    use std::cmp;

    let w: u32 = resolution.w as u32 / 2u32;
    let h: u32 = resolution.h as u32 / cmp::max((1u32 + views.len() as u32) / 2u32, 1);

    for view in views {
        let g = Geometry {
            size: Size {
                w: if toggle { w } else { 0 },
                h: y
            },
            origin: Point {
                x: if !toggle { resolution.w as i32 } else { w as i32 },
                y: h as i32
            }
        };
        view.set_geometry(0, g);
        toggle = !toggle;
        y = y + if !toggle { h } else { 0 };
    }*/
}

// Hook up basic callbacks

extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(output: WlcOutput, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}", view);
    let output = view.get_output();
    println!("view_created: it's on output {:?}", output);
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    render_output(output);
    true
}

extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
    render_output(view.get_output());
}

extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(ViewState::Activated, focused);
}

extern fn view_move_to_output(current: WlcView, q1: WlcView, q2: WlcView) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, q1, q2);
}

extern fn view_request_geometry(view: WlcView, geometry: Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(0, geometry);
    render_output(view.get_output());
}

extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
    view.set_state(state, handled);
}

extern fn view_request_move(view: WlcView, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(view: WlcView, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(view: WlcView) {
    //println!("view_request_render_pre");
}

extern fn view_request_render_post(view: WlcView) {
    //println!("view_request_render_post");
}

extern fn keyboard_key(view: WlcView, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    use std::process::{Command};
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, mods, key, state);
    if state == KeyState::Pressed { return false; }
    println!("Preparing to open the terminal...");
    rustwlc::exec("weston-terminal".to_string(), vec!["weston-terminal".to_string()]);
    // We are definitely able to open programs, they can definitely launch in the host X11 server.
    //rustwlc::exec("emacs".to_string(), vec!["emacs".to_string()]);
    //let output = std::process::Command::new("weston-terminal").output()
    //.unwrap_or_else(|e| { println!("Could not unwrap output!"); panic!("aaaa") });
    let mut child = Command::new("/bin/weston-terminal").spawn()
        .unwrap_or_else(|e| { println!("Error spawning child: {}", e); panic!("1") });

    //let ecode = child.wait().unwrap_or_else(|e| println!("Error unwrapping child"));
    //println!("Output: {}", String::from_utf8(output.stdout).unwrap_or("nope".to_string()));

    false
}

extern fn pointer_button(view: WlcView, button: libc::c_uint, mods: KeyboardModifiers,
                  key: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: key {}, point {}", key, point);

    if state == ButtonState::Pressed {
        view.focus();
    }
    false
}

extern fn pointer_scroll(view: WlcView, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(view: WlcView, time: u32, point: Point) {
    //println!("Pointer moved {} to {}", time, point);
    // TODO wlc_pointer_set_position
    pointer::set_position(point);
}

extern fn touch_touch(view: WlcView, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<commit_msg>Updated way cooler interface to use optional callbacks<commit_after>#![feature(libc)]
extern crate libc;
use std::ffi;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::interface::*;
use rustwlc::input::pointer;
use rustwlc::input::keyboard;
/*
struct CompositorAction {
    view: WlcView,
    grab: Point,
    edges: u32
}

static mut compositor: CompositorAction = CompositorAction {
    view: WlcView(0),
    grab: Point{ x: 0, y: 0},
    edges: 0
};
*/
fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: Some(output_created),
            destroyed: Some(output_destroyed),
            focus: Some(output_focus),
            resolution: Some(output_resolution),

            render: OutputRenderInterface {
                pre: Some(output_render_pre),
                post: Some(output_render_post)
            }
        },
        view: ViewInterface {
            created: Some(view_created),
            destroyed: Some(view_destroyed),
            focus: Some(view_focus),
            move_to_output: Some(view_move_to_output),
            request: RequestInterface {
                geometry: Some(view_request_geometry),
                state: Some(view_request_state),
                move_: Some(view_request_move),
                resize: Some(view_request_resize),
                render: ViewRenderInterface {
                    pre: Some(view_request_render_pre),
                    post: Some(view_request_render_post)
                }
            }
        },
        keyboard: KeyboardInterface {
            key: Some(keyboard_key)
        },
        pointer: PointerInterface {
            button: Some(pointer_button),
            scroll: Some(pointer_scroll),
            motion: Some(pointer_motion)
        },
        touch: TouchInterface {
            touch: Some(touch_touch)
        },
        compositor: CompositorInterface {
            ready: Some(compositor_ready)
        },
        input: InputInterface {
            created: Some(input_created),
            destroyed: Some(input_destroyed)
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);
    rustwlc::log_set_handler(log_callback);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

extern fn log_callback(log_type: LogType, text: *const libc::c_char) {
    let string_text = rustwlc::pointer_to_string(text);
    println!("Wlc Log: {}", string_text);
}

// Important rendering functions copied from wlc/example/example.c

fn start_interactive_action(view: WlcView, origin: Point) -> bool {
    true
}

fn stop_interactive_action() {

}

fn start_interactive_move(view: WlcView, origin: Point) {

}

fn start_interactive_resize(view: WlcView, edges: u32, origin: Point) {

}

fn get_topmost_view(output: WlcOutput, offset: Size) {

}

/// From example.c:
/// very simple layout function
/// you probably don't want to layout certain type of windows in wm
fn render_output(output: WlcOutput) {
    use std::cmp;
    let resolution = output.get_resolution();
    let views = output.get_views();

    if views.len() == 0 { println!("Didn't find any views to render :/"); }

    for view in views {
        view.set_geometry(0,
                          Geometry {
                              size: Size {
                                  w: resolution.w as u32,
                                  h: resolution.h as u32
                              },
                              origin: Point {
                                  x: resolution.w as i32,
                                  y: resolution.h as i32
                              }
                          });
    }

    /*
    let mut toggle = false;
    let mut y = 0u32;
//    use std::cmp;

    let w: u32 = resolution.w as u32 / 2u32;
    let h: u32 = resolution.h as u32 / cmp::max((1u32 + views.len() as u32) / 2u32, 1);

    for view in views {
        let g = Geometry {
            size: Size {
                w: if toggle { w } else { 0 },
                h: y
            },
            origin: Point {
                x: if !toggle { resolution.w as i32 } else { w as i32 },
                y: h as i32
            }
        };
        view.set_geometry(0, g);
        toggle = !toggle;
        y = y + if !toggle { h } else { 0 };
    }*/
}

// Hook up basic callbacks

extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(output: WlcOutput, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}", view);
    let output = view.get_output();
    println!("view_created: it's on output {:?}", output);
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    render_output(output);
    true
}

extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
    render_output(view.get_output());
}

extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(ViewState::Activated, focused);
}

extern fn view_move_to_output(current: WlcView, q1: WlcView, q2: WlcView) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, q1, q2);
}

extern fn view_request_geometry(view: WlcView, geometry: Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(0, geometry);
    render_output(view.get_output());
}

extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
    view.set_state(state, handled);
}

extern fn view_request_move(view: WlcView, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(view: WlcView, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(view: WlcView) {
    //println!("view_request_render_pre");
}

extern fn view_request_render_post(view: WlcView) {
    //println!("view_request_render_post");
}

extern fn keyboard_key(view: WlcView, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    use std::process::{Command};
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, mods, key, state);
    if state == KeyState::Pressed { return false; }
    println!("Preparing to open the terminal...");
    rustwlc::exec("weston-terminal".to_string(), vec!["weston-terminal".to_string()]);
    // We are definitely able to open programs, they can definitely launch in the host X11 server.
    //rustwlc::exec("emacs".to_string(), vec!["emacs".to_string()]);
    //let output = std::process::Command::new("weston-terminal").output()
    //.unwrap_or_else(|e| { println!("Could not unwrap output!"); panic!("aaaa") });
    let mut child = Command::new("/bin/weston-terminal").spawn()
        .unwrap_or_else(|e| { println!("Error spawning child: {}", e); panic!("1") });

    //let ecode = child.wait().unwrap_or_else(|e| println!("Error unwrapping child"));
    //println!("Output: {}", String::from_utf8(output.stdout).unwrap_or("nope".to_string()));

    false
}

extern fn pointer_button(view: WlcView, button: libc::c_uint, mods: KeyboardModifiers,
                  key: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: key {}, point {}", key, point);

    if state == ButtonState::Pressed {
        view.focus();
    }
    false
}

extern fn pointer_scroll(view: WlcView, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(view: WlcView, time: u32, point: Point) {
    //println!("Pointer moved {} to {}", time, point);
    // TODO wlc_pointer_set_position
    pointer::set_position(point);
}

extern fn touch_touch(view: WlcView, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<|endoftext|>


<commit_before>extern crate parser;

use parser::Parser;
use parser::Entry;

use std::fs::File;
use std::io::BufReader;
use std::io::Read;

fn read_file() -> String {
  let file = match File::open("example.l20n") {
      Ok(file) => file,
      Err(..)  => panic!("room"),
  };

  let mut reader = BufReader::new(&file);
  let buffer_string = &mut String::new();
  reader.read_to_string(buffer_string);

  buffer_string.clone()
}

fn main() {
  let source = read_file();
  let mut parser = Parser::new(source.trim());
  let mut entries = parser.parse();

  loop {
    if entries.is_empty() {
      break;
    }
    let entry1 = Some(entries.remove(0));
    let id = match entry1 {
      Some(Entry::Entity{id, value}) => id.clone(),
      None => break
    };

    println!("ID: {}", id);
  }
}
<commit_msg>Use command line param<commit_after>extern crate parser;

use parser::Parser;
use parser::Entry;

use std::fs::File;
use std::io::BufReader;
use std::io::Read;

use std::env;

fn read_file(path: String) -> String {
  let file = match File::open(path) {
      Ok(file) => file,
      Err(..)  => panic!("room"),
  };

  let mut reader = BufReader::new(&file);
  let buffer_string = &mut String::new();
  reader.read_to_string(buffer_string);

  buffer_string.clone()
}

fn print_entities(entries: &mut Vec<Entry>) {
  loop {
    if entries.is_empty() {
      break;
    }
    let entry1 = Some(entries.remove(0));
    let id = match entry1 {
      Some(Entry::Entity{id, value}) => id.clone(),
      None => break
    };

    println!("ID: {}", id);
  }
}

fn main() {
  if let Some(arg1) = env::args().nth(1) {
    let source = read_file(arg1);
    let mut parser = Parser::new(source.trim());
    let mut entries = parser.parse();
    print_entities(&mut entries);
  } else {
    println!("You must pass a path to an l20n file");
    return;
  }
}
<|endoftext|>


<commit_before>
mod genlex;
mod syntax;
mod scanner;

use syntax::Token;

fn main() {

    let mut i = 0;
    for (src,expected) in genlex::new().take(121) {
        i += 1;
        print!("testing source {}: {:?}",i,src);
        let result = scanner::scan(&src);
        if result == expected {
            println!(" ok");
        } else {
            println!(" error");
            println!("expected : {:?}", expected);
            println!("result : {:?}", result);
            break;
        }
    }

}

<commit_msg>a small test about ordered enumeration<commit_after>
mod genlex;
mod syntax;
mod scanner;

use syntax::Token;

fn main() {
    let mut size = 0;
    let mut list = vec!["".to_string()];
    loop {
        match give_one(&mut size, &mut list) {
            Some(s) => println!("{:?}",s),
            None => break
        }
    }
}

fn give_one(size : &mut usize, list : &mut Vec<String>) -> Option<String> {
    loop {
        match list.pop() {
            None => {
                *size += 1;
                list.push("".to_string());
            },
            Some(s) => {
                if s.len() == *size {
                    return Some(s);
                } else if s.len() > *size {
                    continue;
                } else {
                    list.push(s.clone() + "a");
                    list.push(s.clone() + "bbb");
                    continue;
                }
            }
        }
    }
}

fn enum_rec(){
    for n in 0..7 {
        enum_rec_f(n, "".to_string());
    }
}

fn enum_rec_f(n : usize, s : String){
    if n == s.len() {
        println!("{}",s);
        return;
    }
    if n < s.len() {
        return;
    }
    enum_rec_f(n, s.clone() + "a");
    enum_rec_f(n, s.clone() + "bb");
}

fn test() {

    let mut i = 0;
    for (src,expected) in genlex::new().take(121) {
        i += 1;
        print!("testing source {}: {:?}",i,src);
        let result = scanner::scan(&src);
        if result == expected {
            println!(" ok");
        } else {
            println!(" error");
            println!("expected : {:?}", expected);
            println!("result : {:?}", result);
            break;
        }
    }

}

<|endoftext|>


<commit_before>#[macro_use] extern crate nickel;

// use nickel::Nickel;

use std::collections::HashMap;
use nickel::{Nickel, HttpRouter, StaticFilesHandler};

/*
BriqsDBでの'Briq'という概念は、最初はコンスセルの別名に過ぎなかったのだが、
文字列や任意のバイト列をそれで表現したいと思った時に、'128bitの塊'という役割も背負うことになった。
そのせいで、自分の中で混乱が生じているのだ。

果たして、上記のどちらの概念が、よりプリミティブなのか？
*/
trait Piq {
    fn p(&self);
    fn q(&self);
}

/*
ということで、基本はポインタとなる64bitの塊ということにしました。
上記のどちらの概念の間に、あるもの。dominoにこだわるのは、少しやめる感じでしょうか。
*/
struct Omino {
    bytes: [u8; 8]
}

fn main() {
    let mut server = Nickel::new();

    let o = Omino { bytes:[0; 8] };

     /*
     server.utilize(router! {
         get "**" => |_req, _res| {
             "Hello world! Good bye!"
         }
     });
     */

    server.utilize(StaticFilesHandler::new("assets/"));

    server.get("/", middleware! {|_, response|
        let mut data = HashMap::new();
        data.insert("color", "Green");
        data.insert("name", "California Apple");
        data.insert("price", "2.50");
        return response.render("assets/hello.tpl", &data);
    });

     let _ = server.listen("127.0.0.1:6767");
 }
<commit_msg>add Omino initializations<commit_after>#[macro_use] extern crate nickel;

// use nickel::Nickel;

use std::collections::HashMap;
use nickel::{Nickel, HttpRouter, StaticFilesHandler};

/*
BriqsDBでの'Briq'という概念は、最初はコンスセルの別名に過ぎなかったのだが、
文字列や任意のバイト列をそれで表現したいと思った時に、'128bitの塊'という役割も背負うことになった。
そのせいで、自分の中で混乱が生じているのだ。

果たして、上記のどちらの概念が、よりプリミティブなのか？
*/
trait Piq {
    fn p(&self);
    fn q(&self);
}

/*
ということで、基本はポインタとなる64bitの塊ということにしました。
上記のどちらの概念の間に、あるもの。dominoにこだわるのは、少しやめる感じでしょうか。
*/
struct Briq {
    bytes: [u8; 8]
}

struct Omino1 {
    briq: Briq
}

struct Omino2 {
    p: Briq,
    q: Briq,
}

fn main() {
    let mut server = Nickel::new();

    let o1 = Omino1 { briq: Briq { bytes: [0; 8] } };

    let o2 = Omino2 { p: Briq { bytes: [0; 8] }, q: Briq { bytes: [0; 8] } };

     /*
     server.utilize(router! {
         get "**" => |_req, _res| {
             "Hello world! Good bye!"
         }
     });
     */

    server.utilize(StaticFilesHandler::new("assets/"));

    server.get("/", middleware! {|_, response|
        let mut data = HashMap::new();
        data.insert("color", "Green");
        data.insert("name", "California Apple");
        data.insert("price", "2.50");
        return response.render("assets/hello.tpl", &data);
    });

     let _ = server.listen("127.0.0.1:6767");
 }
<|endoftext|>


<commit_before>extern crate argparse;
extern crate env_logger;
extern crate hyper;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serialport;
extern crate websocket;

mod serial_support;

use std::thread;
use std::io::Write;
use std::collections::HashMap;

use argparse::{ArgumentParser, Store};
use websocket::{Server, Message};
use websocket::message::Type;
use hyper::Server as HttpServer;
use hyper::net::Fresh;
use hyper::server::request::Request;
use hyper::server::response::Response;

use serial_support::messages::*;
use serial_support::manage::*;

fn main() {

  // Init logger
  env_logger::init().unwrap();

  // let sr = SerialResponse::Response {
  //     data: "HEY YOU".to_string(),
  //     base64: None,
  // };
  // info!("serialized = {}", serde_json::to_string(&sr).unwrap());

  // Default port number
  let mut port = 8080;
  // Parse cmdline args
  {
    let mut ap = ArgumentParser::new();
    ap.set_description("Provide access to serial ports over JSON Websockets");
    ap.refer(&mut port)
      .add_option(&["-p", "--port"], Store, "Http Port");
    ap.parse_args_or_exit();
  }

  // The HTTP server handler
  let http_handler = move |_: Request, response: Response<Fresh>| {
    let mut response = response.start().unwrap();
    // Send a client webpage
    response
      .write_all(format!(include_str!("websockets.html"), wsPort = port + 1).as_bytes())
      .unwrap();
    response.end().unwrap();
  };

  info!("Using ports {} {}", port, port + 1);

  // Start listening for http connections
  thread::spawn(move || {
                  let http_server = HttpServer::http(format!("127.0.0.1:{}", port)).unwrap();
                  http_server.handle(http_handler).unwrap();
                });

  // Start listening for WebSocket connections
  let ws_server = Server::bind(format!("127.0.0.1:{}", port + 1)).unwrap();

  for connection in ws_server.filter_map(Result::ok) {
    // Spawn a new thread for each connection.
    thread::spawn(move || {
      if !connection
            .protocols()
            .contains(&"rust-websocket".to_string()) {
        connection.reject().unwrap();
        return;
      }

      let mut client = connection
        .use_protocol("rust-websocket")
        .accept()
        .unwrap();

      let ip = client.peer_addr().unwrap();

      info!("Connection from {}", ip);

    //   let message = Message::text("Hello".to_string());
    //   client.send_message(&message).unwrap();

      let (mut receiver, mut sender) = client.split().unwrap();

      for message in receiver.incoming_messages() {
        let message: Message = message.unwrap();

        match message.opcode {

          Type::Close => {
            let message = Message::close();
            sender
              .send_message(&message)
              .unwrap_or_else(|_| info!("Client {} hung up!", ip));
            info!("Client {} disconnected", ip);
            return;
          }

          Type::Ping => {
            let message = Message::pong(message.payload);
            sender
              .send_message(&message)
              .unwrap_or_else(|_| info!("Could not ping client {}!", ip));
          }

          _ => {

            // Get the payload, in a lossy manner
            let msg = String::from_utf8_lossy(&message.payload);

            // Function to remap Json Deserizilation error
            // to a SerialResponse:Error
            let remap_error = |_| -> SerialResponse {
              SerialResponse::Error {
                kind: ErrorType::JsonParseFailure,
                msg: "Unable to parse json".to_string(),
                detail: Some(msg.to_string()),
                port: None,
                handle: None,
              }
            };

            // So we will get a result <SerialRequest::*,SerialResponse::Error> back
            let res: Result<SerialRequest, SerialResponse> = serde_json::from_str(&msg)
              .map_err(remap_error);

            let reply = match res {
              Ok(req) => Message::text(serde_json::to_string(&req).unwrap()),
              Err(err) => Message::text(serde_json::to_string(&err).unwrap()),
            };

            sender
              .send_message(&reply)
              .unwrap_or_else(|_| {
                                info!("Could send message {} to client {}",
                                      String::from_utf8_lossy(&message.payload),
                                      ip)
                              });
          }
        }
      }
    });
  }
}

fn handle_serial_req(req: SerialRequest) {
  match req {
    SerialRequest::Open { port } => {}
    SerialRequest::Write {
      handle,
      port,
      data,
      base64,
    } => {}
    SerialRequest::WriteLock { handle, port } => {}
    SerialRequest::ReleaseWriteLock { handle, port } => {}
  }
}
<commit_msg>Slight cleanup and add match for new close enum value<commit_after>extern crate argparse;
extern crate env_logger;
extern crate hyper;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serialport;
extern crate websocket;

mod serial_support;

use std::thread;
use std::io::Write;
use std::collections::HashMap;

use argparse::{ArgumentParser, Store};
use websocket::{Server, Message};
use websocket::message::Type;
use hyper::Server as HttpServer;
use hyper::net::Fresh;
use hyper::server::request::Request;
use hyper::server::response::Response;

use serial_support::messages::*;
use serial_support::manage::*;

fn main() {

  // Init logger
  env_logger::init().unwrap();

  // let sr = SerialResponse::Response {
  //     data: "HEY YOU".to_string(),
  //     base64: None,
  // };
  // info!("serialized = {}", serde_json::to_string(&sr).unwrap());

  // Default port number
  let mut port = 8080;
  // Parse cmdline args
  {
    let mut ap = ArgumentParser::new();
    ap.set_description("Provide access to serial ports over JSON Websockets");
    ap.refer(&mut port)
      .add_option(&["-p", "--port"], Store, "Http Port");
    ap.parse_args_or_exit();
  }

  // The HTTP server handler
  let http_handler = move |_: Request, response: Response<Fresh>| {
    let mut response = response.start().unwrap();
    // Send a client webpage
    response
      .write_all(format!(include_str!("websockets.html"), wsPort = port + 1).as_bytes())
      .unwrap();
    response.end().unwrap();
  };

  info!("Using ports {} {}", port, port + 1);

  // Start listening for http connections
  thread::spawn(move || {
                  let http_server = HttpServer::http(format!("127.0.0.1:{}", port)).unwrap();
                  http_server.handle(http_handler).unwrap();
                });

  // Start listening for WebSocket connections
  let ws_server = Server::bind(format!("127.0.0.1:{}", port + 1)).unwrap();

  for connection in ws_server.filter_map(Result::ok) {
    // Spawn a new thread for each connection.
    thread::spawn(move || {
      if !connection
            .protocols()
            .contains(&"rust-websocket".to_string()) {
        connection.reject().unwrap();
        return;
      }

      let client = connection
        .use_protocol("rust-websocket")
        .accept()
        .unwrap();

      let ip = client.peer_addr().unwrap();

      info!("Connection from {}", ip);

      //   let message = Message::text("Hello".to_string());
      //   client.send_message(&message).unwrap();

      let (mut receiver, mut sender) = client.split().unwrap();

      for message in receiver.incoming_messages() {
        let message: Message = message.unwrap();

        match message.opcode {

          Type::Close => {
            let message = Message::close();
            sender
              .send_message(&message)
              .unwrap_or_else(|_| info!("Client {} hung up!", ip));
            info!("Client {} disconnected", ip);
            return;
          }

          Type::Ping => {
            let message = Message::pong(message.payload);
            sender
              .send_message(&message)
              .unwrap_or_else(|_| info!("Could not ping client {}!", ip));
          }

          _ => {

            // Get the payload, in a lossy manner
            let msg = String::from_utf8_lossy(&message.payload);

            // Function to remap Json Deserizilation error
            // to a SerialResponse:Error
            let remap_error = |_| -> SerialResponse {
              SerialResponse::Error {
                kind: ErrorType::JsonParseFailure,
                msg: "Unable to parse json".to_string(),
                detail: Some(msg.to_string()),
                port: None,
                handle: None,
              }
            };

            // So we will get a result <SerialRequest::*,SerialResponse::Error> back
            let res: Result<SerialRequest, SerialResponse> = serde_json::from_str(&msg)
              .map_err(remap_error);

            let reply = match res {
              Ok(req) => Message::text(serde_json::to_string(&req).unwrap()),
              Err(err) => Message::text(serde_json::to_string(&err).unwrap()),
            };

            sender
              .send_message(&reply)
              .unwrap_or_else(|_| {
                                info!("Could send message {} to client {}",
                                      String::from_utf8_lossy(&message.payload),
                                      ip)
                              });
          }
        }
      }
    });
  }
}

fn handle_serial_req(req: SerialRequest) {
  match req {
    SerialRequest::Open { port } => {}
    SerialRequest::Write {
      handle,
      port,
      data,
      base64,
    } => {}
    SerialRequest::WriteLock { handle, port } => {}
    SerialRequest::ReleaseWriteLock { handle, port } => {}
    SerialRequest::Close { port } => {}
  }
}
<|endoftext|>


<commit_before>#![feature(core_intrinsics)]
#![allow(deprecated)]
extern crate mmap;

#[path="pi.rs"]
mod pi;

fn main() {
    let gpio = pi::Bcm2835Peripheral::new();
    unsafe {
        gpio.in_gpio(4);
        gpio.out_gpio(4);

        loop {
          gpio.set_gpio(1u32 << 4);
          std::thread::sleep_ms(1000);

          gpio.clear_gpio(1u32 << 4);
          std::thread::sleep_ms(1000);
        }
    }
}
<commit_msg>use usize instead of u32<commit_after>#![feature(core_intrinsics)]
#![allow(deprecated)]
extern crate mmap;

#[path="pi.rs"]
mod pi;

fn main() {
    let gpio = pi::Bcm2835Peripheral::new();
    unsafe {
        gpio.in_gpio(4);
        gpio.out_gpio(4);

        loop {
          gpio.set_gpio(1usize << 4);
          std::thread::sleep_ms(1000);

          gpio.clear_gpio(1usize << 4);
          std::thread::sleep_ms(1000);
        }
    }
}
<|endoftext|>


<commit_before>extern crate zwreec;
extern crate getopts;

use std::env;

#[macro_use]
pub mod utils;

fn main() {
    log_info!("main started");

    // handling commandline parameters
    let args: Vec<String> = env::args().collect();

    let mut input_file_name: &str;
    let mut output_file_name: &str;

    match args.len() {
        1 => {
            input_file_name = "a.in";
            output_file_name = "a.out";
        },
        3 => {
            input_file_name = &args[1];
            output_file_name = &args[2];
        },
        _ => {
            help();
            return;
        }
    };

    // call library
    zwreec::compile(input_file_name, output_file_name);

    // only for testing
    log_verbose!("(1) {}", zwreec::frontend::temp_hello());
    log_verbose!("(2) {}", zwreec::backend::temp_hello());
    log_verbose!("(3) {}", zwreec::file::temp_hello());

    log_info!("main finished");
}

fn help() {
    log_error!("invalid arguments");
    log_info!("usage:\n    zwreec <input_file> <output_file>");
}
<commit_msg>Use getopts to parse command line arguments<commit_after>extern crate zwreec;
extern crate getopts;

use std::env;

#[macro_use]
pub mod utils;

// shorthand to display program usage
macro_rules! print_usage {
    ($prog:ident, $opts:ident) => {{
        print!("{}", $opts.usage(&format!("Usage: {} [-h] [-v] [-o OUTPUT] INPUT", $prog)));
    }}
}

fn main() {
    // set default log level
    // utils::log::LOG_LEVEL = utils::log::LogLevel::WARN;

    // handling commandline parameters
    let args: Vec<String> = env::args().collect();
    let ref program = args[0];

    // define options
    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("v", "verbose", "be more verbose");
    opts.optopt("o", "", "name of the output file", "FILE");

    let parsed_opts = match opts.parse(&args[1..]) {
        Ok(m)  => { m }
        Err(f) => {
            // parsing error
            // display usage and return
            println!("{}", f.to_string());
            print_usage!(program, opts);
            // TODO: figure out a way to set exit code
            return;
        }
    };

    // examinate options
    if parsed_opts.opt_present("h") {
        // parsed "-h|--help"
        // display usage and return
        print_usage!(program, opts);
        return;
    }

    if parsed_opts.opt_present("v") {
        // parsed "-v|--verbose"
        // set loglevel to verbose
        // utils::log::LOG_LEVEL = utils::log::LogLevel::VERBOSE;
    }

    let outfile = if let Some(file) = parsed_opts.opt_str("o") {
        // parsed "-o FILE"
        // set of to filename
        file
    } else {
        // NOTE: string manipulation in rust is stil weird.
        let mut s = String::new();
        s.push_str("a.out");
        s
    };

    let infile = if parsed_opts.free.len() == 1 {
         // check number of 'free' parameter
         // one free parameter is the input file name
         parsed_opts.free[0].clone()
    } else {
        println!("Input file name missing");
        print_usage!(program, opts);
        // TODO: figure out a way to set exit code
        return;
    };

    // call library
    zwreec::compile(&infile, &outfile);

    // only for testing
    log_verbose!("(1) {}", zwreec::frontend::temp_hello());
    log_verbose!("(2) {}", zwreec::backend::temp_hello());
    log_verbose!("(3) {}", zwreec::file::temp_hello());

    log_info!("main finished");
}
<|endoftext|>


<commit_before>//! Client binary

#![deny(missing_docs)]
#![deny(warnings)]

#![feature(plugin)]
#![plugin(clippy)]
#![allow(or_fun_call)]
#![allow(mutex_atomic)]
#![allow(needless_borrow)]

extern crate cgmath;
#[macro_use]
extern crate log;
extern crate thread_scoped;
extern crate time;

extern crate common;
extern crate client_lib;

use std::sync::{Mutex};

use common::protocol;

use client_lib::client;
use client_lib::server;
use client_lib::update_thread::update_thread;

#[allow(missing_docs)]
pub fn run(listen_url: &str, server_url: &str) {
  let quit = Mutex::new(false);
  let quit = &quit;

  let server = server::new(&server_url, &listen_url);

  let client = connect_client(&listen_url, &server);
  *client.load_position.lock().unwrap() = Some(cgmath::Point3::new(0.0, 512.0, 0.0));
  let client = &client;

  let loaded_count = Mutex::new(0);
  let start = time::precise_time_ns();

  let monitor_thread = {
    unsafe {
      thread_scoped::scoped(|| {
        while !*quit.lock().unwrap() {
          let now = time::precise_time_ns();
          let loaded_count = *loaded_count.lock().unwrap();
          info!("Chunks received: {}", loaded_count);
          info!("Chunk receive rate: {} Hz", loaded_count as f32 / (now - start) as f32 * 1e9);
          std::thread::sleep(std::time::Duration::from_secs(1));
        }
      })
    }
  };

  let update_thread = {
    let client       = &client;
    let loaded_count = &loaded_count;
    let server       = server.clone();
    unsafe {
      thread_scoped::scoped(move || {
        update_thread(
          quit,
          client,
          &mut || { server.listen.try() },
          &mut || { None },
          &mut |_| { },
          &mut |_| { },
          &mut |_| { },
          &mut |up| { server.talk.tell(&up) },
          &mut |_, _, reason| {
            if let common::protocol::VoxelReason::Requested = reason {
              *loaded_count.lock().unwrap() += 1;
              *client.outstanding_terrain_requests.lock().unwrap() -= 1;
            }
          },
        );
      })
    }
  };

  while (time::precise_time_ns() - start) < 80e9 as u64 {
    std::thread::sleep(std::time::Duration::from_secs(1));
  }

  println!("{} bytes sent", *server.talk.bytes_sent.lock().unwrap());

  // View thread returned, so we got a quit event.
  *quit.lock().unwrap() = true;

  monitor_thread.join();
  update_thread.join();
}

fn connect_client(listen_url: &str, server: &server::T) -> client::T {
  // TODO: Consider using RPCs to solidify the request-response patterns.
  server.talk.tell(&protocol::ClientToServer::Init(listen_url.to_owned()));
  loop {
    match server.listen.wait() {
      protocol::ServerToClient::LeaseId(client_id) => {
        server.talk.tell(&protocol::ClientToServer::AddPlayer(client_id));
        let client_id = client_id;
        loop {
          match server.listen.wait() {
            protocol::ServerToClient::PlayerAdded(player_id, position) => {
              return client::new(client_id, player_id, position);
            },
            msg => {
              // Ignore other messages in the meantime.
              warn!("Ignoring: {:?}", msg);
            },
          }
        }
      },
      msg => {
        // Ignore other messages in the meantime.
        warn!("Ignoring: {:?}", msg);
      },
    }
  }
}
<commit_msg>fix build?<commit_after>//! Client binary

#![deny(missing_docs)]
#![deny(warnings)]

#![feature(plugin)]
#![plugin(clippy)]
#![allow(or_fun_call)]
#![allow(mutex_atomic)]
#![allow(needless_borrow)]

extern crate cgmath;
#[macro_use]
extern crate log;
extern crate thread_scoped;
extern crate time;

extern crate common;
extern crate client_lib;

use std::sync::{Mutex};

use common::protocol;

use client_lib::client;
use client_lib::server;
use client_lib::update_thread::update_thread;

#[allow(missing_docs)]
pub fn run(listen_url: &str, server_url: &str) {
  let quit = Mutex::new(false);
  let quit = &quit;

  let server = server::new(&server_url, &listen_url);

  let client = connect_client(&listen_url, &server);
  *client.load_position.lock().unwrap() = Some(cgmath::Point3::new(0.0, 512.0, 0.0));
  let client = &client;

  let loaded_count = Mutex::new(0);
  let start = time::precise_time_ns();

  let monitor_thread = {
    unsafe {
      thread_scoped::scoped(|| {
        while !*quit.lock().unwrap() {
          let now = time::precise_time_ns();
          let loaded_count = *loaded_count.lock().unwrap();
          info!("Chunks received: {}", loaded_count);
          info!("Chunk receive rate: {} Hz", loaded_count as f32 / (now - start) as f32 * 1e9);
          std::thread::sleep(std::time::Duration::from_secs(1));
        }
      })
    }
  };

  let update_thread = {
    let client       = &client;
    let loaded_count = &loaded_count;
    let server       = server.clone();
    unsafe {
      thread_scoped::scoped(move || {
        update_thread(
          quit,
          client,
          &mut || { server.listen.try() },
          &mut || { None },
          &mut |_| { },
          &mut |_| { },
          &mut |_| { },
          &mut |up| { server.talk.tell(&up) },
          &mut |_, reason| {
            if let common::protocol::VoxelReason::Requested { .. } = reason {
              *loaded_count.lock().unwrap() += 1;
              *client.outstanding_terrain_requests.lock().unwrap() -= 1;
            }
          },
        );
      })
    }
  };

  while (time::precise_time_ns() - start) < 80e9 as u64 {
    std::thread::sleep(std::time::Duration::from_secs(1));
  }

  println!("{} bytes sent", *server.talk.bytes_sent.lock().unwrap());

  // View thread returned, so we got a quit event.
  *quit.lock().unwrap() = true;

  monitor_thread.join();
  update_thread.join();
}

fn connect_client(listen_url: &str, server: &server::T) -> client::T {
  // TODO: Consider using RPCs to solidify the request-response patterns.
  server.talk.tell(&protocol::ClientToServer::Init(listen_url.to_owned()));
  loop {
    match server.listen.wait() {
      protocol::ServerToClient::LeaseId(client_id) => {
        server.talk.tell(&protocol::ClientToServer::AddPlayer(client_id));
        let client_id = client_id;
        loop {
          match server.listen.wait() {
            protocol::ServerToClient::PlayerAdded(player_id, position) => {
              return client::new(client_id, player_id, position);
            },
            msg => {
              // Ignore other messages in the meantime.
              warn!("Ignoring: {:?}", msg);
            },
          }
        }
      },
      msg => {
        // Ignore other messages in the meantime.
        warn!("Ignoring: {:?}", msg);
      },
    }
  }
}
<|endoftext|>


<commit_before>use std::{fmt, ops::Bound};

use crate::Lazy;

use super::*;

#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct Node {
    pub(crate) data: Data,
    pub(crate) next: Option<PageId>,
    pub(crate) lo: IVec,
    pub(crate) hi: IVec,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl Debug for Node {
    fn fmt(
        &self,
        f: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let data = self.data.fmt_keys(&self.lo);

        write!(
            f,
            "Node {{ \
             lo: {:?} \
             hi: {:?} \
             next: {:?} \
             merging_child: {:?} \
             merging: {} \
             data: {:?} }}",
            self.lo, self.hi, self.next, self.merging_child, self.merging, data
        )
    }
}

impl Node {
    pub(crate) fn apply(&mut self, frag: &Frag) {
        use self::Frag::*;

        assert!(
            !self.merging,
            "somehow a frag was applied to a node after it was merged"
        );

        match *frag {
            Set(ref k, ref v) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.set_leaf(k.clone(), v.clone());
                } else {
                    panic!(
                        "tried to consolidate set at key <= hi.\
                         Set({:?}, {:?}) to node {:?}",
                        k, v, self
                    )
                }
            }
            Del(ref k) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.del_leaf(k);
                } else {
                    panic!("tried to consolidate del at key <= hi")
                }
            }
            Base(_) => panic!("trying to apply a Base to frag {:?}", self),
            ParentMergeIntention(pid) => {
                assert!(
                    self.merging_child.is_none(),
                    "trying to merge {:?} into node {:?} which \
                     is already merging another child",
                    frag,
                    self
                );
                self.merging_child = Some(pid);
            }
            ParentMergeConfirm => {
                assert!(self.merging_child.is_some());
                let merged_child = self.merging_child.take().expect(
                    "we should have a specific \
                     child that was merged if this \
                     frag appears here",
                );
                self.data.parent_merge_confirm(merged_child);
            }
            ChildMergeCap => {
                self.merging = true;
            }
        }
    }

    pub(crate) fn set_leaf(&mut self, key: IVec, val: IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records.binary_search_by(|(k, _)| prefix_cmp(k, &key));
            match search {
                Ok(idx) => records[idx] = (key, val),
                Err(idx) => records.insert(idx, (key, val)),
            }
        } else {
            panic!("tried to Set a value to an index");
        }
    }

    pub(crate) fn parent_split(&mut self, at: &[u8], to: PageId) -> bool {
        if let Data::Index(ref mut ptrs) = self.data {
            let encoded_sep = prefix_encode(&self.lo, at);
            match ptrs.binary_search_by(|a| prefix_cmp(&a.0, &encoded_sep)) {
                Ok(_) => {
                    debug!(
                        "parent_split skipped because \
                         parent already contains child at split point \
                         due to deep race"
                    );
                    return false;
                }
                Err(idx) => ptrs.insert(idx, (encoded_sep, to)),
            }
        } else {
            panic!("tried to attach a ParentSplit to a Leaf chain");
        }

        true
    }

    pub(crate) fn del_leaf(&mut self, key: &IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records
                .binary_search_by(|&(ref k, ref _v)| prefix_cmp(k, &*key));
            if let Ok(idx) = search {
                let _removed = records.remove(idx);
            }
        } else {
            panic!("tried to attach a Del to an Index chain");
        }
    }

    pub(crate) fn split(mut self) -> (Self, Self) {
        let (split, right_data) = self.data.split(&self.lo);
        let rhs = Self {
            data: right_data,
            next: self.next,
            lo: split,
            hi: self.hi.clone(),
            merging_child: None,
            merging: false,
        };

        self.data.drop_gte(&rhs.lo, &self.lo);
        self.hi = rhs.lo.clone();

        // intentionally make this the end to make
        // any issues pop out with setting it
        // correctly after the split.
        self.next = None;

        (self, rhs)
    }

    pub(crate) fn receive_merge(&self, rhs: &Self) -> Self {
        let mut merged = self.clone();
        merged.hi = rhs.hi.clone();
        merged.data.receive_merge(
            rhs.lo.as_ref(),
            merged.lo.as_ref(),
            &rhs.data,
        );
        merged.next = rhs.next;
        merged
    }

    pub(crate) fn contains_upper_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Excluded(bound) if self.hi >= *bound => true,
            Bound::Included(bound) if self.hi > *bound => true,
            _ => self.hi.is_empty(),
        }
    }

    pub(crate) fn contains_lower_bound(
        &self,
        bound: &Bound<IVec>,
        is_forward: bool,
    ) -> bool {
        match bound {
            Bound::Excluded(bound)
                if self.lo < *bound || (is_forward && *bound == self.lo) =>
            {
                true
            }
            Bound::Included(bound) if self.lo <= *bound => true,
            Bound::Unbounded if !is_forward => self.hi.is_empty(),
            _ => self.lo.is_empty(),
        }
    }

    pub(crate) fn successor(
        &self,
        bound: &Bound<IVec>,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.data.is_index());

        // This encoding happens this way because
        // keys cannot be lower than the node's lo key.
        let predecessor_key = match bound {
            Bound::Unbounded => prefix_encode(&self.lo, &self.lo),
            Bound::Included(b) => {
                let max = std::cmp::max(b, &self.lo);
                prefix_encode(&self.lo, max)
            }
            Bound::Excluded(b) => {
                let max = std::cmp::max(b, &self.lo);
                prefix_encode(&self.lo, max)
            }
        };

        let records = self.data.leaf_ref().unwrap();
        let search =
            records.binary_search_by(|(k, _)| prefix_cmp(k, &predecessor_key));

        let idx = match search {
            Ok(idx) => idx,
            Err(idx) if idx < records.len() => idx,
            _ => return None,
        };

        for (k, v) in &records[idx..] {
            match bound {
                Bound::Excluded(b)
                    if prefix_cmp_encoded(k, b, &self.lo)
                        == std::cmp::Ordering::Equal =>
                {
                    // keep going because we wanted to exclude
                    // this key.
                    continue;
                }
                _ => {}
            }
            let decoded_key = prefix_decode(&self.lo, &k);
            return Some((IVec::from(decoded_key), v.clone()));
        }

        None
    }

    pub(crate) fn predecessor(
        &self,
        bound: &Bound<IVec>,
    ) -> Option<(IVec, IVec)> {
        static MAX_IVEC: Lazy<IVec, fn() -> IVec> = Lazy::new(init_max_ivec);

        fn init_max_ivec() -> IVec {
            let mut base = vec![255; 1024 * 1024];
            base[0] = 0;
            IVec::from(base)
        }

        assert!(!self.data.is_index());

        // This encoding happens this way because
        // the rightmost (unbounded) node has
        // a hi key represented by the empty slice
        let successor_key = match bound {
            Bound::Unbounded => {
                if self.hi.is_empty() {
                    MAX_IVEC.clone()
                } else {
                    prefix_encode(&self.lo, &self.hi)
                }
            }
            Bound::Included(b) => {
                let min = if self.hi.is_empty() {
                    b
                } else {
                    std::cmp::min(b, &self.hi)
                };
                prefix_encode(&self.lo, min)
            }
            Bound::Excluded(b) => {
                let min = if self.hi.is_empty() {
                    b
                } else {
                    std::cmp::min(b, &self.hi)
                };
                prefix_encode(&self.lo, min)
            }
        };

        let records = self.data.leaf_ref().unwrap();
        let search =
            records.binary_search_by(|(k, _)| prefix_cmp(k, &successor_key));

        let idx = match search {
            Ok(idx) => idx,
            Err(idx) if idx > 0 => idx - 1,
            _ => return None,
        };

        for (k, v) in records[0..=idx].iter().rev() {
            match bound {
                Bound::Excluded(b)
                    if prefix_cmp_encoded(k, b, &self.lo)
                        == std::cmp::Ordering::Equal =>
                {
                    // keep going because we wanted to exclude
                    // this key.
                    continue;
                }
                _ => {}
            }
            let decoded_key = prefix_decode(&self.lo, &k);
            return Some((IVec::from(decoded_key), v.clone()));
        }
        None
    }

    /// leaf_pair_for_key finds an existing value pair for a given key.
    pub(crate) fn leaf_pair_for_key(
        &self,
        key: &[u8],
    ) -> Option<(&IVec, &IVec)> {
        assert!(!self.data.is_index());

        let records = self.data.leaf_ref().unwrap();
        let search = records
            .binary_search_by(|&(ref k, ref _v)| {
                prefix_cmp_encoded(k, key, &self.lo)
            })
            .ok();

        search.map(|idx| (&records[idx].0, &records[idx].1))
    }

    /// node_kv_pair returns either existing (node/key, value) pair or
    /// (node/key, none) where a node/key is node level encoded key.
    pub fn node_kv_pair(&self, key: &[u8]) -> (IVec, Option<IVec>) {
        if let Some((k, v)) = self.leaf_pair_for_key(key.as_ref()) {
            (k.clone(), Some(v.clone()))
        } else {
            let encoded_key = prefix_encode(&self.lo, key.as_ref());
            let encoded_val = None;
            (encoded_key, encoded_val)
        }
    }

    pub(crate) fn should_split(&self) -> bool {
        let threshold = if cfg!(any(test, feature = "lock_free_delays")) {
            2
        } else if self.data.is_index() {
            256
        } else {
            16
        };

        let size_checks = self.data.len() > threshold;
        let safety_checks = self.merging_child.is_none() && !self.merging;

        size_checks && safety_checks
    }

    pub(crate) fn should_merge(&self) -> bool {
        let threshold = if cfg!(any(test, feature = "lock_free_delays")) {
            1
        } else if self.data.is_index() {
            64
        } else {
            4
        };

        let size_checks = self.data.len() < threshold;
        let safety_checks = self.merging_child.is_none() && !self.merging;

        size_checks && safety_checks
    }

    pub(crate) fn can_merge_child(&self) -> bool {
        self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn index_next_node(&self, key: &[u8]) -> (usize, PageId) {
        assert!(self.data.is_index());

        let records = self.data.index_ref().unwrap();

        let search = binary_search_lub(records, |&(ref k, ref _v)| {
            prefix_cmp_encoded(k, key, &self.lo)
        });

        // This might be none if ord is Less and we're
        // searching for the empty key
        let index = search.expect("failed to traverse index");

        (index, records[index].1)
    }
}
<commit_msg>Don't constantly recompute common prefix length for every compared child on tree traversal<commit_after>use std::{fmt, ops::Bound};

use crate::Lazy;

use super::*;

#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct Node {
    pub(crate) data: Data,
    pub(crate) next: Option<PageId>,
    pub(crate) lo: IVec,
    pub(crate) hi: IVec,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl Debug for Node {
    fn fmt(
        &self,
        f: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let data = self.data.fmt_keys(&self.lo);

        write!(
            f,
            "Node {{ \
             lo: {:?} \
             hi: {:?} \
             next: {:?} \
             merging_child: {:?} \
             merging: {} \
             data: {:?} }}",
            self.lo, self.hi, self.next, self.merging_child, self.merging, data
        )
    }
}

impl Node {
    pub(crate) fn apply(&mut self, frag: &Frag) {
        use self::Frag::*;

        assert!(
            !self.merging,
            "somehow a frag was applied to a node after it was merged"
        );

        match *frag {
            Set(ref k, ref v) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.set_leaf(k.clone(), v.clone());
                } else {
                    panic!(
                        "tried to consolidate set at key <= hi.\
                         Set({:?}, {:?}) to node {:?}",
                        k, v, self
                    )
                }
            }
            Del(ref k) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.del_leaf(k);
                } else {
                    panic!("tried to consolidate del at key <= hi")
                }
            }
            Base(_) => panic!("trying to apply a Base to frag {:?}", self),
            ParentMergeIntention(pid) => {
                assert!(
                    self.merging_child.is_none(),
                    "trying to merge {:?} into node {:?} which \
                     is already merging another child",
                    frag,
                    self
                );
                self.merging_child = Some(pid);
            }
            ParentMergeConfirm => {
                assert!(self.merging_child.is_some());
                let merged_child = self.merging_child.take().expect(
                    "we should have a specific \
                     child that was merged if this \
                     frag appears here",
                );
                self.data.parent_merge_confirm(merged_child);
            }
            ChildMergeCap => {
                self.merging = true;
            }
        }
    }

    pub(crate) fn set_leaf(&mut self, key: IVec, val: IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records.binary_search_by(|(k, _)| prefix_cmp(k, &key));
            match search {
                Ok(idx) => records[idx] = (key, val),
                Err(idx) => records.insert(idx, (key, val)),
            }
        } else {
            panic!("tried to Set a value to an index");
        }
    }

    pub(crate) fn parent_split(&mut self, at: &[u8], to: PageId) -> bool {
        if let Data::Index(ref mut ptrs) = self.data {
            let encoded_sep = prefix_encode(&self.lo, at);
            match ptrs.binary_search_by(|a| prefix_cmp(&a.0, &encoded_sep)) {
                Ok(_) => {
                    debug!(
                        "parent_split skipped because \
                         parent already contains child at split point \
                         due to deep race"
                    );
                    return false;
                }
                Err(idx) => ptrs.insert(idx, (encoded_sep, to)),
            }
        } else {
            panic!("tried to attach a ParentSplit to a Leaf chain");
        }

        true
    }

    pub(crate) fn del_leaf(&mut self, key: &IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records
                .binary_search_by(|&(ref k, ref _v)| prefix_cmp(k, &*key));
            if let Ok(idx) = search {
                let _removed = records.remove(idx);
            }
        } else {
            panic!("tried to attach a Del to an Index chain");
        }
    }

    pub(crate) fn split(mut self) -> (Self, Self) {
        let (split, right_data) = self.data.split(&self.lo);
        let rhs = Self {
            data: right_data,
            next: self.next,
            lo: split,
            hi: self.hi.clone(),
            merging_child: None,
            merging: false,
        };

        self.data.drop_gte(&rhs.lo, &self.lo);
        self.hi = rhs.lo.clone();

        // intentionally make this the end to make
        // any issues pop out with setting it
        // correctly after the split.
        self.next = None;

        (self, rhs)
    }

    pub(crate) fn receive_merge(&self, rhs: &Self) -> Self {
        let mut merged = self.clone();
        merged.hi = rhs.hi.clone();
        merged.data.receive_merge(
            rhs.lo.as_ref(),
            merged.lo.as_ref(),
            &rhs.data,
        );
        merged.next = rhs.next;
        merged
    }

    pub(crate) fn contains_upper_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Excluded(bound) if self.hi >= *bound => true,
            Bound::Included(bound) if self.hi > *bound => true,
            _ => self.hi.is_empty(),
        }
    }

    pub(crate) fn contains_lower_bound(
        &self,
        bound: &Bound<IVec>,
        is_forward: bool,
    ) -> bool {
        match bound {
            Bound::Excluded(bound)
                if self.lo < *bound || (is_forward && *bound == self.lo) =>
            {
                true
            }
            Bound::Included(bound) if self.lo <= *bound => true,
            Bound::Unbounded if !is_forward => self.hi.is_empty(),
            _ => self.lo.is_empty(),
        }
    }

    pub(crate) fn successor(
        &self,
        bound: &Bound<IVec>,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.data.is_index());

        // This encoding happens this way because
        // keys cannot be lower than the node's lo key.
        let predecessor_key = match bound {
            Bound::Unbounded => prefix_encode(&self.lo, &self.lo),
            Bound::Included(b) => {
                let max = std::cmp::max(b, &self.lo);
                prefix_encode(&self.lo, max)
            }
            Bound::Excluded(b) => {
                let max = std::cmp::max(b, &self.lo);
                prefix_encode(&self.lo, max)
            }
        };

        let records = self.data.leaf_ref().unwrap();
        let search =
            records.binary_search_by(|(k, _)| prefix_cmp(k, &predecessor_key));

        let idx = match search {
            Ok(idx) => idx,
            Err(idx) if idx < records.len() => idx,
            _ => return None,
        };

        for (k, v) in &records[idx..] {
            match bound {
                Bound::Excluded(b)
                    if prefix_cmp_encoded(k, b, &self.lo)
                        == std::cmp::Ordering::Equal =>
                {
                    // keep going because we wanted to exclude
                    // this key.
                    continue;
                }
                _ => {}
            }
            let decoded_key = prefix_decode(&self.lo, &k);
            return Some((IVec::from(decoded_key), v.clone()));
        }

        None
    }

    pub(crate) fn predecessor(
        &self,
        bound: &Bound<IVec>,
    ) -> Option<(IVec, IVec)> {
        static MAX_IVEC: Lazy<IVec, fn() -> IVec> = Lazy::new(init_max_ivec);

        fn init_max_ivec() -> IVec {
            let mut base = vec![255; 1024 * 1024];
            base[0] = 0;
            IVec::from(base)
        }

        assert!(!self.data.is_index());

        // This encoding happens this way because
        // the rightmost (unbounded) node has
        // a hi key represented by the empty slice
        let successor_key = match bound {
            Bound::Unbounded => {
                if self.hi.is_empty() {
                    MAX_IVEC.clone()
                } else {
                    prefix_encode(&self.lo, &self.hi)
                }
            }
            Bound::Included(b) => {
                let min = if self.hi.is_empty() {
                    b
                } else {
                    std::cmp::min(b, &self.hi)
                };
                prefix_encode(&self.lo, min)
            }
            Bound::Excluded(b) => {
                let min = if self.hi.is_empty() {
                    b
                } else {
                    std::cmp::min(b, &self.hi)
                };
                prefix_encode(&self.lo, min)
            }
        };

        let records = self.data.leaf_ref().unwrap();
        let search =
            records.binary_search_by(|(k, _)| prefix_cmp(k, &successor_key));

        let idx = match search {
            Ok(idx) => idx,
            Err(idx) if idx > 0 => idx - 1,
            _ => return None,
        };

        for (k, v) in records[0..=idx].iter().rev() {
            match bound {
                Bound::Excluded(b)
                    if prefix_cmp_encoded(k, b, &self.lo)
                        == std::cmp::Ordering::Equal =>
                {
                    // keep going because we wanted to exclude
                    // this key.
                    continue;
                }
                _ => {}
            }
            let decoded_key = prefix_decode(&self.lo, &k);
            return Some((IVec::from(decoded_key), v.clone()));
        }
        None
    }

    /// leaf_pair_for_key finds an existing value pair for a given key.
    pub(crate) fn leaf_pair_for_key(
        &self,
        key: &[u8],
    ) -> Option<(&IVec, &IVec)> {
        assert!(!self.data.is_index());

        let records = self.data.leaf_ref().unwrap();

        let common_prefix = key
            .iter()
            .zip(self.lo.iter())
            .take(u8::max_value() as usize)
            .take_while(|(a, b)| a == b)
            .count() as u8;

        let search = records
            .binary_search_by(|&(ref k, ref _v)| {
                if k[0] > common_prefix {
                    Ordering::Less
                } else if k[0] < common_prefix {
                    Ordering::Greater
                } else {
                    k[1..].cmp(&key[common_prefix as usize..])
                }
            })
            .ok();

        search.map(|idx| (&records[idx].0, &records[idx].1))
    }

    /// node_kv_pair returns either existing (node/key, value) pair or
    /// (node/key, none) where a node/key is node level encoded key.
    pub fn node_kv_pair(&self, key: &[u8]) -> (IVec, Option<IVec>) {
        if let Some((k, v)) = self.leaf_pair_for_key(key.as_ref()) {
            (k.clone(), Some(v.clone()))
        } else {
            let encoded_key = prefix_encode(&self.lo, key.as_ref());
            let encoded_val = None;
            (encoded_key, encoded_val)
        }
    }

    pub(crate) fn should_split(&self) -> bool {
        let threshold = if cfg!(any(test, feature = "lock_free_delays")) {
            2
        } else if self.data.is_index() {
            256
        } else {
            16
        };

        let size_checks = self.data.len() > threshold;
        let safety_checks = self.merging_child.is_none() && !self.merging;

        size_checks && safety_checks
    }

    pub(crate) fn should_merge(&self) -> bool {
        let threshold = if cfg!(any(test, feature = "lock_free_delays")) {
            1
        } else if self.data.is_index() {
            64
        } else {
            4
        };

        let size_checks = self.data.len() < threshold;
        let safety_checks = self.merging_child.is_none() && !self.merging;

        size_checks && safety_checks
    }

    pub(crate) fn can_merge_child(&self) -> bool {
        self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn index_next_node(&self, key: &[u8]) -> (usize, PageId) {
        let records = self
            .data
            .index_ref()
            .expect("index_next_node called on leaf");

        let common_prefix = key
            .iter()
            .zip(self.lo.iter())
            .take(u8::max_value() as usize)
            .take_while(|(a, b)| a == b)
            .count() as u8;

        let search = binary_search_lub(records, |&(ref k, ref _v)| {
            if k[0] > common_prefix {
                Ordering::Less
            } else if k[0] < common_prefix {
                Ordering::Greater
            } else {
                k[1..].cmp(&key[common_prefix as usize..])
            }
        });

        let index = search.expect("failed to traverse index");

        (index, records[index].1)
    }
}
<|endoftext|>