<commit_before>extern crate libc;
extern crate termios;

use libc::{STDIN_FILENO, STDOUT_FILENO, TIOCGWINSZ, winsize};
use termios::{Termios, tcsetattr, TCSAFLUSH, VMIN, VTIME};
use termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON};
use termios::{OPOST, CS8};
use termios::{ECHO, ICANON, IEXTEN, ISIG};

use std::env;
use std::fs::File;
use std::io::{self, Stdin, Stdout, Read, BufRead, BufReader, Error, ErrorKind, Write};

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

#[derive(PartialEq, Clone, Copy)]
enum Key {
    Character(u8),
    ArrowLeft,
    ArrowRight,
    ArrowUp,
    ArrowDown,
    DeleteKey,
    HomeKey,
    EndKey,
    PageUp,
    PageDown,
}

macro_rules! ctrl_key {
    ($k:expr) => ($k & 0x1f);
}

struct RawMode {
    orig_term: Termios
}

struct Row(String);

struct Editor {
    _mode: RawMode,
    cx: usize,
    cy: usize,
    rowoff: usize,
    coloff: usize,
    screenrows: usize,
    screencols: usize,
    rows: Option<Vec<Row>>,
    stdin: Stdin,
    stdout: Stdout,
}

impl RawMode {
    fn enable_raw_mode() -> io::Result<RawMode> {
        let mut term = Termios::from_fd(STDIN_FILENO)?;
        let mode = RawMode { orig_term: term.clone() };

        term.c_iflag &= !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        term.c_oflag &= !OPOST;
        term.c_cflag |= CS8;
        term.c_lflag &= !(ECHO | ICANON | IEXTEN | ISIG);
        term.c_cc[VMIN] = 0;
        term.c_cc[VTIME] = 1;

        tcsetattr(STDIN_FILENO, TCSAFLUSH, &term)?;
        Ok(mode)
    }
}

impl Drop for RawMode {
    fn drop(&mut self) {
        tcsetattr(STDIN_FILENO, TCSAFLUSH, &self.orig_term).unwrap()
    }
}

fn read_non_blocking<R : Read>(r : &mut R, buf: &mut [u8]) -> usize {
    r.read(buf)
     .or_else(|e| if e.kind() == ErrorKind::WouldBlock { Ok(0) } else { Err(e) })
     .expect("read_non_blocking")
}

fn byte_slice(s: &str, offset: usize, max_len: usize) -> &[u8] {
    if s.len() > max_len + offset {
        s[offset..(max_len + offset)].as_bytes()
    } else if s.len() > offset {
        s[offset..].as_bytes()
    } else {
        s[0..0].as_bytes()
    }
}

fn editor_read_key(stdin: &mut Stdin) -> Key {
    let mut buf = [0; 1];
    loop {
        let n = read_non_blocking(stdin, &mut buf);
        if n == 1 {
            if buf[0] == b'\x1b' {
                let mut seq = [0; 2];
                let n = read_non_blocking(stdin, &mut seq);
                if n == 2 && seq[0] == b'[' {
                    if seq[1] >= b'0' && seq[1] <= b'9' {
                        let mut last = [0; 1];
                        let n = read_non_blocking(stdin, &mut last);
                        if n == 1 {
                            if last[0] == b'~' {
                                return match seq[1] {
                                    b'1' => Key::HomeKey,
                                    b'3' => Key::DeleteKey,
                                    b'4' => Key::EndKey,
                                    b'5' => Key::PageUp,
                                    b'6' => Key::PageDown,
                                    b'7' => Key::HomeKey,
                                    b'8' => Key::EndKey,
                                    _ => Key::Character(b'\x1b'),
                                }
                            }
                        }
                    } else {
                        return match seq[1] {
                            b'A' => Key::ArrowUp,
                            b'B' => Key::ArrowDown,
                            b'C' => Key::ArrowRight,
                            b'D' => Key::ArrowLeft,
                            b'H' => Key::HomeKey,
                            b'F' => Key::EndKey,
                            _ => Key::Character(b'\x1b'),
                        }
                    }
                } else if n == 2 && seq[0] == b'O' {
                    return match seq[1] {
                        b'H' => Key::HomeKey,
                        b'F' => Key::EndKey,
                        _ => Key::Character(b'\x1b'),
                    }
                }
                return Key::Character(b'\x1b');
            } else {
                return Key::Character(buf[0]);
            }
        }
    }
}

fn get_window_size() -> io::Result<(u16, u16)> {
    let ws = winsize { ws_col: 0, ws_row: 0, ws_xpixel: 0, ws_ypixel: 0 };
    unsafe {
        if libc::ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0 {
            return Err(Error::new(ErrorKind::Other, "get_window_size: ioctl failed"))
        }
    }
    Ok((ws.ws_row, ws.ws_col))
}

impl Editor {
    fn new() -> io::Result<Editor> {
        let mode = RawMode::enable_raw_mode()?;
        let (rows, cols) = get_window_size()?;
        let stdin = io::stdin();
        let stdout = io::stdout();
        Ok(Editor {
            _mode: mode,
            cx: 0,
            cy: 0,
            rowoff: 0,
            coloff: 0,
            screenrows: rows as usize,
            screencols: cols as usize,
            rows: None,
            stdin: stdin,
            stdout: stdout
        })
    }

    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.stdout.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }

    fn scroll(&mut self) {
        if self.cy < self.rowoff {
            self.rowoff = self.cy;
        }
        if self.cy >= self.rowoff + self.screenrows {
            self.rowoff = self.cy - self.screenrows + 1;
        }
        if self.cx < self.coloff {
            self.coloff = self.cx;
        }
        if self.cx >= self.coloff + self.screencols {
            self.coloff = (1 + self.cx) - self.screencols;
        }
    }

    fn numrows(&self) -> usize {
        self.rows.as_ref().map_or(0, |v| v.len())
    }

    fn draw_rows(&mut self) -> io::Result<()> {
        let numrows = self.numrows();
        for y in 0..(self.screenrows) {
            let filerow = y + self.rowoff;
            if filerow >= numrows {
                if self.rows.is_none() && y == self.screenrows / 3 {
                    let mut msg = format!("Kilo-rs editor -- version {}", VERSION);
                    msg.truncate(self.screencols);
                    let padding = (self.screencols - msg.len()) / 2;
                    if padding > 0 {
                        self.write(b"~")?;
                        for _ in 1..padding {
                            self.write(b" ")?;
                        }
                    }
                    self.write(msg.as_bytes())?;
                } else {
                    self.write(b"~")?;
                }
            } else {
                let rows = self.rows.as_ref().unwrap();
                self.stdout.write(byte_slice(&rows[filerow].0, self.coloff, self.screencols))?;
            }

            self.write(b"\x1b[K")?;
            if y < self.screenrows - 1 {
                self.write(b"\r\n")?;
            }
        }
        Ok(())
    }

    fn refresh_screen(&mut self) -> io::Result<()> {
        self.scroll();

        self.write(b"\x1b[?25l")?;
        self.write(b"\x1b[H")?;

        self.draw_rows()?;

        let move_cursor = format!("\x1b[{};{}H",
                                  (self.cy - self.rowoff) + 1,
                                  (self.cx - self.coloff) + 1)
                                 .into_bytes();
        self.write(&move_cursor)?;

        self.write(b"\x1b[?25h")?;
        self.flush()
    }

    fn rowlen(&self, index: usize) -> usize {
        let row = self.rows.as_ref().and_then(|r| r.get(index));
        row.map_or(0, |r| r.0.len())
    }

    fn move_cursor(&mut self, k: Key) {
        match k {
            Key::ArrowUp => {
                if self.cy > 0 {
                    self.cy -= 1;
                }
            },
            Key::ArrowDown => {
                if self.cy < self.numrows() {
                    self.cy += 1;
                }
            },
            Key::ArrowLeft => {
                if self.cx > 0 {
                    self.cx -= 1;
                } else if self.cy > 0 {
                    self.cy -= 1;
                    self.cx = self.rowlen(self.cy);
                }
            },
            Key::ArrowRight => {
                let row = self.rows.as_ref().and_then(|r| r.get(self.cy));
                let rowlen = row.map_or(0, |r| r.0.len());
                if self.cx < rowlen {
                    self.cx += 1;
                } else if row.is_some() && self.cx == rowlen {
                    self.cx = 0;
                    self.cy += 1;
                }
            },
            _ => (),
        }

        let rowlen = self.rowlen(self.cy);
        if self.cx > rowlen {
            self.cx = rowlen;
        }
    }

    fn process_keypress(&mut self) -> bool {
        let c = editor_read_key(&mut self.stdin);

        match c {
            Key::Character(k) if k == ctrl_key!(b'q') => {
                return false
            },
            Key::HomeKey => {
                self.cx = 0;
            },
            Key::EndKey => {
                self.cx = self.screencols - 1;
            },
            Key::PageUp | Key::PageDown => {
                let key = if c == Key::PageUp { Key::ArrowUp } else { Key::ArrowDown };
                for _ in 0..(self.screenrows) {
                    self.move_cursor(key);
                }
            },
            Key::ArrowUp | Key::ArrowDown | Key::ArrowLeft | Key::ArrowRight => {
                self.move_cursor(c);
            },
            _ => ()
        };
        true
    }

    fn open(&mut self, filename: &str) -> io::Result<()> {
        let f = File::open(filename)?;
        let file = BufReader::new(&f);
        let results: io::Result<Vec<Row>> = file.lines()
                        .map(|r| r.map(|l| Row(l)))
                        .collect();
        self.rows = Some(results?);
        Ok(())
    }
}

impl Drop for Editor {
    fn drop(&mut self) {
        // clear screen
        self.stdout.write(b"\x1b[2J").unwrap();
        self.stdout.write(b"\x1b[H").unwrap();
        self.stdout.flush().unwrap();
    }
}

fn main() {
    let mut editor = Editor::new().unwrap();
    if let Some(filename) = env::args().nth(1) {
        editor.open(&filename).unwrap();
    }

    editor.refresh_screen().unwrap();
    while editor.process_keypress() {
        editor.refresh_screen().unwrap();
    }
}
<commit_msg>Format with rustfmt<commit_after>extern crate libc;
extern crate termios;

use libc::{STDIN_FILENO, STDOUT_FILENO, TIOCGWINSZ, winsize};
use termios::{Termios, tcsetattr, TCSAFLUSH, VMIN, VTIME};
use termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON};
use termios::{OPOST, CS8};
use termios::{ECHO, ICANON, IEXTEN, ISIG};

use std::env;
use std::fs::File;
use std::io::{self, Stdin, Stdout, Read, BufRead, BufReader, Error, ErrorKind, Write};

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

#[derive(PartialEq, Clone, Copy)]
enum Key {
    Character(u8),
    ArrowLeft,
    ArrowRight,
    ArrowUp,
    ArrowDown,
    DeleteKey,
    HomeKey,
    EndKey,
    PageUp,
    PageDown,
}

macro_rules! ctrl_key {
    ($k:expr) => ($k & 0x1f);
}

struct RawMode {
    orig_term: Termios,
}

struct Row(String);

struct Editor {
    _mode: RawMode,
    cx: usize,
    cy: usize,
    rowoff: usize,
    coloff: usize,
    screenrows: usize,
    screencols: usize,
    rows: Option<Vec<Row>>,
    stdin: Stdin,
    stdout: Stdout,
}

impl RawMode {
    fn enable_raw_mode() -> io::Result<RawMode> {
        let mut term = Termios::from_fd(STDIN_FILENO)?;
        let mode = RawMode { orig_term: term.clone() };

        term.c_iflag &= !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        term.c_oflag &= !OPOST;
        term.c_cflag |= CS8;
        term.c_lflag &= !(ECHO | ICANON | IEXTEN | ISIG);
        term.c_cc[VMIN] = 0;
        term.c_cc[VTIME] = 1;

        tcsetattr(STDIN_FILENO, TCSAFLUSH, &term)?;
        Ok(mode)
    }
}

impl Drop for RawMode {
    fn drop(&mut self) {
        tcsetattr(STDIN_FILENO, TCSAFLUSH, &self.orig_term).unwrap()
    }
}

fn read_non_blocking<R: Read>(r: &mut R, buf: &mut [u8]) -> usize {
    r.read(buf)
        .or_else(|e| if e.kind() == ErrorKind::WouldBlock {
                     Ok(0)
                 } else {
                     Err(e)
                 })
        .expect("read_non_blocking")
}

fn byte_slice(s: &str, offset: usize, max_len: usize) -> &[u8] {
    if s.len() > max_len + offset {
        s[offset..(max_len + offset)].as_bytes()
    } else if s.len() > offset {
        s[offset..].as_bytes()
    } else {
        s[0..0].as_bytes()
    }
}

fn editor_read_key(stdin: &mut Stdin) -> Key {
    let mut buf = [0; 1];
    loop {
        let n = read_non_blocking(stdin, &mut buf);
        if n == 1 {
            if buf[0] == b'\x1b' {
                let mut seq = [0; 2];
                let n = read_non_blocking(stdin, &mut seq);
                if n == 2 && seq[0] == b'[' {
                    if seq[1] >= b'0' && seq[1] <= b'9' {
                        let mut last = [0; 1];
                        let n = read_non_blocking(stdin, &mut last);
                        if n == 1 {
                            if last[0] == b'~' {
                                return match seq[1] {
                                           b'1' => Key::HomeKey,
                                           b'3' => Key::DeleteKey,
                                           b'4' => Key::EndKey,
                                           b'5' => Key::PageUp,
                                           b'6' => Key::PageDown,
                                           b'7' => Key::HomeKey,
                                           b'8' => Key::EndKey,
                                           _ => Key::Character(b'\x1b'),
                                       };
                            }
                        }
                    } else {
                        return match seq[1] {
                                   b'A' => Key::ArrowUp,
                                   b'B' => Key::ArrowDown,
                                   b'C' => Key::ArrowRight,
                                   b'D' => Key::ArrowLeft,
                                   b'H' => Key::HomeKey,
                                   b'F' => Key::EndKey,
                                   _ => Key::Character(b'\x1b'),
                               };
                    }
                } else if n == 2 && seq[0] == b'O' {
                    return match seq[1] {
                               b'H' => Key::HomeKey,
                               b'F' => Key::EndKey,
                               _ => Key::Character(b'\x1b'),
                           };
                }
                return Key::Character(b'\x1b');
            } else {
                return Key::Character(buf[0]);
            }
        }
    }
}

fn get_window_size() -> io::Result<(u16, u16)> {
    let ws = winsize {
        ws_col: 0,
        ws_row: 0,
        ws_xpixel: 0,
        ws_ypixel: 0,
    };
    unsafe {
        if libc::ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0 {
            return Err(Error::new(ErrorKind::Other, "get_window_size: ioctl failed"));
        }
    }
    Ok((ws.ws_row, ws.ws_col))
}

impl Editor {
    fn new() -> io::Result<Editor> {
        let mode = RawMode::enable_raw_mode()?;
        let (rows, cols) = get_window_size()?;
        let stdin = io::stdin();
        let stdout = io::stdout();
        Ok(Editor {
               _mode: mode,
               cx: 0,
               cy: 0,
               rowoff: 0,
               coloff: 0,
               screenrows: rows as usize,
               screencols: cols as usize,
               rows: None,
               stdin: stdin,
               stdout: stdout,
           })
    }

    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.stdout.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }

    fn scroll(&mut self) {
        if self.cy < self.rowoff {
            self.rowoff = self.cy;
        }
        if self.cy >= self.rowoff + self.screenrows {
            self.rowoff = self.cy - self.screenrows + 1;
        }
        if self.cx < self.coloff {
            self.coloff = self.cx;
        }
        if self.cx >= self.coloff + self.screencols {
            self.coloff = (1 + self.cx) - self.screencols;
        }
    }

    fn numrows(&self) -> usize {
        self.rows.as_ref().map_or(0, |v| v.len())
    }

    fn draw_rows(&mut self) -> io::Result<()> {
        let numrows = self.numrows();
        for y in 0..(self.screenrows) {
            let filerow = y + self.rowoff;
            if filerow >= numrows {
                if self.rows.is_none() && y == self.screenrows / 3 {
                    let mut msg = format!("Kilo-rs editor -- version {}", VERSION);
                    msg.truncate(self.screencols);
                    let padding = (self.screencols - msg.len()) / 2;
                    if padding > 0 {
                        self.write(b"~")?;
                        for _ in 1..padding {
                            self.write(b" ")?;
                        }
                    }
                    self.write(msg.as_bytes())?;
                } else {
                    self.write(b"~")?;
                }
            } else {
                let rows = self.rows.as_ref().unwrap();
                self.stdout
                    .write(byte_slice(&rows[filerow].0, self.coloff, self.screencols))?;
            }

            self.write(b"\x1b[K")?;
            if y < self.screenrows - 1 {
                self.write(b"\r\n")?;
            }
        }
        Ok(())
    }

    fn refresh_screen(&mut self) -> io::Result<()> {
        self.scroll();

        self.write(b"\x1b[?25l")?;
        self.write(b"\x1b[H")?;

        self.draw_rows()?;

        let move_cursor = format!("\x1b[{};{}H",
                                  (self.cy - self.rowoff) + 1,
                                  (self.cx - self.coloff) + 1)
                .into_bytes();
        self.write(&move_cursor)?;

        self.write(b"\x1b[?25h")?;
        self.flush()
    }

    fn rowlen(&self, index: usize) -> usize {
        let row = self.rows.as_ref().and_then(|r| r.get(index));
        row.map_or(0, |r| r.0.len())
    }

    fn move_cursor(&mut self, k: Key) {
        match k {
            Key::ArrowUp => {
                if self.cy > 0 {
                    self.cy -= 1;
                }
            }
            Key::ArrowDown => {
                if self.cy < self.numrows() {
                    self.cy += 1;
                }
            }
            Key::ArrowLeft => {
                if self.cx > 0 {
                    self.cx -= 1;
                } else if self.cy > 0 {
                    self.cy -= 1;
                    self.cx = self.rowlen(self.cy);
                }
            }
            Key::ArrowRight => {
                let row = self.rows.as_ref().and_then(|r| r.get(self.cy));
                let rowlen = row.map_or(0, |r| r.0.len());
                if self.cx < rowlen {
                    self.cx += 1;
                } else if row.is_some() && self.cx == rowlen {
                    self.cx = 0;
                    self.cy += 1;
                }
            }
            _ => (),
        }

        let rowlen = self.rowlen(self.cy);
        if self.cx > rowlen {
            self.cx = rowlen;
        }
    }

    fn process_keypress(&mut self) -> bool {
        let c = editor_read_key(&mut self.stdin);

        match c {
            Key::Character(k) if k == ctrl_key!(b'q') => return false,
            Key::HomeKey => {
                self.cx = 0;
            }
            Key::EndKey => {
                self.cx = self.screencols - 1;
            }
            Key::PageUp | Key::PageDown => {
                let key = if c == Key::PageUp {
                    Key::ArrowUp
                } else {
                    Key::ArrowDown
                };
                for _ in 0..(self.screenrows) {
                    self.move_cursor(key);
                }
            }
            Key::ArrowUp | Key::ArrowDown | Key::ArrowLeft | Key::ArrowRight => {
                self.move_cursor(c);
            }
            _ => (),
        };
        true
    }

    fn open(&mut self, filename: &str) -> io::Result<()> {
        let f = File::open(filename)?;
        let file = BufReader::new(&f);
        let results: io::Result<Vec<Row>> = file.lines().map(|r| r.map(|l| Row(l))).collect();
        self.rows = Some(results?);
        Ok(())
    }
}

impl Drop for Editor {
    fn drop(&mut self) {
        // clear screen
        self.stdout.write(b"\x1b[2J").unwrap();
        self.stdout.write(b"\x1b[H").unwrap();
        self.stdout.flush().unwrap();
    }
}

fn main() {
    let mut editor = Editor::new().unwrap();
    if let Some(filename) = env::args().nth(1) {
        editor.open(&filename).unwrap();
    }

    editor.refresh_screen().unwrap();
    while editor.process_keypress() {
        editor.refresh_screen().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::io::BufWriter;
extern crate time;
extern crate toml;
extern crate rawloader;
use rawloader::decoders;

fn usage() {
  println!("rawloader <file>");
  std::process::exit(1);
}

fn error(err: &str) {
  println!("ERROR: {}", err);
  std::process::exit(2);
}

fn main() {
  let args: Vec<_> = env::args().collect();
  if args.len() != 2 {
    usage();
  }
  let file = &args[1];
  println!("Loading file \"{}\"", file);

  let rawloader = decoders::RawLoader::new();
  let from_time = time::precise_time_ns();
  let image = match rawloader.decode_safe(file) {
    Ok(val) => val,
    Err(e) => {error(&e);unreachable!()},
  };
  let to_time = time::precise_time_ns();
  println!("Decoded in {} ms", (to_time - from_time)/1000000);

  println!("Found camera \"{}\" model \"{}\"", image.make, image.model);
  println!("Found canonical named camera \"{}\" model \"{}\"", image.canonical_make, image.canonical_model);
  println!("Image size is {}x{}", image.width, image.height);
  println!("WB coeffs are {:?}", image.wb_coeffs);
  println!("black levels are {:?}", image.blacklevels);
  println!("white levels are {:?}", image.whitelevels);
  println!("color matrix is {:?}", image.color_matrix);
  println!("dcraw filters is {:#x}", image.dcraw_filters);
  println!("crops are {:?}", image.crops);

  let mut sum: u64 = 0;
  for i in 0..(image.width*image.height) {
    sum += image.data[i as usize] as u64;
  }
  println!("Image sum: {}", sum);
  let count: u64 = (image.width as u64) * (image.height as u64);
  println!("Image avg: {}", sum/count);

  let uf = match File::create(format!("{}.ppm",file)) {
    Ok(val) => val,
    Err(e) => {error(e.description());unreachable!()},
  };
  let mut f = BufWriter::new(uf);
  let preamble = format!("P6 {} {} {}\n", image.width, image.height, image.whitelevels[0]).into_bytes();
  if let Err(err) = f.write_all(&preamble) {
    error(err.description());
  }
  for row in 0..image.height {
    let from: usize = (row as usize) * (image.width as usize);
    let to: usize = ((row+1) as usize) * (image.width as usize);
    let imgline = &image.data[from .. to];

    for pixel in imgline {
      let bytes = [(pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8];
       if let Err(err) = f.write_all(&bytes) {
        error(err.description());
      }
    }
  }
}
<commit_msg>Add optional argument to decide where to write ppm<commit_after>use std::env;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::io::BufWriter;
extern crate time;
extern crate toml;
extern crate rawloader;
use rawloader::decoders;

fn usage() {
  println!("rawloader <file> [outfile]");
  std::process::exit(1);
}

fn error(err: &str) {
  println!("ERROR: {}", err);
  std::process::exit(2);
}

fn main() {
  let args: Vec<_> = env::args().collect();
  if args.len() < 2 {
    usage();
  }
  let file = &args[1];
  let fileppm = format!("{}.ppm",file);
  let outfile = if args.len() > 2 {
    &args[2]
  } else {
    &fileppm
  };
  println!("Loading file \"{}\" and saving it as \"{}\"", file, outfile);

  let rawloader = decoders::RawLoader::new();
  let from_time = time::precise_time_ns();
  let image = match rawloader.decode_safe(file) {
    Ok(val) => val,
    Err(e) => {error(&e);unreachable!()},
  };
  let to_time = time::precise_time_ns();
  println!("Decoded in {} ms", (to_time - from_time)/1000000);

  println!("Found camera \"{}\" model \"{}\"", image.make, image.model);
  println!("Found canonical named camera \"{}\" model \"{}\"", image.canonical_make, image.canonical_model);
  println!("Image size is {}x{}", image.width, image.height);
  println!("WB coeffs are {:?}", image.wb_coeffs);
  println!("black levels are {:?}", image.blacklevels);
  println!("white levels are {:?}", image.whitelevels);
  println!("color matrix is {:?}", image.color_matrix);
  println!("dcraw filters is {:#x}", image.dcraw_filters);
  println!("crops are {:?}", image.crops);

  let mut sum: u64 = 0;
  for i in 0..(image.width*image.height) {
    sum += image.data[i as usize] as u64;
  }
  println!("Image sum: {}", sum);
  let count: u64 = (image.width as u64) * (image.height as u64);
  println!("Image avg: {}", sum/count);

  let uf = match File::create(outfile) {
    Ok(val) => val,
    Err(e) => {error(e.description());unreachable!()},
  };
  let mut f = BufWriter::new(uf);
  let preamble = format!("P6 {} {} {}\n", image.width, image.height, image.whitelevels[0]).into_bytes();
  if let Err(err) = f.write_all(&preamble) {
    error(err.description());
  }
  for row in 0..image.height {
    let from: usize = (row as usize) * (image.width as usize);
    let to: usize = ((row+1) as usize) * (image.width as usize);
    let imgline = &image.data[from .. to];

    for pixel in imgline {
      let bytes = [(pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8];
       if let Err(err) = f.write_all(&bytes) {
        error(err.description());
      }
    }
  }
}
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]

extern crate curl;
extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_curl;

#[macro_use]
extern crate clap;
extern crate chrono;
extern crate histogram;

#[macro_use]
#[cfg(test)]
extern crate quickcheck;

mod args;
mod misc;

use args::{Config, parse_args};

use curl::easy::Easy;
use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_curl::{Session, PerformError};
use chrono::*;
use std::sync::mpsc::channel;
use histogram::*;
use std::thread;

struct RequestResult {
    latency: Duration,
}

impl RequestResult {
    fn new(latency: Duration) -> Self {
        RequestResult { latency: latency }
    }
}

impl Default for RequestResult {
    fn default() -> Self {
        RequestResult { latency: Duration::zero() }
    }
}

fn send_request(easy_request: Easy,
                session: &Session)
                -> impl Future<Item = (RequestResult, Easy), Error = PerformError> {
    session.perform(easy_request)
        .and_then(|mut easy| {
            let latency = easy.total_time()
                .ok()
                .and_then(|x| Duration::from_std(x).ok())
                .unwrap();
            let request_result = RequestResult::new(latency);
            Ok((request_result, easy))
        })
}

struct RunInfo {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    pub duration: Duration,
    histogram: Histogram,
    /// Number of failed requests
    num_failed_requests: usize,
}

impl RunInfo {
    fn new(duration: Duration) -> Self {
        RunInfo {
            requests_completed: 0,
            num_failed_requests: 0,
            duration: duration,
            histogram: Histogram::new(),
        }
    }
    pub fn requests_per_second(&self) -> f32 {
        (self.requests_completed as f32) / (self.duration.num_seconds() as f32)
    }

    fn merge(&mut self, other: &Self) {
        self.requests_completed += other.requests_completed;
        self.num_failed_requests += other.num_failed_requests;
        self.histogram.merge(&other.histogram);
    }
}

/// Delegates and manages all the work.
struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

fn make_easy(url: &str) -> Easy {
    let mut easy_request = Easy::new();
    easy_request.get(true).unwrap();
    easy_request.url(&url).unwrap();
    easy_request
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self,
                           desired_connections: usize,
                           url: String,
                           duration: Duration)
                           -> RunInfo {
        let (tx, rx) = channel();
        let desired_connections_per_worker_iter = misc::split_number(desired_connections,
                                                                     self.num_threads);
        // start num_threads workers
        for desired_connections_per_worker in desired_connections_per_worker_iter {
            let tx = tx.clone();
            let url = url.clone();
            thread::spawn(move || {
                let mut lp = Core::new().unwrap();
                let start_time = Local::now();
                let wanted_end_time = start_time + duration;
                let session = Session::new(lp.handle());

                let iterator = (0..desired_connections_per_worker).map(|_| {

                    let runinfo = RunInfo::new(duration);
                    let easy_request = make_easy(&url);
                    loop_fn((runinfo, easy_request), |(mut runinfo, easy_request)| {
                        send_request(easy_request, &session)
                            .then(|res| -> Result<_, ()> { match res {
                                // on request success
                                Ok((request_res, easy_request)) => {
                                    // update histogram
                                    request_res.latency.num_nanoseconds()
                                        .map(|x| runinfo.histogram.increment(x as u64).ok());
                                    runinfo.requests_completed += 1;

                                    let state = (runinfo, easy_request);

                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                                // on request failure
                                Err(mut err) => {
                                    runinfo.num_failed_requests += 1;
                                    // attempt to recover the easy handle from the error,
                                    // else make a new handle
                                    let easy_request = err.take_easy().unwrap_or(make_easy(&url));
                                    let state = (runinfo, easy_request);
                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                            }})
                            .map_err(|_| ())
                    })
                        // Extract latency histogram
                        .map(|(histogram, _)| histogram)
                });
                let future = stream::futures_unordered(iterator)
                    .fold(RunInfo::new(duration), |mut runinfo_acc, runinfo| {
                        runinfo_acc.merge(&runinfo);
                        ok(runinfo_acc)
                    });
                let res = lp.run(future).unwrap();
                tx.send(res).unwrap();
            });
        }
        // collect information from all workers
        rx.iter()
            .take(self.num_threads)
            .fold(RunInfo::new(duration), |mut runinfo_acc, runinfo| {
                runinfo_acc.merge(&runinfo);
                runinfo_acc
            })
    }
}

fn start(config: Config) -> RunInfo {
    let boss = Boss::new(config.num_threads);
    boss.start_workforce(config.num_connections, config.url, config.duration)
}

fn nanoseconds_to_milliseconds(nanoseconds: u64) -> f64 {
    nanoseconds as f64 / 1_000_000_f64
}

/// Presents the results to the user
fn present(run_info: RunInfo) {
    let requests_completed = run_info.requests_completed;
    println!("{} requests in {}s",
             requests_completed,
             run_info.duration.num_seconds());
    println!("{} failed requests", run_info.num_failed_requests);
    println!("Requests per second: {}", run_info.requests_per_second());
    println!("Latency distribution: \n50%: {} ms\n75%: {} ms\n90%: {} ms\n95%: {} ms\n99%: {} ms",
        run_info.histogram.percentile(50.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(75.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(90.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(95.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(99.0).map(nanoseconds_to_milliseconds).unwrap(),
    );
}

fn main() {
    env_logger::init().unwrap();
    let config = parse_args();
    let run_info = start(config);
    present(run_info)
}
<commit_msg>only attempt to print latency distribution if histogram has data<commit_after>#![feature(conservative_impl_trait)]

extern crate curl;
extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_curl;

#[macro_use]
extern crate clap;
extern crate chrono;
extern crate histogram;

#[macro_use]
#[cfg(test)]
extern crate quickcheck;

mod args;
mod misc;

use args::{Config, parse_args};

use curl::easy::Easy;
use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_curl::{Session, PerformError};
use chrono::*;
use std::sync::mpsc::channel;
use histogram::*;
use std::thread;

struct RequestResult {
    latency: Duration,
}

impl RequestResult {
    fn new(latency: Duration) -> Self {
        RequestResult { latency: latency }
    }
}

impl Default for RequestResult {
    fn default() -> Self {
        RequestResult { latency: Duration::zero() }
    }
}

fn send_request(easy_request: Easy,
                session: &Session)
                -> impl Future<Item = (RequestResult, Easy), Error = PerformError> {
    session.perform(easy_request)
        .and_then(|mut easy| {
            let latency = easy.total_time()
                .ok()
                .and_then(|x| Duration::from_std(x).ok())
                .unwrap();
            let request_result = RequestResult::new(latency);
            Ok((request_result, easy))
        })
}

struct RunInfo {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    pub duration: Duration,
    histogram: Histogram,
    /// Number of failed requests
    num_failed_requests: usize,
}

impl RunInfo {
    fn new(duration: Duration) -> Self {
        RunInfo {
            requests_completed: 0,
            num_failed_requests: 0,
            duration: duration,
            histogram: Histogram::new(),
        }
    }
    pub fn requests_per_second(&self) -> f32 {
        (self.requests_completed as f32) / (self.duration.num_seconds() as f32)
    }

    fn merge(&mut self, other: &Self) {
        self.requests_completed += other.requests_completed;
        self.num_failed_requests += other.num_failed_requests;
        self.histogram.merge(&other.histogram);
    }
}

/// Delegates and manages all the work.
struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

fn make_easy(url: &str) -> Easy {
    let mut easy_request = Easy::new();
    easy_request.get(true).unwrap();
    easy_request.url(&url).unwrap();
    easy_request
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self,
                           desired_connections: usize,
                           url: String,
                           duration: Duration)
                           -> RunInfo {
        let (tx, rx) = channel();
        let desired_connections_per_worker_iter = misc::split_number(desired_connections,
                                                                     self.num_threads);
        // start num_threads workers
        for desired_connections_per_worker in desired_connections_per_worker_iter {
            let tx = tx.clone();
            let url = url.clone();
            thread::spawn(move || {
                let mut lp = Core::new().unwrap();
                let start_time = Local::now();
                let wanted_end_time = start_time + duration;
                let session = Session::new(lp.handle());

                let iterator = (0..desired_connections_per_worker).map(|_| {

                    let runinfo = RunInfo::new(duration);
                    let easy_request = make_easy(&url);
                    loop_fn((runinfo, easy_request), |(mut runinfo, easy_request)| {
                        send_request(easy_request, &session)
                            .then(|res| -> Result<_, ()> { match res {
                                // on request success
                                Ok((request_res, easy_request)) => {
                                    // update histogram
                                    request_res.latency.num_nanoseconds()
                                        .map(|x| runinfo.histogram.increment(x as u64).ok());
                                    runinfo.requests_completed += 1;

                                    let state = (runinfo, easy_request);

                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                                // on request failure
                                Err(mut err) => {
                                    runinfo.num_failed_requests += 1;
                                    // attempt to recover the easy handle from the error,
                                    // else make a new handle
                                    let easy_request = err.take_easy().unwrap_or(make_easy(&url));
                                    let state = (runinfo, easy_request);
                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                            }})
                            .map_err(|_| ())
                    })
                        // Extract latency histogram
                        .map(|(histogram, _)| histogram)
                });
                let future = stream::futures_unordered(iterator)
                    .fold(RunInfo::new(duration), |mut runinfo_acc, runinfo| {
                        runinfo_acc.merge(&runinfo);
                        ok(runinfo_acc)
                    });
                let res = lp.run(future).unwrap();
                tx.send(res).unwrap();
            });
        }
        // collect information from all workers
        rx.iter()
            .take(self.num_threads)
            .fold(RunInfo::new(duration), |mut runinfo_acc, runinfo| {
                runinfo_acc.merge(&runinfo);
                runinfo_acc
            })
    }
}

fn start(config: Config) -> RunInfo {
    let boss = Boss::new(config.num_threads);
    boss.start_workforce(config.num_connections, config.url, config.duration)
}

fn nanoseconds_to_milliseconds(nanoseconds: u64) -> f64 {
    nanoseconds as f64 / 1_000_000_f64
}

/// Presents the results to the user
fn present(run_info: RunInfo) {
    let requests_completed = run_info.requests_completed;
    println!("{} requests in {}s",
             requests_completed,
             run_info.duration.num_seconds());
    println!("{} failed requests", run_info.num_failed_requests);
    println!("Requests per second: {}", run_info.requests_per_second());

    // we can only print the latency distribution if there is data in the histogram
    if run_info.histogram.entries() > 0 {
        println!("Latency distribution: \n50%: {} ms\n75%: {} ms\n90%: {} ms\n95%: {} ms\n99%: {} ms",
            run_info.histogram.percentile(50.0).map(nanoseconds_to_milliseconds).unwrap(),
            run_info.histogram.percentile(75.0).map(nanoseconds_to_milliseconds).unwrap(),
            run_info.histogram.percentile(90.0).map(nanoseconds_to_milliseconds).unwrap(),
            run_info.histogram.percentile(95.0).map(nanoseconds_to_milliseconds).unwrap(),
            run_info.histogram.percentile(99.0).map(nanoseconds_to_milliseconds).unwrap(),
        );
    }

}

fn main() {
    env_logger::init().unwrap();
    let config = parse_args();
    let run_info = start(config);
    present(run_info)
}
<|endoftext|>


<commit_before>#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate board_game_geom as geom;
extern crate piston_window;

use geom::{Geom, Move, Point, Size, Table};

use piston_window::{Button, Context, Graphics, MouseButton, MouseCursorEvent, PistonWindow, PressEvent, ReleaseEvent, Transformed, WindowSettings};
use piston_window::types::Color;

const BOARD_ROWS: usize = 8;
const BOARD_COLS: usize = 8;

const CELL_WIDTH: f64 = 80.0;
const CELL_HEIGHT: f64 = 80.0;

const BOARD_WIDTH: f64 = CELL_WIDTH * (BOARD_COLS as f64);
const BOARD_HEIGHT: f64 = CELL_HEIGHT * (BOARD_ROWS as f64);
const BOARD_H_MARGIN: f64 = 40.0;
const BOARD_V_MARGIN: f64 = 40.0;

const DOT_RADIUS: f64 = 6.0;
const DOT_DIAMETER: f64 = DOT_RADIUS * 2.0;

const DISK_RADIUS: f64 = 32.0;
const DISK_DIAMETER: f64 = DISK_RADIUS * 2.0;

const WINDOW_WIDTH: u32 = (BOARD_H_MARGIN * 2.0 + BOARD_WIDTH + 0.5) as u32;
const WINDOW_HEIGHT: u32 = (BOARD_V_MARGIN * 2.0 + BOARD_HEIGHT + 0.5) as u32;

const BLACK: Color = [0.0, 0.0, 0.0, 1.0];
const WHITE: Color = [1.0, 1.0, 1.0, 1.0];
const GREEN: Color = [0.0, 0.5, 0.0, 1.0];

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Cell {
    Black, White
}

impl Into<Color> for Cell {
    fn into(self) -> Color {
        match self {
            Cell::Black => BLACK,
            Cell::White => WHITE,
        }
    }
}

impl Cell {
    fn flip(self) -> Cell {
        match self {
            Cell::Black => Cell::White,
            Cell::White => Cell::Black,
        }
    }
}

#[derive(Clone, Debug)]
struct Board {
    cells: Table<Option<Cell>>,
    turn: Option<Cell>,
}

impl Board {
    fn new() -> Board {
        let size = Size(8, 8);
        let mut board = Board {
            cells: Table::new_empty(size, None, None),
            turn: Some(Cell::Black)
        };
        board.cells[Point(3, 3)] = Some(Cell::White);
        board.cells[Point(4, 4)] = Some(Cell::White);
        board.cells[Point(3, 4)] = Some(Cell::Black);
        board.cells[Point(4, 3)] = Some(Cell::Black);
        board
    }

    fn can_locate(&self, pt: Point) -> bool {
        if self.turn.is_none() {
            return false;
        }

        if !self.cells.contains(pt) || self.cells[pt].is_some() {
            return false
        }

        for &mv in &Move::ALL_ADJACENTS {
            if self.can_locate_mv(pt, mv).is_some() {
                return true
            }
        }

        false
    }

    fn can_locate_mv(&self, pt: Point, mv: Move) -> Option<Point> {
        let turn = if let Some(turn) = self.turn {
            turn
        } else {
            return None
        };

        let flip = turn.flip();

        let mut pt = pt + mv;
        if !self.cells.contains(pt) || self.cells[pt] != Some(flip) {
            return None
        }

        while self.cells.contains(pt) {
            if let Some(x) = self.cells[pt] {
                pt = pt + mv;
                if x == flip {
                    continue
                }
                return Some(pt)
            }
            return None
        }
        None
    }

    fn locate(&mut self, pt: Point) {
        let turn = if let Some(turn) = self.turn {
            turn
        } else {
            return
        };
        let flip = turn.flip();

        if !self.can_locate(pt) {
            return
        }

        for &mv in &Move::ALL_ADJACENTS {
            if let Some(end) = self.can_locate_mv(pt, mv) {
                let mut pt = pt;
                while pt != end {
                    self.cells[pt] = Some(turn);
                    pt = pt + mv;
                }
            }
        }

        self.turn = Some(flip);
        for pt in self.cells.points() {
            if self.can_locate(pt) {
                return
            }
        }

        self.turn = Some(turn);
        for pt in self.cells.points() {
            if self.can_locate(pt) {
                return
            }
        }

        self.turn = None;
    }
}

fn draw_2d<G>(c: Context, g: &mut G, board: &mut Board, mouse_pos: Option<Point>)
    where G: Graphics
{
    piston_window::clear(GREEN, g);
    let board_trans = c.transform.trans(BOARD_H_MARGIN, BOARD_V_MARGIN);

    // draw lines
    for y in 0..(BOARD_ROWS + 1) {
        let fy = (y as f64) * CELL_HEIGHT;
        piston_window::line(BLACK, 1.0, [0.0, fy, BOARD_WIDTH, fy], board_trans, g);
    }
    for x in 0..(BOARD_COLS + 1) {
        let fx = (x as f64) * CELL_WIDTH;
        piston_window::line(BLACK, 1.0, [fx, 0.0, fx, BOARD_HEIGHT], board_trans, g);
    }

    // draw dots
    for x in 0..2 {
        let fx = ((x * 4 + 2) as f64) * CELL_WIDTH - DOT_RADIUS;
        for y in 0..2 {
            let fy = ((y * 4 + 2) as f64) * CELL_HEIGHT - DOT_RADIUS;
            piston_window::ellipse(BLACK, [fx, fy, DOT_DIAMETER, DOT_DIAMETER], board_trans, g)
        }
    }

    // draw disks
    for x in 0..BOARD_COLS {
        let fx = (x as f64 + 0.5) * CELL_WIDTH - DISK_RADIUS;
        for y in 0..BOARD_ROWS {
            let fy = (y as f64 + 0.5) * CELL_HEIGHT - DISK_RADIUS;
            let pt = Point(x as i32, y as i32);
            match board.cells[pt] {
                Some(cell) => {
                    piston_window::ellipse(cell.into(), [fx, fy, DISK_DIAMETER, DISK_DIAMETER], board_trans, g);
                }
                None => {
                    if let Some(turn) = board.turn {
                        if board.can_locate(pt) {
                            let mut color: Color = turn.into();
                            color[3] = if mouse_pos == Some(pt) { 0.7 } else { 0.3 };
                            piston_window::ellipse(color, [fx, fy, DISK_DIAMETER, DISK_DIAMETER], board_trans, g);
                        }
                    }
                }
            }
        }
    }
}

fn update_mouse_pos(e: &PistonWindow, pt: &mut Option<Point>) {
    if let Some(pos) = e.mouse_cursor_args() {
        let fx = (pos[0] - BOARD_H_MARGIN) / CELL_WIDTH;
        let fy = (pos[1] - BOARD_V_MARGIN) / CELL_HEIGHT;
        if fx < 0.0 || fx > (BOARD_COLS as f64) || fy < 0.0 || fy > (BOARD_ROWS as f64) {
            *pt = None;
        } else {
            *pt = Some(Point(fx as i32, fy as i32));
        }
    }
}

fn main() {
    let window: PistonWindow = WindowSettings::new("Othello", (WINDOW_WIDTH, WINDOW_HEIGHT))
        .exit_on_esc(true)
        .build()
        .unwrap_or_else(|e| panic!("Failed to build PistonWindow: {}", e));
    let mut board = Board::new();
    let mut mouse_pos = None;
    let mut mouse_press_pos = None;

    for e in window {
        e.draw_2d(|c, g| draw_2d(c, g, &mut board, mouse_pos));

        update_mouse_pos(&e, &mut mouse_pos);

        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                mouse_press_pos = mouse_pos;
            }
        }

        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) {
                if mouse_pos == mouse_press_pos {
                    if let Some(pt) = mouse_pos {
                        board.locate(pt);
                    }
                }
                mouse_press_pos = None;
            }
        }
    }
}
<commit_msg>Run rustfmt<commit_after>#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate board_game_geom as geom;
extern crate piston_window;

use geom::{Geom, Move, Point, Size, Table};

use piston_window::{Button, Context, Graphics, MouseButton, MouseCursorEvent, PistonWindow,
                    PressEvent, ReleaseEvent, Transformed, WindowSettings};
use piston_window::types::Color;

const BOARD_ROWS: usize = 8;
const BOARD_COLS: usize = 8;

const CELL_WIDTH: f64 = 80.0;
const CELL_HEIGHT: f64 = 80.0;

const BOARD_WIDTH: f64 = CELL_WIDTH * (BOARD_COLS as f64);
const BOARD_HEIGHT: f64 = CELL_HEIGHT * (BOARD_ROWS as f64);
const BOARD_H_MARGIN: f64 = 40.0;
const BOARD_V_MARGIN: f64 = 40.0;

const DOT_RADIUS: f64 = 6.0;
const DOT_DIAMETER: f64 = DOT_RADIUS * 2.0;

const DISK_RADIUS: f64 = 32.0;
const DISK_DIAMETER: f64 = DISK_RADIUS * 2.0;

const WINDOW_WIDTH: u32 = (BOARD_H_MARGIN * 2.0 + BOARD_WIDTH + 0.5) as u32;
const WINDOW_HEIGHT: u32 = (BOARD_V_MARGIN * 2.0 + BOARD_HEIGHT + 0.5) as u32;

const BLACK: Color = [0.0, 0.0, 0.0, 1.0];
const WHITE: Color = [1.0, 1.0, 1.0, 1.0];
const GREEN: Color = [0.0, 0.5, 0.0, 1.0];

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Cell {
    Black,
    White,
}

impl Into<Color> for Cell {
    fn into(self) -> Color {
        match self {
            Cell::Black => BLACK,
            Cell::White => WHITE,
        }
    }
}

impl Cell {
    fn flip(self) -> Cell {
        match self {
            Cell::Black => Cell::White,
            Cell::White => Cell::Black,
        }
    }
}

#[derive(Clone, Debug)]
struct Board {
    cells: Table<Option<Cell>>,
    turn: Option<Cell>,
}

impl Board {
    fn new() -> Board {
        let size = Size(8, 8);
        let mut board = Board {
            cells: Table::new_empty(size, None, None),
            turn: Some(Cell::Black),
        };
        board.cells[Point(3, 3)] = Some(Cell::White);
        board.cells[Point(4, 4)] = Some(Cell::White);
        board.cells[Point(3, 4)] = Some(Cell::Black);
        board.cells[Point(4, 3)] = Some(Cell::Black);
        board
    }

    fn can_locate(&self, pt: Point) -> bool {
        if self.turn.is_none() {
            return false;
        }

        if !self.cells.contains(pt) || self.cells[pt].is_some() {
            return false;
        }

        for &mv in &Move::ALL_ADJACENTS {
            if self.can_locate_mv(pt, mv).is_some() {
                return true;
            }
        }

        false
    }

    fn can_locate_mv(&self, pt: Point, mv: Move) -> Option<Point> {
        let turn = if let Some(turn) = self.turn {
            turn
        } else {
            return None;
        };

        let flip = turn.flip();

        let mut pt = pt + mv;
        if !self.cells.contains(pt) || self.cells[pt] != Some(flip) {
            return None;
        }

        while self.cells.contains(pt) {
            if let Some(x) = self.cells[pt] {
                pt = pt + mv;
                if x == flip {
                    continue;
                }
                return Some(pt);
            }
            return None;
        }
        None
    }

    fn locate(&mut self, pt: Point) {
        let turn = if let Some(turn) = self.turn {
            turn
        } else {
            return;
        };
        let flip = turn.flip();

        if !self.can_locate(pt) {
            return;
        }

        for &mv in &Move::ALL_ADJACENTS {
            if let Some(end) = self.can_locate_mv(pt, mv) {
                let mut pt = pt;
                while pt != end {
                    self.cells[pt] = Some(turn);
                    pt = pt + mv;
                }
            }
        }

        self.turn = Some(flip);
        for pt in self.cells.points() {
            if self.can_locate(pt) {
                return;
            }
        }

        self.turn = Some(turn);
        for pt in self.cells.points() {
            if self.can_locate(pt) {
                return;
            }
        }

        self.turn = None;
    }
}

fn draw_2d<G>(c: Context, g: &mut G, board: &mut Board, mouse_pos: Option<Point>)
    where G: Graphics
{
    piston_window::clear(GREEN, g);
    let board_trans = c.transform.trans(BOARD_H_MARGIN, BOARD_V_MARGIN);

    // draw lines
    for y in 0..(BOARD_ROWS + 1) {
        let fy = (y as f64) * CELL_HEIGHT;
        piston_window::line(BLACK, 1.0, [0.0, fy, BOARD_WIDTH, fy], board_trans, g);
    }
    for x in 0..(BOARD_COLS + 1) {
        let fx = (x as f64) * CELL_WIDTH;
        piston_window::line(BLACK, 1.0, [fx, 0.0, fx, BOARD_HEIGHT], board_trans, g);
    }

    // draw dots
    for x in 0..2 {
        let fx = ((x * 4 + 2) as f64) * CELL_WIDTH - DOT_RADIUS;
        for y in 0..2 {
            let fy = ((y * 4 + 2) as f64) * CELL_HEIGHT - DOT_RADIUS;
            piston_window::ellipse(BLACK, [fx, fy, DOT_DIAMETER, DOT_DIAMETER], board_trans, g)
        }
    }

    // draw disks
    for x in 0..BOARD_COLS {
        let fx = (x as f64 + 0.5) * CELL_WIDTH - DISK_RADIUS;
        for y in 0..BOARD_ROWS {
            let fy = (y as f64 + 0.5) * CELL_HEIGHT - DISK_RADIUS;
            let pt = Point(x as i32, y as i32);
            match board.cells[pt] {
                Some(cell) => {
                    piston_window::ellipse(cell.into(),
                                           [fx, fy, DISK_DIAMETER, DISK_DIAMETER],
                                           board_trans,
                                           g);
                }
                None => {
                    if let Some(turn) = board.turn {
                        if board.can_locate(pt) {
                            let mut color: Color = turn.into();
                            color[3] = if mouse_pos == Some(pt) {
                                0.7
                            } else {
                                0.3
                            };
                            piston_window::ellipse(color,
                                                   [fx, fy, DISK_DIAMETER, DISK_DIAMETER],
                                                   board_trans,
                                                   g);
                        }
                    }
                }
            }
        }
    }
}

fn update_mouse_pos(e: &PistonWindow, pt: &mut Option<Point>) {
    if let Some(pos) = e.mouse_cursor_args() {
        let fx = (pos[0] - BOARD_H_MARGIN) / CELL_WIDTH;
        let fy = (pos[1] - BOARD_V_MARGIN) / CELL_HEIGHT;
        if fx < 0.0 || fx > (BOARD_COLS as f64) || fy < 0.0 || fy > (BOARD_ROWS as f64) {
            *pt = None;
        } else {
            *pt = Some(Point(fx as i32, fy as i32));
        }
    }
}

fn main() {
    let window: PistonWindow = WindowSettings::new("Othello", (WINDOW_WIDTH, WINDOW_HEIGHT))
                                   .exit_on_esc(true)
                                   .build()
                                   .unwrap_or_else(|e| {
                                       panic!("Failed to build PistonWindow: {}", e)
                                   });
    let mut board = Board::new();
    let mut mouse_pos = None;
    let mut mouse_press_pos = None;

    for e in window {
        e.draw_2d(|c, g| draw_2d(c, g, &mut board, mouse_pos));

        update_mouse_pos(&e, &mut mouse_pos);

        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                mouse_press_pos = mouse_pos;
            }
        }

        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) {
                if mouse_pos == mouse_press_pos {
                    if let Some(pt) = mouse_pos {
                        board.locate(pt);
                    }
                }
                mouse_press_pos = None;
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::rc::Rc;
use std::str::SplitWhitespace;
use std::slice::Iter;
use std::cell::RefCell;

pub struct Command<'a> {
    command: Vec<&'a str>,
    exec: Box<RefCell<FnMut(Vec<&str>) + 'a>>,
    complete: Option<Box<RefCell<FnMut(Vec<&str>) -> Vec<&str> + 'a>>>
}

impl<'a> Command<'a> {
    fn new<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) -> Vec<&str> + 'a>(cmd: Vec<&'a str>, exec_handler: T, complete_handler: Option<U>) -> Command<'a> {
        let mut complete_cb:Option<Box<RefCell<FnMut(Vec<&str>) -> Vec<&str>>>> = None;
        if let Some(cb) = complete_handler {
            complete_cb = Some(Box::new(RefCell::new(cb)));
        }

        Command {
            command: cmd,
            exec: Box::new(RefCell::new(exec_handler)),
            complete: complete_cb
        }
    }
}

pub struct Cli<'a> {
    commands: HashMap<&'a str, Cli<'a>>,
    handler: Option<Rc<Command<'a>>>
}

impl<'a> Cli<'a>{

    fn new() -> Cli<'a> {
        Cli {
            commands: HashMap::new(),
            handler: None
        }
    }

    fn register<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) -> Vec<&str> + 'a>(&mut self, cmd: Vec<&'a str>, exec: T) -> Result<(), ()> {
        let tmp = Rc::new(Command::new(cmd.clone(), exec, None::<U>));

        match self._register(cmd.iter(), tmp.clone()) {
            Ok(_) => Ok(()),
            Err(_) => {
                //TODO: this can only happen if we register "Vec::new()" ... probably disallow that at all
                self.handler = Some(tmp.clone());
                Err(())
            }
        }
    }

    fn register_dyn_complete<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) -> Vec<&str> + 'a>(&mut self, cmd: Vec<&'a str>, exec: T, complete: U) -> Result<(), ()> {
        let tmp = Rc::new(Command::new(cmd.clone(), exec, Some(complete)));

        match self._register(cmd.iter(), tmp.clone()) {
            Ok(_) => Ok(()),
            Err(_) => {
                //TODO: this can only happen if we register "Vec::new()" ... probably disallow that at all
                self.handler = Some(tmp.clone());
                Err(())
            }
        }
    }

    fn _register(&mut self, mut it: Iter<&'a str>, command: Rc<Command<'a>>) -> Result<(), ()> {
        if let Some(portion) = it.next() {
            if !self.commands.contains_key(portion) {
                let mut cli = Cli::new();
                if let Err(_) = cli._register(it, command.clone()) {
                    cli.handler = Some(command.clone())
                }
                self.commands.insert(portion, cli);
            } else {
                if let Some(cmd) = self.commands.get_mut(portion) {
                    if let Err(_) = cmd._register(it, command.clone()) {
                        cmd.handler = Some(command.clone())
                    }
                }
            };
            Ok(())
        } else {
            Err(())
        }
    }

    fn complete(&mut self, argv: &'a str) -> Vec<&str> {
        println!("complete for '{}'", argv.trim());
        let portions = argv.trim().split_whitespace();

        match self._complete(portions) {
            Ok(ret) => ret,
            Err(_) => Vec::new()
        }
    }

    fn _complete(&mut self, mut portions: SplitWhitespace<'a>) -> Result<Vec<&'a str>, ()> {

        if let Some(ref portion) = portions.next() {
            if let Some(cmd) = self.commands.get_mut(portion) {
                return cmd._complete(portions);
            }

            let mut ret:Vec<&str> = Vec::new();
            if let Some(ref mut handler) = self.handler {
                if let Some(ref cb) = handler.complete {
                    let mut args:Vec<&str> = Vec::new();
                    args.push(portion);
                    args.extend(portions);
                    ret.extend((&mut *cb.borrow_mut())(args));
                }
            }
            ret.extend(self.commands.keys()
                .filter(|cmd| cmd.starts_with(portion)));
            return Ok(ret);
        } else {
            let mut ret:Vec<&str> = Vec::new();
            if let Some(ref mut handler) = self.handler {
                if let Some(ref cb) = handler.complete {
                    ret.extend((&mut *cb.borrow_mut())(vec![""]).iter());
                }
            }
            ret.extend(self.commands.keys());
            return Ok(ret)
        }
    }

    fn exec(&mut self, cmd: &'a str) {
        let argv:Vec<&'a str> = cmd.clone().split_whitespace().collect();
        let portions = cmd.trim().split_whitespace();
        self._exec(portions, argv);
    }

    fn _exec(&mut self, mut portions: SplitWhitespace, argv: Vec<&str>) {
        if let Some(portion) = portions.next() {
            if let Some(cmd) = self.commands.get_mut(portion) {
                cmd._exec(portions, argv);
            } else {
                if let Some(ref mut cb) = self.handler {
                    println!("handler for {:?}", cb.command);
                    (&mut *cb.exec.borrow_mut())(argv);
                }
            }
        } else {
            if let Some(ref mut cb) = self.handler {
                println!("handler for {:?}", cb.command);
                (&mut *cb.exec.borrow_mut())(argv);
            }
        }
    }
}

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

    //#[test]
    //fn test_register_and_execute() {
        //let mut called = false;
        //{
            //let mut cli = Cli::new();
            //cli.register(vec!["foo", "bar"], | _ | { called=true }).ok();
            //cli.exec("foo bar");
        //}
        //assert!(called == true)
    //}

    //#[test]
    //fn test_register_and_execute_multiple_times() {
        //let mut called = 0u8;
        //{
            //let mut cli = Cli::new();
            //cli.register(vec!["foo", "bar"], | _ | { called = called + 1} ).ok();
            //cli.exec("foo bar");
            //cli.exec("foo bar");
        //}
        //assert!(called == 2)
    //}

    //#[test]
    //fn test_complete_empty_single_cmd() {
        //let mut cli = Cli::new();
        //cli.register(vec!["foo"], | _ | { } ).ok();
        //assert!(vec!["foo"] == cli.complete(""));
        //assert!(vec!["foo"] == cli.complete("f"));
        //assert!(vec!["foo"] == cli.complete("  f"));
        ////assert!(vec![""] == cli.complete("f   "));  //FIXME: this test should pass
        //assert!(cli.complete("foo").is_empty());
    //}

    #[test]
    fn test_complete_with_dynamic() {
        let mut cli = Cli::new();
        cli.register_dyn_complete(vec!["foo"], | _ | { }, | args | {
            println!("called with {:?}", args);
            vec!["bar", "baz"]
        }).ok();
        //assert!(vec!["foo"] == cli.complete("f"));
        assert!(vec!["bar", "baz"] == cli.complete("foo a b"));
    }

    //#[test]
    //fn test_complete_multi_cmd() {
        //let mut cli = Cli::new();
        //cli.register(vec!["foo", "bar"], | _| { } ).ok();
        //assert!(vec!["foo"] == cli.complete("f"));
        //assert!(vec!["bar"] == cli.complete("foo"));
        //assert!(vec!["bar"] == cli.complete("foo b"));
    //}

    //#[test]
    //fn test_register_and_execute_with_arguments() {
        //let mut called = false;
        //{
            //let mut cli = Cli::new();
            //cli.register(vec!["foo"], | args | {
                //called=true;
                //assert!(vec!["foo", "bar", "baz"] == args);
            //} ).ok();
            //cli.exec("foo bar baz");
        //}
        //assert!(called == true);
    //}
}

fn foo(argv: Vec<&str>) {
    println!("--> {:?}", argv);
}

fn main() {
    let mut cli = Cli::new();

    //cli.register(vec!["show", "stuff"], foo).ok();
    //cli.register(vec!["show", "other"], foo).ok();
    //cli.register(vec!["some", "other"], foo).ok();
    //cli.register(vec!["list", "other", "cool"], foo).ok();
    //cli.register(vec!["list", "other", "uncool"], foo).ok();

    //loop {
        //let mut line = String::new();
        //std::io::stdin().read_line(&mut line).unwrap();

        ////println!("got: {:?}", cli.complete(&line));
        //cli.exec(&line);
    //}
}
<commit_msg>builds alright now, but API is quite shit - need to work on that<commit_after>use std::collections::HashMap;
use std::rc::Rc;
use std::str::SplitWhitespace;
use std::slice::Iter;
use std::cell::RefCell;

pub struct Command<'a> {
    command: Vec<&'a str>,
    exec: Box<RefCell<FnMut(Vec<&str>) + 'a>>,
    complete: Option<Box<RefCell<FnMut(Vec<&str>) -> Vec<&str> + 'a>>>
}

impl<'a> Command<'a> {
    fn new<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) -> Vec<&str> + 'a>(cmd: Vec<&'a str>, exec_handler: T, complete_handler: Option<U>) -> Command<'a> {
        let mut complete_cb:Option<Box<RefCell<FnMut(Vec<&str>) -> Vec<&str>>>> = None;
        if let Some(cb) = complete_handler {
            complete_cb = Some(Box::new(RefCell::new(cb)));
        }

        Command {
            command: cmd,
            exec: Box::new(RefCell::new(exec_handler)),
            complete: complete_cb
        }
    }
}

pub struct Cli<'a> {
    commands: HashMap<&'a str, Cli<'a>>,
    handler: Option<Rc<Command<'a>>>
}

impl<'a> Cli<'a>{

    fn new() -> Cli<'a> {
        Cli {
            commands: HashMap::new(),
            handler: None
        }
    }

    fn register<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) -> Vec<&str> + 'a>(&mut self, cmd: Vec<&'a str>, exec: T) -> Result<(), ()> {
        let tmp = Rc::new(Command::new(cmd.clone(), exec, None::<U>));

        match self._register(cmd.iter(), tmp.clone()) {
            Ok(_) => Ok(()),
            Err(_) => {
                //TODO: this can only happen if we register "Vec::new()" ... probably disallow that at all
                self.handler = Some(tmp.clone());
                Err(())
            }
        }
    }

    fn register_dyn_complete<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) -> Vec<&str> + 'a>(&mut self, cmd: Vec<&'a str>, exec: T, complete: U) -> Result<(), ()> {
        let tmp = Rc::new(Command::new(cmd.clone(), exec, Some(complete)));

        match self._register(cmd.iter(), tmp.clone()) {
            Ok(_) => Ok(()),
            Err(_) => {
                //TODO: this can only happen if we register "Vec::new()" ... probably disallow that at all
                self.handler = Some(tmp.clone());
                Err(())
            }
        }
    }

    fn _register(&mut self, mut it: Iter<&'a str>, command: Rc<Command<'a>>) -> Result<(), ()> {
        if let Some(portion) = it.next() {
            if !self.commands.contains_key(portion) {
                let mut cli = Cli::new();
                if let Err(_) = cli._register(it, command.clone()) {
                    cli.handler = Some(command.clone())
                }
                self.commands.insert(portion, cli);
            } else {
                if let Some(cmd) = self.commands.get_mut(portion) {
                    if let Err(_) = cmd._register(it, command.clone()) {
                        cmd.handler = Some(command.clone())
                    }
                }
            };
            Ok(())
        } else {
            Err(())
        }
    }

    fn complete(&mut self, argv: &'a str) -> Vec<&str> {
        println!("complete for '{}'", argv.trim());
        let portions = argv.trim().split_whitespace();

        match self._complete(portions) {
            Ok(ret) => ret,
            Err(_) => Vec::new()
        }
    }

    fn _complete(&mut self, mut portions: SplitWhitespace<'a>) -> Result<Vec<&'a str>, ()> {

        if let Some(ref portion) = portions.next() {
            if let Some(cmd) = self.commands.get_mut(portion) {
                return cmd._complete(portions);
            }

            let mut ret:Vec<&str> = Vec::new();
            if let Some(ref mut handler) = self.handler {
                if let Some(ref cb) = handler.complete {
                    let mut args:Vec<&str> = Vec::new();
                    args.push(portion);
                    args.extend(portions);
                    ret.extend((&mut *cb.borrow_mut())(args));
                }
            }
            ret.extend(self.commands.keys()
                .filter(|cmd| cmd.starts_with(portion)));
            return Ok(ret);
        } else {
            let mut ret:Vec<&str> = Vec::new();
            if let Some(ref mut handler) = self.handler {
                if let Some(ref cb) = handler.complete {
                    ret.extend((&mut *cb.borrow_mut())(vec![""]).iter());
                }
            }
            ret.extend(self.commands.keys());
            return Ok(ret)
        }
    }

    fn exec(&mut self, cmd: &'a str) {
        let argv:Vec<&'a str> = cmd.clone().split_whitespace().collect();
        let portions = cmd.trim().split_whitespace();
        self._exec(portions, argv);
    }

    fn _exec(&mut self, mut portions: SplitWhitespace, argv: Vec<&str>) {
        if let Some(portion) = portions.next() {
            if let Some(cmd) = self.commands.get_mut(portion) {
                cmd._exec(portions, argv);
            } else {
                if let Some(ref mut cb) = self.handler {
                    println!("handler for {:?}", cb.command);
                    (&mut *cb.exec.borrow_mut())(argv);
                }
            }
        } else {
            if let Some(ref mut cb) = self.handler {
                println!("handler for {:?}", cb.command);
                (&mut *cb.exec.borrow_mut())(argv);
            }
        }
    }
}

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

    #[test]
    fn test_register_and_execute() {
        let mut called = false;
        {
            let mut cli = Cli::new();
            cli.register(vec!["foo", "bar"], | _ | { called=true }).ok();
            cli.exec("foo bar");
        }
        assert!(called == true)
    }

    #[test]
    fn test_register_and_execute_multiple_times() {
        let mut called = 0u8;
        {
            let mut cli = Cli::new();
            cli.register(vec!["foo", "bar"], | _ | { called = called + 1} ).ok();
            cli.exec("foo bar");
            cli.exec("foo bar");
        }
        assert!(called == 2)
    }

    #[test]
    fn test_complete_empty_single_cmd() {
        let mut cli = Cli::new();
        cli.register(vec!["foo"], | _ | { } ).ok();
        assert!(vec!["foo"] == cli.complete(""));
        assert!(vec!["foo"] == cli.complete("f"));
        assert!(vec!["foo"] == cli.complete("  f"));
        //assert!(vec![""] == cli.complete("f   "));  //FIXME: this test should pass
        assert!(cli.complete("foo").is_empty());
    }

    #[test]
    fn test_complete_with_dynamic() {
        let mut cli = Cli::new();
        cli.register_dyn_complete(vec!["foo"], | _ | { }, | args | {
            println!("called with {:?}", args);
            vec!["bar", "baz"]
        }).ok();
        assert!(vec!["foo"] == cli.complete("f"));
        assert!(vec!["bar", "baz"] == cli.complete("foo a b"));
    }

    #[test]
    fn test_complete_multi_cmd() {
        let mut cli = Cli::new();
        cli.register(vec!["foo", "bar"], | _| { } ).ok();
        assert!(vec!["foo"] == cli.complete("f"));
        assert!(vec!["bar"] == cli.complete("foo"));
        assert!(vec!["bar"] == cli.complete("foo b"));
    }

    #[test]
    fn test_register_and_execute_with_arguments() {
        let mut called = false;
        {
            let mut cli = Cli::new();
            cli.register(vec!["foo"], | args | {
                called=true;
                assert!(vec!["foo", "bar", "baz"] == args);
            } ).ok();
            cli.exec("foo bar baz");
        }
        assert!(called == true);
    }
}

fn foo(argv: Vec<&str>) {
    println!("--> {:?}", argv);
}

fn main() {
    let mut cli = Cli::new();

    //cli.register(vec!["show", "stuff"], foo).ok();
    //cli.register(vec!["show", "other"], foo).ok();
    //cli.register(vec!["some", "other"], foo).ok();
    //cli.register(vec!["list", "other", "cool"], foo).ok();
    //cli.register(vec!["list", "other", "uncool"], foo).ok();

    //loop {
        //let mut line = String::new();
        //std::io::stdin().read_line(&mut line).unwrap();

        ////println!("got: {:?}", cli.complete(&line));
        //cli.exec(&line);
    //}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 - 2016, Alberto Corona <ac@albertocorona.com>
// All rights reserved. This file is part of yabs, distributed under the BSD
// 3-Clause license. For full terms please see the LICENSE file.

extern crate util;
extern crate num_cpus;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate log;

use clap::App;
use std::env;
use std::fmt::Display;
use std::process::exit;
use util::*;

enum ExitStatus {
    Success = 0,
    GeneralError,
    OptionError,
    BuildError,
}

fn check_error<T, E: Display>(result: Result<T, E>, status: ExitStatus) -> ExitStatus {
    if let Err(error) = result {
        error!("{}", error.to_string());
    }
    status
}

fn run() -> ExitStatus {
    let yaml = load_yaml!("cli.yaml");
    if let Err(error) = logger::Logger::init() {
        error!("{}", error.to_string());
        return ExitStatus::OptionError;
    };
    let matches = App::from_yaml(yaml).get_matches();
    if let Some(matches) = matches.subcommand_matches("new") {
        if matches.is_present("bin") {
            if let Some(value) = matches.value_of("bin") {
                if let Err(error) = new::new_project(&value.to_owned(), false) {
                    error!("{}", error.to_string());
                    return ExitStatus::OptionError;
                }
            }
        }
    } else if let Ok(ref mut cwd) = env::current_dir() {
        match build::find_build_file(cwd) {
            Ok(mut build_file) => {
                if let Some(matches) = matches.subcommand_matches("build") {
                    let mut jobs = num_cpus::get();
                    if let Some(jobs_given) = matches.value_of("jobs") {
                        match jobs_given.parse::<usize>() {
                            Ok(j) => jobs = j,
                            Err(error) => {
                                error!("{}", error.to_string());
                                return ExitStatus::OptionError;
                            },
                        }
                    }
                    if let Some(bin_name) = matches.value_of("bin") {
                        return check_error(build_file.build_binary_with_name(bin_name, jobs),
                                           ExitStatus::BuildError);
                    } else if let Some(lib_name) = matches.value_of("lib") {
                        return check_error(build_file.build_library_with_name(lib_name, jobs),
                                           ExitStatus::BuildError);
                    } else {
                        return check_error(build_file.build(jobs), ExitStatus::BuildError);
                    }
                } else if matches.subcommand_matches("clean").is_some() {
                    return check_error(build_file.clean(), ExitStatus::GeneralError);
                }
                if matches.is_present("sources") {
                    build_file.print_sources();
                }
            },
            Err(error) => {
                error!("{}", error.to_string());
                return ExitStatus::GeneralError;
            },
        }
    }
    ExitStatus::Success
}

fn main() {
    match run() {
        error => exit(error as i32),
    }
}
<commit_msg>Fix exit status on successful build<commit_after>// Copyright (c) 2015 - 2016, Alberto Corona <ac@albertocorona.com>
// All rights reserved. This file is part of yabs, distributed under the BSD
// 3-Clause license. For full terms please see the LICENSE file.

extern crate util;
extern crate num_cpus;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate log;

use clap::App;
use std::env;
use std::fmt::Display;
use std::process::exit;
use util::*;

enum ExitStatus {
    Success = 0,
    GeneralError,
    OptionError,
    BuildError,
}

fn check_error<T, E: Display>(result: Result<T, E>, status: ExitStatus) -> ExitStatus {
    if let Err(error) = result {
        error!("{}", error.to_string());
        return status;
    } else {
        return ExitStatus::Success;
    }
}

fn run() -> ExitStatus {
    let yaml = load_yaml!("cli.yaml");
    if let Err(error) = logger::Logger::init() {
        error!("{}", error.to_string());
        return ExitStatus::OptionError;
    };
    let matches = App::from_yaml(yaml).get_matches();
    if let Some(matches) = matches.subcommand_matches("new") {
        if matches.is_present("bin") {
            if let Some(value) = matches.value_of("bin") {
                if let Err(error) = new::new_project(&value.to_owned(), false) {
                    error!("{}", error.to_string());
                    return ExitStatus::OptionError;
                }
            }
        }
    } else if let Ok(ref mut cwd) = env::current_dir() {
        match build::find_build_file(cwd) {
            Ok(mut build_file) => {
                if let Some(matches) = matches.subcommand_matches("build") {
                    let mut jobs = num_cpus::get();
                    if let Some(jobs_given) = matches.value_of("jobs") {
                        match jobs_given.parse::<usize>() {
                            Ok(j) => jobs = j,
                            Err(error) => {
                                error!("{}", error.to_string());
                                return ExitStatus::OptionError;
                            },
                        }
                    }
                    if let Some(bin_name) = matches.value_of("bin") {
                        return check_error(build_file.build_binary_with_name(bin_name, jobs),
                                           ExitStatus::BuildError);
                    } else if let Some(lib_name) = matches.value_of("lib") {
                        return check_error(build_file.build_library_with_name(lib_name, jobs),
                                           ExitStatus::BuildError);
                    } else {
                        return check_error(build_file.build(jobs), ExitStatus::BuildError);
                    }
                } else if matches.subcommand_matches("clean").is_some() {
                    return check_error(build_file.clean(), ExitStatus::GeneralError);
                }
                if matches.is_present("sources") {
                    build_file.print_sources();
                }
            },
            Err(error) => {
                error!("{}", error.to_string());
                return ExitStatus::GeneralError;
            },
        }
    }
    ExitStatus::Success
}

fn main() {
    match run() {
        error => exit(error as i32),
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate chrono;

use std::env;
use std::io::Read;
use chrono::*;
use hyper::Client;
use hyper::header::Connection;

static WEEKDAY_WEBSITE: &'static str = "http://www.hvilkenukeerdet.no";

fn print_help() {
    println!("`uke` gives the current week number.
             `uke <number>` gives you the range for that week number");
}

fn show_week_period_for_week_number(w: usize) {
    let year = Local::now().year();
    let mut start_date = UTC.ymd(year, 1, 1).and_hms(1,0,0);
    let mut current_week = 1;

    // week 1 is defined by the first week with a thursday
    // in a year

    let jan_1_week_day = start_date.weekday().number_from_monday();
    if jan_1_week_day > 4 {
        /* this week has no thursday */
        /* the calculation will give the date of monday in the first week*/
        start_date = UTC.ymd(year, 1, (1 + 8-jan_1_week_day)).and_hms(1,0,0);
    } else {
        /* start at this week's first day */
        start_date = UTC.ymd(year-1, 12, (31 - (jan_1_week_day - 2))).and_hms(1,0,0);
    }

    while w != current_week {
        start_date = start_date + Duration::weeks(1);
        current_week += 1;
    }

    let end_date = start_date + Duration::days(6);

    println!("Week {}, {} is from \"{}\" to \"{}\"",
             w,
             year,
             start_date.format("%d %b"),
             end_date.format("%d %b")
            );
}

fn main() {
    if let Some(arg1) = env::args().nth(1) {
        match arg1.parse::<usize>() {
            Ok(week_number) =>
                if week_number >= 1 && week_number <= 52 {
                    show_week_period_for_week_number(week_number);
                    return;
                },
            _ => {} ,
        }

        print_help();
    } else {
        let client = Client::new();

        let mut res = client
                        .get(WEEKDAY_WEBSITE)
                        .header(Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let body_index = body.find("\n").unwrap() + "\n".len();
        let break_index = body.find("
").unwrap();

        let week_number = &body[body_index..break_index];
        println!("{}", week_number);
    }
}
<commit_msg>Add support for 53 weeks in a year<commit_after>extern crate hyper;
extern crate chrono;

use std::env;
use std::io::Read;
use chrono::*;
use hyper::Client;
use hyper::header::Connection;

static WEEKDAY_WEBSITE: &'static str = "http://www.hvilkenukeerdet.no";

fn print_help() {
    println!("`uke` gives the current week number.
             `uke <number>` gives you the range for that week number");
}

fn is_leap_year(year: i32) -> bool {
    return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
}

fn find_num_of_weeks_this_year(year: i32) -> usize {
    let last_day_of_year = UTC.ymd(year, 12, 31);
    if last_day_of_year.weekday() == Weekday::Thu ||
        (last_day_of_year.weekday() == Weekday::Fri &&
         is_leap_year(year)) {
        return 53;
    } else {
        return 52;
    }
}

fn show_week_period_for_week_number(w: usize, year: i32) {
    let mut start_date = UTC.ymd(year, 1, 1).and_hms(1,0,0);
    let mut current_week = 1;

    // week 1 is defined by the first week with a thursday
    // in a year

    let jan_1_week_day = start_date.weekday().number_from_monday();
    if jan_1_week_day > 4 {
        /* this week has no thursday */
        /* the calculation will give the date of monday in the first week*/
        start_date = UTC.ymd(year, 1, (1 + 8-jan_1_week_day)).and_hms(1,0,0);
    } else {
        /* start at this week's first day */
        start_date = UTC.ymd(year-1, 12, (31 - (jan_1_week_day - 2))).and_hms(1,0,0);
    }

    while w != current_week {
        start_date = start_date + Duration::weeks(1);
        current_week += 1;
    }

    let end_date = start_date + Duration::days(6);

    println!("Week {}, {} is from \"{}\" to \"{}\"",
             w,
             year,
             start_date.format("%d %b"),
             end_date.format("%d %b")
            );
}

fn main() {
    let year = Local::now().year();

    if let Some(arg1) = env::args().nth(1) {
        let num_of_weeks_this_year = find_num_of_weeks_this_year(year);
        match arg1.parse::<usize>() {
            Ok(week_number) =>
                if week_number >= 1 && week_number <= num_of_weeks_this_year {
                    show_week_period_for_week_number(week_number, year);
                    return;
                },
            _ => {} ,
        }

        print_help();
    } else {
        let client = Client::new();

        let mut res = client
                        .get(WEEKDAY_WEBSITE)
                        .header(Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let body_index = body.find("\n").unwrap() + "\n".len();
        let break_index = body.find("
").unwrap();

        let week_number = &body[body_index..break_index];
        println!("{}", week_number);
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::prelude::*;

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

    let mut argument_spaces = "2".to_string();
    if args.len() == 2 {
        argument_spaces = args[1].clone().to_string();
    }

    let mut argument_path = (".").to_string();
    if args.len() == 3 {
        argument_spaces = args[1].clone().to_string();
        argument_path = args[2].clone().to_string();
    }

    let file_name = "/.editorconfig";
    let full_path = argument_path + &file_name;

    let save_path = Path::new(&full_path);
    let save_path_display = save_path.display();

    let part_1 = String::from("# editorconfig.org\n\
\n\
root = true\n\
\n\
[*]\n\
end_of_line = lf\n\
charset = utf-8\n\
trim_trailing_whitespace = true\n\
insert_final_newline = true\n\
indent_style = space\n\
indent_size = ");

let part_2 = String::from("\n\
\n\
[*.md]\n\
trim_trailing_whitespace = false\n");

    let contents = part_1 + &argument_spaces + &part_2;

    let mut output_file = match File::create(&save_path) {
        Err(error) => panic!("Could not create {}: {}", save_path_display, error.description()),
        Ok(file) => file,
    };

    output_file.write_all(contents.as_bytes()).unwrap();
}
<commit_msg>Fix clippy lints<commit_after>use std::error::Error;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::prelude::*;

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

    let mut argument_spaces = if args.len() == 2 {
        args[1].clone().to_string()
    } else {
        "2".to_string()
    };

    let argument_path = if args.len() == 3 {
        argument_spaces = args[1].clone().to_string();
        args[2].clone().to_string()
    } else {
        ".".to_string()
    };

    let file_name = "/.editorconfig";
    let full_path = argument_path + file_name;

    let save_path = Path::new(&full_path);
    let save_path_display = save_path.display();

    let part_1 = String::from("# editorconfig.org\n\
\n\
root = true\n\
\n\
[*]\n\
end_of_line = lf\n\
charset = utf-8\n\
trim_trailing_whitespace = true\n\
insert_final_newline = true\n\
indent_style = space\n\
indent_size = ");

let part_2 = String::from("\n\
\n\
[*.md]\n\
trim_trailing_whitespace = false\n");

    let contents = part_1 + &argument_spaces + &part_2;

    let mut output_file = File::create(&save_path).unwrap_or_else(|error| {
        panic!("Could not create {}: {}", save_path_display, error.description());
    });

    output_file.write_all(contents.as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(syntax, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate sync;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use sync::DuplexStream;
use sync::{Arc,RWLock};
use std::comm::{Disconnected,Empty};

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let args = std::os::args();

	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(StrBuf::from_str(*args.get(0)).append(" <filename>").into_owned(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = sync::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename, &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<commit_msg>getopts now require a &[StrBuf] as argument<commit_after>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(syntax, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate sync;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use sync::DuplexStream;
use sync::{Arc,RWLock};
use std::comm::{Disconnected,Empty};

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let mut args = Vec::new();
	for a in std::os::args().iter()
	{
		args.push(a.to_strbuf());
	}

	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").to_str(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = sync::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename.to_str(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<|endoftext|>