<commit_before>/*
 * Copyright (c) 2014-2015 Mathias Hällman
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

extern crate libc;
extern crate termkey;

use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
use std::thread::Thread;

use self::termkey::{TermKeyEvent, TermKeyResult};
use self::termkey::c::TermKeySym;

use keymap;

#[cfg(not(test))]
const STDIN_FILENO: libc::c_int = 0;

/*
 * TermInput is returned when starting listening for key events on a file
 * descriptor. It controls the life time of the terminal input loop. When the
 * TermInput is dropped, the terminal input loop will finish.
 */
pub struct TermInput {
  kill_tx: Sender<()>,
  died_rx: Receiver<()>,
}

impl Drop for TermInput {
  fn drop(&mut self) {
    self.kill_tx.send(()).unwrap();
    self.died_rx.recv().unwrap();
  }
}

// start listening for terminal input on stdin
#[cfg(not(test))]
pub fn start(key_tx: Sender<keymap::Key>) -> TermInput {
  start_on_fd(STDIN_FILENO, key_tx)
}

// start listening for terminal input on the specified file descriptor
pub fn start_on_fd(fd: libc::c_int, key_tx: Sender<keymap::Key>) -> TermInput {
  let (kill_tx, kill_rx) = channel();
  let (died_tx, died_rx) = channel();
  Thread::spawn(move |:| { input_loop(kill_rx, died_tx, key_tx, fd); });
  TermInput { kill_tx: kill_tx, died_rx: died_rx }
}

/*
 * Helper module for detecting available bytes on the file descriptor being
 * listened to.
 */
mod libc_poll {
  use super::libc::{c_int, c_long, c_short};

  #[repr(C)]
  struct Pollfd {
    fd: c_int,
    events: c_short,
    revents: c_short
  }

  extern {
    fn poll(fds: *mut Pollfd, nfds: c_long, timeout: c_int) -> c_int;
  }

  #[derive(PartialEq)]
  pub enum PollResult {
    Ready,
    Timeout,
  }

  pub fn poll_fd(fd: c_int, timeout_ms: int) -> PollResult {
    const POLLIN: c_short = 1;
    let mut pollfd = Pollfd { fd: fd, events: POLLIN, revents: 0 };
    let num_fds = 1;
    let poll_result = unsafe {
      poll(&mut pollfd, num_fds, timeout_ms as c_int)
    };
    if poll_result < 0      { panic!("Unable to poll stdin."); }
    else if poll_result > 0 { PollResult::Ready }
    else                    { PollResult::Timeout }
  }
}

fn input_loop(kill_rx: Receiver<()>, died_tx: Sender<()>,
              key_tx: Sender<keymap::Key>, fd: libc::c_int) {
  let is_alive = |&:| kill_rx.try_recv() == Err(TryRecvError::Empty);
  let mut tk = termkey::TermKey::new(fd, termkey::c::TERMKEY_FLAG_CTRLC);

  while is_alive() {
    // check for available input
    let poll_timeout_ms = 10;
    if libc_poll::poll_fd(fd, poll_timeout_ms) == libc_poll::PollResult::Ready {
      // tell termkey that there's input available
      tk.advisereadable();
    }

    // empty the fd, translating and sending key events
    loop {
      match tk.getkey() {
        TermKeyResult::None_        => break,  // got nothing, done here
        TermKeyResult::Eof          =>
          panic!("stdin closed, you're on your own."),
        TermKeyResult::Error{errno} =>
          panic!("termkey::geykey failed with error code {}", errno),
        TermKeyResult::Key(key)     => translate_key(key),
        TermKeyResult::Again        =>
          // There's input available, but not enough to make a key event. Likely
          // escape has been pushed, which we want to force out and interpret as
          // a key on its own, otherwise oops.
          match tk.getkey_force() {
            TermKeyResult::Key(key)     => translate_key(key),
            TermKeyResult::Eof          =>
              panic!("stdin closed, you're on your own."),
            TermKeyResult::Error{errno} =>
              panic!("termkey::geykey_force failed with error code {}", errno),
            _                           => unreachable!(),
          },
      }.map(|key| key_tx.send(key));
    }
  }

  died_tx.send(()).unwrap();
}

fn translate_key(key: TermKeyEvent) -> Option<keymap::Key> {
  match key {
    TermKeyEvent::FunctionEvent{num, mods}                =>
      Some(keymap::Key::Fn{num: num, mods: translate_mods(mods)}),
    TermKeyEvent::KeySymEvent{sym, mods}                  =>
      Some(keymap::Key::Sym{
        sym: translate_sym(sym), mods: translate_mods(mods)}),
    TermKeyEvent::UnicodeEvent{codepoint, mods, utf8:_}   =>
      Some(keymap::Key::Unicode{
        codepoint: codepoint, mods: translate_mods(mods)}),
    _                                                     =>
      None,
  }
}

fn translate_sym(sym: TermKeySym) -> keymap::KeySym {
  match sym {
    TermKeySym::TERMKEY_SYM_UNKNOWN   => keymap::KeySym::Unknown,
    TermKeySym::TERMKEY_SYM_NONE      => keymap::KeySym::None,
    TermKeySym::TERMKEY_SYM_BACKSPACE => keymap::KeySym::Backspace,
    TermKeySym::TERMKEY_SYM_TAB       => keymap::KeySym::Tab,
    TermKeySym::TERMKEY_SYM_ENTER     => keymap::KeySym::Enter,
    TermKeySym::TERMKEY_SYM_ESCAPE    => keymap::KeySym::Escape,
    TermKeySym::TERMKEY_SYM_SPACE     => keymap::KeySym::Space,
    TermKeySym::TERMKEY_SYM_DEL       => keymap::KeySym::Del,
    TermKeySym::TERMKEY_SYM_UP        => keymap::KeySym::Up,
    TermKeySym::TERMKEY_SYM_DOWN      => keymap::KeySym::Down,
    TermKeySym::TERMKEY_SYM_LEFT      => keymap::KeySym::Left,
    TermKeySym::TERMKEY_SYM_RIGHT     => keymap::KeySym::Right,
    TermKeySym::TERMKEY_SYM_BEGIN     => keymap::KeySym::Begin,
    TermKeySym::TERMKEY_SYM_FIND      => keymap::KeySym::Find,
    TermKeySym::TERMKEY_SYM_INSERT    => keymap::KeySym::Insert,
    TermKeySym::TERMKEY_SYM_DELETE    => keymap::KeySym::Delete,
    TermKeySym::TERMKEY_SYM_SELECT    => keymap::KeySym::Select,
    TermKeySym::TERMKEY_SYM_PAGEUP    => keymap::KeySym::Pageup,
    TermKeySym::TERMKEY_SYM_PAGEDOWN  => keymap::KeySym::Pagedown,
    TermKeySym::TERMKEY_SYM_HOME      => keymap::KeySym::Home,
    TermKeySym::TERMKEY_SYM_END       => keymap::KeySym::End,
    TermKeySym::TERMKEY_SYM_CANCEL    => keymap::KeySym::Cancel,
    TermKeySym::TERMKEY_SYM_CLEAR     => keymap::KeySym::Clear,
    TermKeySym::TERMKEY_SYM_CLOSE     => keymap::KeySym::Close,
    TermKeySym::TERMKEY_SYM_COMMAND   => keymap::KeySym::Command,
    TermKeySym::TERMKEY_SYM_COPY      => keymap::KeySym::Copy,
    TermKeySym::TERMKEY_SYM_EXIT      => keymap::KeySym::Exit,
    TermKeySym::TERMKEY_SYM_HELP      => keymap::KeySym::Help,
    TermKeySym::TERMKEY_SYM_MARK      => keymap::KeySym::Mark,
    TermKeySym::TERMKEY_SYM_MESSAGE   => keymap::KeySym::Message,
    TermKeySym::TERMKEY_SYM_MOVE      => keymap::KeySym::Move,
    TermKeySym::TERMKEY_SYM_OPEN      => keymap::KeySym::Open,
    TermKeySym::TERMKEY_SYM_OPTIONS   => keymap::KeySym::Options,
    TermKeySym::TERMKEY_SYM_PRINT     => keymap::KeySym::Print,
    TermKeySym::TERMKEY_SYM_REDO      => keymap::KeySym::Redo,
    TermKeySym::TERMKEY_SYM_REFERENCE => keymap::KeySym::Reference,
    TermKeySym::TERMKEY_SYM_REFRESH   => keymap::KeySym::Refresh,
    TermKeySym::TERMKEY_SYM_REPLACE   => keymap::KeySym::Replace,
    TermKeySym::TERMKEY_SYM_RESTART   => keymap::KeySym::Restart,
    TermKeySym::TERMKEY_SYM_RESUME    => keymap::KeySym::Resume,
    TermKeySym::TERMKEY_SYM_SAVE      => keymap::KeySym::Save,
    TermKeySym::TERMKEY_SYM_SUSPEND   => keymap::KeySym::Suspend,
    TermKeySym::TERMKEY_SYM_UNDO      => keymap::KeySym::Undo,
    TermKeySym::TERMKEY_SYM_KP0       => keymap::KeySym::KP0,
    TermKeySym::TERMKEY_SYM_KP1       => keymap::KeySym::KP1,
    TermKeySym::TERMKEY_SYM_KP2       => keymap::KeySym::KP2,
    TermKeySym::TERMKEY_SYM_KP3       => keymap::KeySym::KP3,
    TermKeySym::TERMKEY_SYM_KP4       => keymap::KeySym::KP4,
    TermKeySym::TERMKEY_SYM_KP5       => keymap::KeySym::KP5,
    TermKeySym::TERMKEY_SYM_KP6       => keymap::KeySym::KP6,
    TermKeySym::TERMKEY_SYM_KP7       => keymap::KeySym::KP7,
    TermKeySym::TERMKEY_SYM_KP8       => keymap::KeySym::KP8,
    TermKeySym::TERMKEY_SYM_KP9       => keymap::KeySym::KP9,
    TermKeySym::TERMKEY_SYM_KPENTER   => keymap::KeySym::KPEnter,
    TermKeySym::TERMKEY_SYM_KPPLUS    => keymap::KeySym::KPPlus,
    TermKeySym::TERMKEY_SYM_KPMINUS   => keymap::KeySym::KPMinus,
    TermKeySym::TERMKEY_SYM_KPMULT    => keymap::KeySym::KPMult,
    TermKeySym::TERMKEY_SYM_KPDIV     => keymap::KeySym::KPDiv,
    TermKeySym::TERMKEY_SYM_KPCOMMA   => keymap::KeySym::KPComma,
    TermKeySym::TERMKEY_SYM_KPPERIOD  => keymap::KeySym::KPPeriod,
    TermKeySym::TERMKEY_SYM_KPEQUALS  => keymap::KeySym::KPEquals,
    TermKeySym::TERMKEY_N_SYMS        => keymap::KeySym::NSyms,
  }
}

fn translate_mods(mods: termkey::c::X_TermKey_KeyMod) -> keymap::KeyMod {
  let mut ret = keymap::MOD_NONE;
  if mods.contains(termkey::c::TERMKEY_KEYMOD_SHIFT) {
    ret.insert(keymap::MOD_SHIFT);
  }
  if mods.contains(termkey::c::TERMKEY_KEYMOD_ALT) {
    ret.insert(keymap::MOD_ALT);
  }
  if mods.contains(termkey::c::TERMKEY_KEYMOD_CTRL) {
    ret.insert(keymap::MOD_CTRL);
  }
  return ret;
}

#[cfg(test)]
mod test {
  extern crate time;

  use super::libc;
  use std::sync::mpsc::{channel, Sender};
  use std::old_io::pipe::PipeStream;
  use std::old_io::timer;
  use std::os;
  use std::thread::Thread;
  use std::time::duration::Duration;

  use keymap;

  // Simulates stdin by writing bytes to a pipe, then listens for the key
  // outputs and matches with expectations.
  #[test]
  fn test_input() {
    // pairs of input bytes on "stdin" and corresponding expected key output
    let input_output_pairs = vec!(
      (vec!(0x61),
        keymap::Key::Unicode{codepoint: 'a', mods: keymap::MOD_NONE}),
      (vec!(0x1B, 0x61),
        keymap::Key::Unicode{codepoint: 'a', mods: keymap::MOD_ALT}),
      (vec!(0x1B),
        keymap::Key::Sym{sym: keymap::KeySym::Escape, mods: keymap::MOD_NONE}),
      (vec!(0x61),
        keymap::Key::Unicode{codepoint: 'a', mods: keymap::MOD_NONE}),
      (vec!(0x03),
        keymap::Key::Unicode{codepoint: 'c', mods: keymap::MOD_CTRL}),
      (vec!(0x1B, 0x5B, 0x41),
        keymap::Key::Sym{sym: keymap::KeySym::Up, mods: keymap::MOD_NONE}),
      (vec!(0x1B, 0x4F, 0x53),
        keymap::Key::Fn{num: 4, mods: keymap::MOD_NONE}),
      (vec!(0xE3, 0x81, 0x82),
        keymap::Key::Unicode{codepoint: 'あ', mods: keymap::MOD_NONE}),
    );

    let inputs: Vec<Vec<u8>> =
      input_output_pairs.iter().map(|&(ref input, _)| input.clone()).collect();
    let outputs: Vec<keymap::Key> =
      input_output_pairs.iter().map(|&(_, output)| output).collect();

    // set up communication channels
    let (key_tx, key_rx) = channel();
    let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };

    // start input listener
    let _term_input = super::start_on_fd(reader, key_tx);

    // make sure we quit in an orderly fashion even at failure
    let (close_writer_tx, close_writer_rx) = channel();
    struct PipeKiller { close_writer_tx: Sender<()>, reader: libc::c_int }
    impl Drop for PipeKiller {
      fn drop(&mut self) {
        unsafe { libc::close(self.reader); }
        self.close_writer_tx.send(()).unwrap();
      }
    }
    let _pipe_killer =
      PipeKiller { close_writer_tx: close_writer_tx, reader: reader };

    // simulate keyboard input
    Thread::spawn(move || {
      let mut pipe_out = PipeStream::open(writer);
      for input in inputs.iter() {
        pipe_out.write_all(input.as_slice()).unwrap();
        // give termkey a chance to parse escape as a standalone key
        timer::sleep(Duration::milliseconds(1));
      }
      // keep the pipe alive until we're finished with it
      close_writer_rx.recv().unwrap();
    });

    // receive key outputs and match with expectations
    let timeout_at = time::get_time() + Duration::milliseconds(100);
    for output in outputs.iter() {
      // just keep looping until the key arrives
      loop {
        match key_rx.try_recv() {
          Ok(key) => { assert_eq!(key, *output); break; }
          _       => (),
        }
        let time_now = time::get_time();
        if time_now > timeout_at { panic!("Timeout waiting for key event."); }
      }
    }
  }
}
<commit_msg>Changed syntax for closures<commit_after>/*
 * Copyright (c) 2014-2015 Mathias Hällman
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

extern crate libc;
extern crate termkey;

use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
use std::thread::Thread;

use self::termkey::{TermKeyEvent, TermKeyResult};
use self::termkey::c::TermKeySym;

use keymap;

#[cfg(not(test))]
const STDIN_FILENO: libc::c_int = 0;

/*
 * TermInput is returned when starting listening for key events on a file
 * descriptor. It controls the life time of the terminal input loop. When the
 * TermInput is dropped, the terminal input loop will finish.
 */
pub struct TermInput {
  kill_tx: Sender<()>,
  died_rx: Receiver<()>,
}

impl Drop for TermInput {
  fn drop(&mut self) {
    self.kill_tx.send(()).unwrap();
    self.died_rx.recv().unwrap();
  }
}

// start listening for terminal input on stdin
#[cfg(not(test))]
pub fn start(key_tx: Sender<keymap::Key>) -> TermInput {
  start_on_fd(STDIN_FILENO, key_tx)
}

// start listening for terminal input on the specified file descriptor
pub fn start_on_fd(fd: libc::c_int, key_tx: Sender<keymap::Key>) -> TermInput {
  let (kill_tx, kill_rx) = channel();
  let (died_tx, died_rx) = channel();
  Thread::spawn(move || { input_loop(kill_rx, died_tx, key_tx, fd); });
  TermInput { kill_tx: kill_tx, died_rx: died_rx }
}

/*
 * Helper module for detecting available bytes on the file descriptor being
 * listened to.
 */
mod libc_poll {
  use super::libc::{c_int, c_long, c_short};

  #[repr(C)]
  struct Pollfd {
    fd: c_int,
    events: c_short,
    revents: c_short
  }

  extern {
    fn poll(fds: *mut Pollfd, nfds: c_long, timeout: c_int) -> c_int;
  }

  #[derive(PartialEq)]
  pub enum PollResult {
    Ready,
    Timeout,
  }

  pub fn poll_fd(fd: c_int, timeout_ms: int) -> PollResult {
    const POLLIN: c_short = 1;
    let mut pollfd = Pollfd { fd: fd, events: POLLIN, revents: 0 };
    let num_fds = 1;
    let poll_result = unsafe {
      poll(&mut pollfd, num_fds, timeout_ms as c_int)
    };
    if poll_result < 0      { panic!("Unable to poll stdin."); }
    else if poll_result > 0 { PollResult::Ready }
    else                    { PollResult::Timeout }
  }
}

fn input_loop(kill_rx: Receiver<()>, died_tx: Sender<()>,
              key_tx: Sender<keymap::Key>, fd: libc::c_int) {
  let is_alive = |&:| kill_rx.try_recv() == Err(TryRecvError::Empty);
  let mut tk = termkey::TermKey::new(fd, termkey::c::TERMKEY_FLAG_CTRLC);

  while is_alive() {
    // check for available input
    let poll_timeout_ms = 10;
    if libc_poll::poll_fd(fd, poll_timeout_ms) == libc_poll::PollResult::Ready {
      // tell termkey that there's input available
      tk.advisereadable();
    }

    // empty the fd, translating and sending key events
    loop {
      match tk.getkey() {
        TermKeyResult::None_        => break,  // got nothing, done here
        TermKeyResult::Eof          =>
          panic!("stdin closed, you're on your own."),
        TermKeyResult::Error{errno} =>
          panic!("termkey::geykey failed with error code {}", errno),
        TermKeyResult::Key(key)     => translate_key(key),
        TermKeyResult::Again        =>
          // There's input available, but not enough to make a key event. Likely
          // escape has been pushed, which we want to force out and interpret as
          // a key on its own, otherwise oops.
          match tk.getkey_force() {
            TermKeyResult::Key(key)     => translate_key(key),
            TermKeyResult::Eof          =>
              panic!("stdin closed, you're on your own."),
            TermKeyResult::Error{errno} =>
              panic!("termkey::geykey_force failed with error code {}", errno),
            _                           => unreachable!(),
          },
      }.map(|key| key_tx.send(key));
    }
  }

  died_tx.send(()).unwrap();
}

fn translate_key(key: TermKeyEvent) -> Option<keymap::Key> {
  match key {
    TermKeyEvent::FunctionEvent{num, mods}                =>
      Some(keymap::Key::Fn{num: num, mods: translate_mods(mods)}),
    TermKeyEvent::KeySymEvent{sym, mods}                  =>
      Some(keymap::Key::Sym{
        sym: translate_sym(sym), mods: translate_mods(mods)}),
    TermKeyEvent::UnicodeEvent{codepoint, mods, utf8:_}   =>
      Some(keymap::Key::Unicode{
        codepoint: codepoint, mods: translate_mods(mods)}),
    _                                                     =>
      None,
  }
}

fn translate_sym(sym: TermKeySym) -> keymap::KeySym {
  match sym {
    TermKeySym::TERMKEY_SYM_UNKNOWN   => keymap::KeySym::Unknown,
    TermKeySym::TERMKEY_SYM_NONE      => keymap::KeySym::None,
    TermKeySym::TERMKEY_SYM_BACKSPACE => keymap::KeySym::Backspace,
    TermKeySym::TERMKEY_SYM_TAB       => keymap::KeySym::Tab,
    TermKeySym::TERMKEY_SYM_ENTER     => keymap::KeySym::Enter,
    TermKeySym::TERMKEY_SYM_ESCAPE    => keymap::KeySym::Escape,
    TermKeySym::TERMKEY_SYM_SPACE     => keymap::KeySym::Space,
    TermKeySym::TERMKEY_SYM_DEL       => keymap::KeySym::Del,
    TermKeySym::TERMKEY_SYM_UP        => keymap::KeySym::Up,
    TermKeySym::TERMKEY_SYM_DOWN      => keymap::KeySym::Down,
    TermKeySym::TERMKEY_SYM_LEFT      => keymap::KeySym::Left,
    TermKeySym::TERMKEY_SYM_RIGHT     => keymap::KeySym::Right,
    TermKeySym::TERMKEY_SYM_BEGIN     => keymap::KeySym::Begin,
    TermKeySym::TERMKEY_SYM_FIND      => keymap::KeySym::Find,
    TermKeySym::TERMKEY_SYM_INSERT    => keymap::KeySym::Insert,
    TermKeySym::TERMKEY_SYM_DELETE    => keymap::KeySym::Delete,
    TermKeySym::TERMKEY_SYM_SELECT    => keymap::KeySym::Select,
    TermKeySym::TERMKEY_SYM_PAGEUP    => keymap::KeySym::Pageup,
    TermKeySym::TERMKEY_SYM_PAGEDOWN  => keymap::KeySym::Pagedown,
    TermKeySym::TERMKEY_SYM_HOME      => keymap::KeySym::Home,
    TermKeySym::TERMKEY_SYM_END       => keymap::KeySym::End,
    TermKeySym::TERMKEY_SYM_CANCEL    => keymap::KeySym::Cancel,
    TermKeySym::TERMKEY_SYM_CLEAR     => keymap::KeySym::Clear,
    TermKeySym::TERMKEY_SYM_CLOSE     => keymap::KeySym::Close,
    TermKeySym::TERMKEY_SYM_COMMAND   => keymap::KeySym::Command,
    TermKeySym::TERMKEY_SYM_COPY      => keymap::KeySym::Copy,
    TermKeySym::TERMKEY_SYM_EXIT      => keymap::KeySym::Exit,
    TermKeySym::TERMKEY_SYM_HELP      => keymap::KeySym::Help,
    TermKeySym::TERMKEY_SYM_MARK      => keymap::KeySym::Mark,
    TermKeySym::TERMKEY_SYM_MESSAGE   => keymap::KeySym::Message,
    TermKeySym::TERMKEY_SYM_MOVE      => keymap::KeySym::Move,
    TermKeySym::TERMKEY_SYM_OPEN      => keymap::KeySym::Open,
    TermKeySym::TERMKEY_SYM_OPTIONS   => keymap::KeySym::Options,
    TermKeySym::TERMKEY_SYM_PRINT     => keymap::KeySym::Print,
    TermKeySym::TERMKEY_SYM_REDO      => keymap::KeySym::Redo,
    TermKeySym::TERMKEY_SYM_REFERENCE => keymap::KeySym::Reference,
    TermKeySym::TERMKEY_SYM_REFRESH   => keymap::KeySym::Refresh,
    TermKeySym::TERMKEY_SYM_REPLACE   => keymap::KeySym::Replace,
    TermKeySym::TERMKEY_SYM_RESTART   => keymap::KeySym::Restart,
    TermKeySym::TERMKEY_SYM_RESUME    => keymap::KeySym::Resume,
    TermKeySym::TERMKEY_SYM_SAVE      => keymap::KeySym::Save,
    TermKeySym::TERMKEY_SYM_SUSPEND   => keymap::KeySym::Suspend,
    TermKeySym::TERMKEY_SYM_UNDO      => keymap::KeySym::Undo,
    TermKeySym::TERMKEY_SYM_KP0       => keymap::KeySym::KP0,
    TermKeySym::TERMKEY_SYM_KP1       => keymap::KeySym::KP1,
    TermKeySym::TERMKEY_SYM_KP2       => keymap::KeySym::KP2,
    TermKeySym::TERMKEY_SYM_KP3       => keymap::KeySym::KP3,
    TermKeySym::TERMKEY_SYM_KP4       => keymap::KeySym::KP4,
    TermKeySym::TERMKEY_SYM_KP5       => keymap::KeySym::KP5,
    TermKeySym::TERMKEY_SYM_KP6       => keymap::KeySym::KP6,
    TermKeySym::TERMKEY_SYM_KP7       => keymap::KeySym::KP7,
    TermKeySym::TERMKEY_SYM_KP8       => keymap::KeySym::KP8,
    TermKeySym::TERMKEY_SYM_KP9       => keymap::KeySym::KP9,
    TermKeySym::TERMKEY_SYM_KPENTER   => keymap::KeySym::KPEnter,
    TermKeySym::TERMKEY_SYM_KPPLUS    => keymap::KeySym::KPPlus,
    TermKeySym::TERMKEY_SYM_KPMINUS   => keymap::KeySym::KPMinus,
    TermKeySym::TERMKEY_SYM_KPMULT    => keymap::KeySym::KPMult,
    TermKeySym::TERMKEY_SYM_KPDIV     => keymap::KeySym::KPDiv,
    TermKeySym::TERMKEY_SYM_KPCOMMA   => keymap::KeySym::KPComma,
    TermKeySym::TERMKEY_SYM_KPPERIOD  => keymap::KeySym::KPPeriod,
    TermKeySym::TERMKEY_SYM_KPEQUALS  => keymap::KeySym::KPEquals,
    TermKeySym::TERMKEY_N_SYMS        => keymap::KeySym::NSyms,
  }
}

fn translate_mods(mods: termkey::c::X_TermKey_KeyMod) -> keymap::KeyMod {
  let mut ret = keymap::MOD_NONE;
  if mods.contains(termkey::c::TERMKEY_KEYMOD_SHIFT) {
    ret.insert(keymap::MOD_SHIFT);
  }
  if mods.contains(termkey::c::TERMKEY_KEYMOD_ALT) {
    ret.insert(keymap::MOD_ALT);
  }
  if mods.contains(termkey::c::TERMKEY_KEYMOD_CTRL) {
    ret.insert(keymap::MOD_CTRL);
  }
  return ret;
}

#[cfg(test)]
mod test {
  extern crate time;

  use super::libc;
  use std::sync::mpsc::{channel, Sender};
  use std::old_io::pipe::PipeStream;
  use std::old_io::timer;
  use std::os;
  use std::thread::Thread;
  use std::time::duration::Duration;

  use keymap;

  // Simulates stdin by writing bytes to a pipe, then listens for the key
  // outputs and matches with expectations.
  #[test]
  fn test_input() {
    // pairs of input bytes on "stdin" and corresponding expected key output
    let input_output_pairs = vec!(
      (vec!(0x61),
        keymap::Key::Unicode{codepoint: 'a', mods: keymap::MOD_NONE}),
      (vec!(0x1B, 0x61),
        keymap::Key::Unicode{codepoint: 'a', mods: keymap::MOD_ALT}),
      (vec!(0x1B),
        keymap::Key::Sym{sym: keymap::KeySym::Escape, mods: keymap::MOD_NONE}),
      (vec!(0x61),
        keymap::Key::Unicode{codepoint: 'a', mods: keymap::MOD_NONE}),
      (vec!(0x03),
        keymap::Key::Unicode{codepoint: 'c', mods: keymap::MOD_CTRL}),
      (vec!(0x1B, 0x5B, 0x41),
        keymap::Key::Sym{sym: keymap::KeySym::Up, mods: keymap::MOD_NONE}),
      (vec!(0x1B, 0x4F, 0x53),
        keymap::Key::Fn{num: 4, mods: keymap::MOD_NONE}),
      (vec!(0xE3, 0x81, 0x82),
        keymap::Key::Unicode{codepoint: 'あ', mods: keymap::MOD_NONE}),
    );

    let inputs: Vec<Vec<u8>> =
      input_output_pairs.iter().map(|&(ref input, _)| input.clone()).collect();
    let outputs: Vec<keymap::Key> =
      input_output_pairs.iter().map(|&(_, output)| output).collect();

    // set up communication channels
    let (key_tx, key_rx) = channel();
    let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };

    // start input listener
    let _term_input = super::start_on_fd(reader, key_tx);

    // make sure we quit in an orderly fashion even at failure
    let (close_writer_tx, close_writer_rx) = channel();
    struct PipeKiller { close_writer_tx: Sender<()>, reader: libc::c_int }
    impl Drop for PipeKiller {
      fn drop(&mut self) {
        unsafe { libc::close(self.reader); }
        self.close_writer_tx.send(()).unwrap();
      }
    }
    let _pipe_killer =
      PipeKiller { close_writer_tx: close_writer_tx, reader: reader };

    // simulate keyboard input
    Thread::spawn(move || {
      let mut pipe_out = PipeStream::open(writer);
      for input in inputs.iter() {
        pipe_out.write_all(input.as_slice()).unwrap();
        // give termkey a chance to parse escape as a standalone key
        timer::sleep(Duration::milliseconds(1));
      }
      // keep the pipe alive until we're finished with it
      close_writer_rx.recv().unwrap();
    });

    // receive key outputs and match with expectations
    let timeout_at = time::get_time() + Duration::milliseconds(100);
    for output in outputs.iter() {
      // just keep looping until the key arrives
      loop {
        match key_rx.try_recv() {
          Ok(key) => { assert_eq!(key, *output); break; }
          _       => (),
        }
        let time_now = time::get_time();
        if time_now > timeout_at { panic!("Timeout waiting for key event."); }
      }
    }
  }
}
<|endoftext|>


<commit_before>//! Utilities for defining a JSON parser.

use util::Id;

use std::cell::RefCell;
use std::collections::{ HashMap, HashSet };
use std::error::Error as StdError;
use std::fmt::{ Display, Debug, Error as FmtError, Formatter };
use std::hash::Hash;
use std::rc::Rc;
use std::sync::Arc;

use serde_json::error;
use serde::ser::{ Serialize, Serializer };
use serde_json;
pub use serde_json::value::Value as JSON;
use serde::de::Error;

/// Utility function: Make sure that we have consumed all the fields of an object.
pub fn check_fields(path: Path, json: &JSON) -> Result<(), ParseError> {
    if let JSON::Object(ref obj) = *json {
        if obj.is_empty() {
            Ok(())
        } else {
            Err(ParseError::unknown_fields(obj.keys().cloned().collect(), &path))
        }
    } else {
        Ok(())
    }
}

/// A path in the JSON tree. Used for displaying error messages.
#[derive(Clone, Debug)]
pub struct Path {
    buf: Rc<RefCell<String>>,
    len: usize,
}
impl Path {
    /// Create an empty Path.
    pub fn new() -> Self {
        Path {
            buf: Rc::new(RefCell::new(String::new())),
            len: 0,
        }
    }

    /// Push a suffix after a path.
    pub fn push_str<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        let buf = self.buf.clone();
        let len;
        {
            let mut str = buf.borrow_mut();
            str.push_str(suffix);
            len = str.len();
        }
        let path = Path {
            buf: buf,
            len: len,
        };
        let result = cb(path);
        {
            let mut str = self.buf.borrow_mut();
            str.truncate(self.len)
        }
        result
    }

    pub fn push_index<F, T>(&self, index: usize, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!("[{}]", index), cb)
    }

    pub fn push<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!(".{}", suffix), cb)
    }

    pub fn to_string(&self) -> String {
        let mut str = self.buf.borrow().clone();
        str.truncate(self.len);
        str
    }
}

/// An error during parsing.
#[derive(Debug)]
pub enum ParseError {
    JSON(JSONError),
    MissingField {
        name: String,
        at: String,
    },
    UnknownFields {
        names: Vec<String>,
        at: String,
    },
    TypeError {
        name: String,
        at: String,
        expected: String,
    },
    EmptyObject {
        at: String
    },
    UnknownConstant {
        at: String,
        constant: String,
    }
}

impl Display for ParseError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        (self as &Debug).fmt(formatter)
    }
}
impl StdError for ParseError {
    fn description(&self) -> &str {
        "Error while parsing to JSON"
    }
}

impl ParseError {
    pub fn missing_field(name: &str, at: &Path) -> Self {
        ParseError::MissingField {
            name: name.to_owned(),
            at: at.to_string(),
        }
    }
    pub fn type_error(name: &str, at: &Path, expected: &str) -> Self {
        ParseError::TypeError {
            name: name.to_owned(),
            at: at.to_string(),
            expected: expected.to_owned()
        }
    }
    pub fn unknown_fields(names: Vec<String>, at: &Path) -> Self {
        ParseError::UnknownFields {
            names: names,
            at: at.to_string()
        }
    }
    pub fn unknown_constant(value: &str, at: &Path) -> Self {
        ParseError::UnknownConstant {
            constant: value.to_owned(),
            at: at.to_string()
        }
    }
    pub fn empty_object(at: &Path) -> Self {
        ParseError::EmptyObject {
            at: at.to_string(),
        }
    }
    pub fn json(error: error::Error) -> Self {
        ParseError::JSON(JSONError(error))
    }
}

#[derive(Debug)]
pub struct JSONError(error::Error);

impl Serialize for JSONError {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(&format!("{:?}", self))
    }
}

/// An object that knows how to parse values from JSON into type T.
///
/// The JSON object is expected to be consumed along the way. A successful parse will
/// typically leave an empty JSON object.
pub trait Parser<T: Sized> {
    fn description() -> String;
    fn from_str(source: &str) -> Result<T, ParseError> {
        match serde_json::from_str(source) {
            Err(err) => Err(ParseError::json(err)),
            Ok(mut json) => Self::parse(Path::new(), &mut json)
        }
    }

    /// Parse a single value from JSON, consuming as much as necessary from JSON.
    fn parse(path: Path, source: &mut JSON) -> Result<T, ParseError>;

    /// Parse a field from JSON, consuming it.
    fn take(path: Path, source: &mut JSON, field_name: &str) -> Result<T, ParseError> {
        match Self::take_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }

    /// Parse a field from JSON, consuming it.
    fn take_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<T, ParseError>> {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(mut v) = obj.remove(field_name) {
                Some(Self::parse(path, &mut v))
            } else {
                None
            }
        } else {
            Some(Err(ParseError::type_error(field_name, &path, "object")))
        }
    }

    /// Parse a field containing an array from JSON, consuming the field.
    fn take_vec_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<Vec<T>, ParseError>>
    {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(ref mut json) = obj.remove(field_name) {
                if let JSON::Array(ref mut vec) = *json {
                    let mut result = Vec::with_capacity(vec.len());
                    for (json, i) in vec.iter_mut().zip(0..) {
                        match path.push(&format!("{}[{}]", field_name, i),
                            |path| Self::parse(path, json)
                        ) {
                            Err(error) => return Some(Err(error)),
                            Ok(parsed) => result.push(parsed)
                        }
                    }
                    Some(Ok(result))
                } else {
                    Some(Err(ParseError::type_error(field_name, &path, "array")))
                }
            } else {
                None
            }
        } else {
            Some(Err(ParseError::missing_field(field_name, &path)))
        }
    }

    fn take_vec(path: Path, source: &mut JSON, field_name: &str) -> Result<Vec<T>, ParseError> {
        match Self::take_vec_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }
}

impl Parser<f64> for f64 {
    fn description() -> String {
        "Number".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::I64(val) => Ok(val as f64),
            JSON::F64(val) => Ok(val),
            JSON::U64(val) => Ok(val as f64),
            _ => Err(ParseError::type_error("as float", &path, "number"))
        }
    }
}

impl Parser<bool> for bool {
    fn description() -> String {
        "bool".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Bool(ref b) => Ok(*b),
            JSON::U64(0) | JSON::I64(0) => Ok(false),
            JSON::U64(1) | JSON::I64(1) => Ok(true),
            JSON::String(ref str) if str == "true" => Ok(true),
            JSON::String(ref str) if str == "false" => Ok(false),
            _ => Err(ParseError::type_error("as bool", &path, "boolean"))
        }
    }
}

impl Parser<u8> for u8 {
    fn description() -> String {
        "byte".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_u64() {
            None => Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) if *val > u8::max_value() as u64 =>
                Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) => Ok(*val as u8)
        }
    }
}

impl<T> Parser<Vec<T>> for Vec<T> where T: Parser<T> {
    fn description() -> String {
        format!("Array<{}>", T::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        // Otherwise, parse as an actual array.
        match *source {
            JSON::Array(ref mut array) => {
                let mut result = Vec::with_capacity(array.len());
                for (source, i) in array.iter_mut ().zip(0..) {
                    let value = try!(path.push_index(i, |path| T::parse(path, source)));
                    result.push(value)
                }
                Ok(result)
            }
            JSON::Null => {
                // Accept `null` as an empty array.
                Ok(vec![])
            }
            _ => {
                // Attempt to promote the value to an array.
                let single = try!(path.push_str("", |path| T::parse(path, source)));
                Ok(vec![single])
            }
        }
    }
}

/*
impl<T, U> Parser<(T, U)> for (T, U) where T: Parser<T>, U: Parser<U> {
    fn description() -> String {
        format!("({}, {})", T::description(), U::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Array(ref mut array) if array.len() == 2 => {
                let mut right = array.pop().unwrap(); // We just checked that length == 2
                let mut left = array.pop().unwrap(); // We just checked that length == 2
                let left_parsed = try!(path.push(&T::description() as &str, |path| {T::parse(path, &mut left)}));
                let right_parsed = try!(path.push(&U::description() as &str, |path| {U::parse(path, &mut right)}));
                Ok((left_parsed, right_parsed))
            }
            _ => Err(ParseError::type_error("pair of values", &path, "array"))
        }
    }
}
*/
impl Parser<String> for String {
    fn description() -> String {
        "String".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_string() {
            Some(str) => Ok(str.to_owned()),
            None => Err(ParseError::type_error("string", &path, "string"))
        }
    }
}

impl<T> Parser<Arc<T>> for Arc<T> where T: Parser<T> {
    fn description() -> String {
        T::description()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        Ok(Arc::new(try!(T::parse(path, source))))
    }
}

pub trait ToJSON {
    fn to_json(&self) -> JSON;
}

impl ToJSON for String {
    fn to_json(&self) -> JSON {
        JSON::String(self.clone())
    }
}

impl ToJSON for bool {
    fn to_json(&self) -> JSON {
        JSON::Bool(*self)
    }
}

impl ToJSON for f64 {
    fn to_json(&self) -> JSON {
        JSON::F64(*self)
    }
}

impl ToJSON for usize {
    fn to_json(&self) -> JSON {
        JSON::U64(*self as u64)
    }
}

impl ToJSON for JSON {
    fn to_json(&self) -> JSON {
        self.clone()
    }
}

impl<T> ToJSON for HashSet<T> where T: ToJSON + Eq + Hash {
    fn to_json(&self) -> JSON {
        JSON::Array((*self).iter().map(T::to_json).collect())
    }
}

impl<T> ToJSON for HashMap<String, T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, v)| (k.clone(), T::to_json(v))).collect())
    }
}

impl<T> ToJSON for Vec<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Array(self.iter().map(|x| x.to_json()).collect())
    }
}

impl<'a, T> ToJSON for Vec<(&'a str, T)> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|&(ref k, ref v)| {
            ((*k).to_owned(), v.to_json())
        }).collect())
    }
}

impl <'a> ToJSON for &'a str {
    fn to_json(&self) -> JSON {
        JSON::String((*self).to_owned())
    }
}

impl<'a, T> ToJSON for &'a T where T: ToJSON {
    fn to_json(&self) -> JSON {
        (**self).to_json()
    }
}

impl<K, T, V> ToJSON for HashMap<Id<K>, Result<T, V>> where T: ToJSON, V: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, result)| {
            let k = k.to_string();
            let result = match *result {
                Ok(ref ok) => ok.to_json(),
                Err(ref err) => vec![("Error", err)].to_json()
            };
            (k, result)
        }).collect())
    }
}

impl<T> ToJSON for Option<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        match *self {
            None => JSON::Null,
            Some(ref result) => result.to_json()
        }
    }
}

impl ToJSON for () {
    fn to_json(&self) -> JSON {
        JSON::Null
    }
}

/*
impl<T> Parser<T> for T where T: Deserialize {
    fn parse(_: Path, source: &mut JSON) -> Result<T, ParseError> {
        use serde_json;
        serde_json::from_value(source.clone()).map_err(ParseError::json)
    }
}
*/
<commit_msg>Better deserialization error messages<commit_after>//! Utilities for defining a JSON parser.

use util::Id;

use std::cell::RefCell;
use std::collections::{ HashMap, HashSet };
use std::error::Error as StdError;
use std::fmt::{ Display, Debug, Error as FmtError, Formatter };
use std::hash::Hash;
use std::rc::Rc;
use std::sync::Arc;

use serde_json::error;
use serde::ser::{ Serialize, Serializer };
use serde_json;
pub use serde_json::value::Value as JSON;
use serde::de::Error;

/// Utility function: Make sure that we have consumed all the fields of an object.
pub fn check_fields(path: Path, json: &JSON) -> Result<(), ParseError> {
    if let JSON::Object(ref obj) = *json {
        if obj.is_empty() {
            Ok(())
        } else {
            Err(ParseError::unknown_fields(obj.keys().cloned().collect(), &path))
        }
    } else {
        Ok(())
    }
}

/// A path in the JSON tree. Used for displaying error messages.
#[derive(Clone, Debug)]
pub struct Path {
    buf: Rc<RefCell<String>>,
    len: usize,
}
impl Path {
    /// Create an empty Path.
    pub fn new() -> Self {
        Path {
            buf: Rc::new(RefCell::new(String::new())),
            len: 0,
        }
    }

    /// Push a suffix after a path.
    pub fn push_str<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        let buf = self.buf.clone();
        let len;
        {
            let mut str = buf.borrow_mut();
            str.push_str(suffix);
            len = str.len();
        }
        let path = Path {
            buf: buf,
            len: len,
        };
        let result = cb(path);
        {
            let mut str = self.buf.borrow_mut();
            str.truncate(self.len)
        }
        result
    }

    pub fn push_index<F, T>(&self, index: usize, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!("[{}]", index), cb)
    }

    pub fn push<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!(".{}", suffix), cb)
    }

    pub fn to_string(&self) -> String {
        let mut str = self.buf.borrow().clone();
        str.truncate(self.len);
        str
    }
}

/// An error during parsing.
#[derive(Debug)]
pub enum ParseError {
    JSON(JSONError),
    MissingField {
        name: String,
        at: String,
    },
    UnknownFields {
        names: Vec<String>,
        at: String,
    },
    TypeError {
        name: String,
        at: String,
        expected: String,
    },
    EmptyObject {
        at: String
    },
    UnknownConstant {
        at: String,
        constant: String,
    }
}

impl Display for ParseError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        (self as &Debug).fmt(formatter)
    }
}
impl StdError for ParseError {
    fn description(&self) -> &str {
        "Error while parsing to JSON"
    }
}

impl ParseError {
    pub fn missing_field(name: &str, at: &Path) -> Self {
        ParseError::MissingField {
            name: name.to_owned(),
            at: at.to_string(),
        }
    }
    pub fn type_error(name: &str, at: &Path, expected: &str) -> Self {
        ParseError::TypeError {
            name: name.to_owned(),
            at: at.to_string(),
            expected: expected.to_owned()
        }
    }
    pub fn unknown_fields(names: Vec<String>, at: &Path) -> Self {
        ParseError::UnknownFields {
            names: names,
            at: at.to_string()
        }
    }
    pub fn unknown_constant(value: &str, at: &Path) -> Self {
        ParseError::UnknownConstant {
            constant: value.to_owned(),
            at: at.to_string()
        }
    }
    pub fn empty_object(at: &Path) -> Self {
        ParseError::EmptyObject {
            at: at.to_string(),
        }
    }
    pub fn json(error: error::Error) -> Self {
        ParseError::JSON(JSONError(error))
    }
}

#[derive(Debug)]
pub struct JSONError(error::Error);

impl Serialize for JSONError {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(&format!("{:?}", self))
    }
}

/// An object that knows how to parse values from JSON into type T.
///
/// The JSON object is expected to be consumed along the way. A successful parse will
/// typically leave an empty JSON object.
pub trait Parser<T: Sized> {
    fn description() -> String;
    fn from_str(source: &str) -> Result<T, ParseError> {
        match serde_json::from_str(source) {
            Err(err) => Err(ParseError::json(err)),
            Ok(mut json) => Self::parse(Path::new(), &mut json)
        }
    }

    /// Parse a single value from JSON, consuming as much as necessary from JSON.
    fn parse(path: Path, source: &mut JSON) -> Result<T, ParseError>;

    /// Parse a field from JSON, consuming it.
    fn take(path: Path, source: &mut JSON, field_name: &str) -> Result<T, ParseError> {
        match Self::take_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }

    /// Parse a field from JSON, consuming it.
    fn take_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<T, ParseError>> {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(mut v) = obj.remove(field_name) {
                Some(Self::parse(path, &mut v))
            } else {
                None
            }
        } else {
            Some(Err(ParseError::type_error(field_name, &path, "object")))
        }
    }

    /// Parse a field containing an array from JSON, consuming the field.
    fn take_vec_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<Vec<T>, ParseError>>
    {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(ref mut json) = obj.remove(field_name) {
                if let JSON::Array(ref mut vec) = *json {
                    let mut result = Vec::with_capacity(vec.len());
                    for (json, i) in vec.iter_mut().zip(0..) {
                        match path.push(&format!("[{}]", i),
                            |path| Self::parse(path, json)
                        ) {
                            Err(error) => return Some(Err(error)),
                            Ok(parsed) => result.push(parsed)
                        }
                    }
                    Some(Ok(result))
                } else {
                    Some(Err(ParseError::type_error(field_name, &path, "array")))
                }
            } else {
                None
            }
        } else {
            Some(Err(ParseError::missing_field(field_name, &path)))
        }
    }

    fn take_vec(path: Path, source: &mut JSON, field_name: &str) -> Result<Vec<T>, ParseError> {
        match Self::take_vec_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }
}

impl Parser<f64> for f64 {
    fn description() -> String {
        "Number".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::I64(val) => Ok(val as f64),
            JSON::F64(val) => Ok(val),
            JSON::U64(val) => Ok(val as f64),
            _ => Err(ParseError::type_error("as float", &path, "number"))
        }
    }
}

impl Parser<bool> for bool {
    fn description() -> String {
        "bool".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Bool(ref b) => Ok(*b),
            JSON::U64(0) | JSON::I64(0) => Ok(false),
            JSON::U64(1) | JSON::I64(1) => Ok(true),
            JSON::String(ref str) if str == "true" => Ok(true),
            JSON::String(ref str) if str == "false" => Ok(false),
            _ => Err(ParseError::type_error("as bool", &path, "boolean"))
        }
    }
}

impl Parser<u8> for u8 {
    fn description() -> String {
        "byte".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_u64() {
            None => Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) if *val > u8::max_value() as u64 =>
                Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) => Ok(*val as u8)
        }
    }
}

impl<T> Parser<Vec<T>> for Vec<T> where T: Parser<T> {
    fn description() -> String {
        format!("Array<{}>", T::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        // Otherwise, parse as an actual array.
        match *source {
            JSON::Array(ref mut array) => {
                let mut result = Vec::with_capacity(array.len());
                for (source, i) in array.iter_mut ().zip(0..) {
                    let value = try!(path.push_index(i, |path| T::parse(path, source)));
                    result.push(value)
                }
                Ok(result)
            }
            JSON::Null => {
                // Accept `null` as an empty array.
                Ok(vec![])
            }
            _ => {
                // Attempt to promote the value to an array.
                let single = try!(path.push_str("", |path| T::parse(path, source)));
                Ok(vec![single])
            }
        }
    }
}

/*
impl<T, U> Parser<(T, U)> for (T, U) where T: Parser<T>, U: Parser<U> {
    fn description() -> String {
        format!("({}, {})", T::description(), U::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Array(ref mut array) if array.len() == 2 => {
                let mut right = array.pop().unwrap(); // We just checked that length == 2
                let mut left = array.pop().unwrap(); // We just checked that length == 2
                let left_parsed = try!(path.push(&T::description() as &str, |path| {T::parse(path, &mut left)}));
                let right_parsed = try!(path.push(&U::description() as &str, |path| {U::parse(path, &mut right)}));
                Ok((left_parsed, right_parsed))
            }
            _ => Err(ParseError::type_error("pair of values", &path, "array"))
        }
    }
}
*/
impl Parser<String> for String {
    fn description() -> String {
        "String".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_string() {
            Some(str) => Ok(str.to_owned()),
            None => Err(ParseError::type_error("string", &path, "string"))
        }
    }
}

impl<T> Parser<Arc<T>> for Arc<T> where T: Parser<T> {
    fn description() -> String {
        T::description()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        Ok(Arc::new(try!(T::parse(path, source))))
    }
}

pub trait ToJSON {
    fn to_json(&self) -> JSON;
}

impl ToJSON for String {
    fn to_json(&self) -> JSON {
        JSON::String(self.clone())
    }
}

impl ToJSON for bool {
    fn to_json(&self) -> JSON {
        JSON::Bool(*self)
    }
}

impl ToJSON for f64 {
    fn to_json(&self) -> JSON {
        JSON::F64(*self)
    }
}

impl ToJSON for usize {
    fn to_json(&self) -> JSON {
        JSON::U64(*self as u64)
    }
}

impl ToJSON for JSON {
    fn to_json(&self) -> JSON {
        self.clone()
    }
}

impl<T> ToJSON for HashSet<T> where T: ToJSON + Eq + Hash {
    fn to_json(&self) -> JSON {
        JSON::Array((*self).iter().map(T::to_json).collect())
    }
}

impl<T> ToJSON for HashMap<String, T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, v)| (k.clone(), T::to_json(v))).collect())
    }
}

impl<T> ToJSON for Vec<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Array(self.iter().map(|x| x.to_json()).collect())
    }
}

impl<'a, T> ToJSON for Vec<(&'a str, T)> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|&(ref k, ref v)| {
            ((*k).to_owned(), v.to_json())
        }).collect())
    }
}

impl <'a> ToJSON for &'a str {
    fn to_json(&self) -> JSON {
        JSON::String((*self).to_owned())
    }
}

impl<'a, T> ToJSON for &'a T where T: ToJSON {
    fn to_json(&self) -> JSON {
        (**self).to_json()
    }
}

impl<K, T, V> ToJSON for HashMap<Id<K>, Result<T, V>> where T: ToJSON, V: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, result)| {
            let k = k.to_string();
            let result = match *result {
                Ok(ref ok) => ok.to_json(),
                Err(ref err) => vec![("Error", err)].to_json()
            };
            (k, result)
        }).collect())
    }
}

impl<T> ToJSON for Option<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        match *self {
            None => JSON::Null,
            Some(ref result) => result.to_json()
        }
    }
}

impl ToJSON for () {
    fn to_json(&self) -> JSON {
        JSON::Null
    }
}

/*
impl<T> Parser<T> for T where T: Deserialize {
    fn parse(_: Path, source: &mut JSON) -> Result<T, ParseError> {
        use serde_json;
        serde_json::from_value(source.clone()).map_err(ParseError::json)
    }
}
*/
<|endoftext|>


<commit_before>use bytes::{BufMut, BytesMut};

use std::io;
use std::str;

use tokio_core::net::TcpStream;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

pub type ImapTransport = Framed<TlsStream<TcpStream>, ImapCodec>;

pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}

pub struct ImapCodec;

impl Decoder for ImapCodec {
    type Item = String;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut)
             -> Result<Option<String>, io::Error> {
        if let Some(n) = buf.iter().position(|b| *b == b'\n') {
            let line = buf.split_to(n);
            buf.split_to(1);
            return match str::from_utf8(line.get(..).unwrap()) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other,
                                             "invalid string")),
            }
        } else {
            Ok(None)
        }
    }
}

impl Encoder for ImapCodec {
    type Item = String;
    type Error = io::Error;
    fn encode(&mut self, msg: String, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.as_bytes());
        dst.put("\r\n");
        Ok(())
    }
}

<commit_msg>Silence warning about unused protocol states<commit_after>use bytes::{BufMut, BytesMut};

use std::io;
use std::str;

use tokio_core::net::TcpStream;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

pub type ImapTransport = Framed<TlsStream<TcpStream>, ImapCodec>;

#[allow(dead_code)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}

pub struct ImapCodec;

impl Decoder for ImapCodec {
    type Item = String;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut)
             -> Result<Option<String>, io::Error> {
        if let Some(n) = buf.iter().position(|b| *b == b'\n') {
            let line = buf.split_to(n);
            buf.split_to(1);
            return match str::from_utf8(line.get(..).unwrap()) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other,
                                             "invalid string")),
            }
        } else {
            Ok(None)
        }
    }
}

impl Encoder for ImapCodec {
    type Item = String;
    type Error = io::Error;
    fn encode(&mut self, msg: String, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.as_bytes());
        dst.put("\r\n");
        Ok(())
    }
}

<|endoftext|>


<commit_before>use std::io;
use std::iter::Map;
use std::io::BufReader;
use std::fs::File;

use serde_json;

use cgmath::*;
use shape::*;
use vec3d::Vec3d;
use vec3d::Rotatable;
use light::Light;

use color;
use color::Color;

#[derive(Serialize, Deserialize)]
pub struct Scene {
    shapes: Vec<Shape>,
    lights: Vec<Light>,
    camera_pos: Vec3d,
    camera_dir: Vec3d,
    camera_up: Vec3d,
    max_reflection: i32,
}

#[derive(Debug)]
pub enum CraycrayError {
    Io(io::Error),
    Serde(serde_json::Error),
}

impl Scene {
    pub fn new(camera_pos: Vec3d, camera_dir: Vec3d, camera_up: Vec3d) -> Scene {
        Scene {
            shapes: Vec::new(),
            lights: Vec::new(),
            camera_pos: camera_pos,
            camera_dir: camera_dir,
            camera_up: camera_up,
            max_reflection: 4,
        }
    }

    pub fn from_file(filename: &str) -> Result<Scene, CraycrayError> {
        File::open(filename)
            .map_err(CraycrayError::Io)
            .and_then(|f| serde_json::from_reader(BufReader::new(f)).map_err(CraycrayError::Serde))
    }

    pub fn add_shape(&mut self, s: Shape) {
        self.shapes.push(s);
    }

    pub fn step(&mut self) {
        // self.light.translate(&[1.0, 0.0, 0.0]);
    }

    pub fn mv_camera_fwd(&mut self) {
        self.camera_pos = self.camera_pos + self.camera_dir;
    }

    pub fn mv_camera_back(&mut self) {
        self.camera_pos = self.camera_pos - self.camera_dir;
    }

    pub fn rot_camera(&mut self, x_rot: f64, y_rot: f64) {
        // project camera_dir to X plane
        let mut x_proj = self.camera_dir;
        x_proj.y = 0.0;
        x_proj = x_proj.normalize();

        let angle = if x_proj.x < 0.0 {
            -Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        } else {
            Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        };

        self.camera_dir = self.camera_dir
            .rot_y(x_rot)
            .rot_y(-angle)
            .rot_x(y_rot)
            .rot_y(angle)
            .normalize();
    }

    /// Returns an iterator for a line at given resolution
    pub fn line_iter(&self, h: usize, v: usize, l: usize) -> LineIter {
        LineIter::new(self, h, v, l)
    }

    /// line_iter converted to (u8, u8, u8)
    pub fn line_iter_u8(&self,
                        h: usize,
                        v: usize,
                        l: usize)
                        -> Map<LineIter, fn(Color) -> (u8, u8, u8)> {
        self.line_iter(h, v, l).map(Color::col_to_u8)
    }

    // Recursively trace lines
    fn trace(&self, point: Vec3d, dir: Vec3d, depth: i32) -> Color {
        if depth >= self.max_reflection {
            return color::BLACK;
        }

        if let Some(intersect) = self.closest_q(point, dir) {
            let local = self.lights
                .iter()
                .map(|l| {
                         let (f_unit, dist) = l.feeler(intersect.point);
                         let direct_light = self.is_direct_light(intersect.point, f_unit, dist);
                         if direct_light {
                             phong(point, &intersect, l)
                         } else {
                             color::BLACK
                         }
                     })
                .sum::<Color>() + intersect.material.ambient_color;

            let tmp = (intersect.point - point).normalize();
            let reflection_dir = tmp - (intersect.normal * 2.0 * tmp.dot(intersect.normal));

            let reflected = self.trace(intersect.point, reflection_dir, depth + 1);

            local + (reflected * intersect.material.reflectivity)
        } else {
            color::BLACK
        }
    }

    // Is there anything on the path to the light
    fn is_direct_light(&self, point: Vec3d, dir: Vec3d, dl: f64) -> bool {
        !self.shapes
             .iter()
             .map(|x| x.intersect_dist(point, dir))
             .any(|dist_opt| dist_opt.map_or(false, |i| i < dl))
    }

    // Checks against all objects and returns closest intersection
    fn closest_q(&self, point: Vec3d, dir: Vec3d) -> Option<Intersection> {
        let find_min_opt = |min, (s, op_val)| {
            match (min, op_val) {
                (Some((_, min_val)), Some(val)) if val < min_val => Some((s, val)),
                (None, Some(val)) => Some((s, val)),
                _ => min,
            }
        };

        self.shapes
            .iter()
            .map(|x| (x, x.intersect_dist(point, dir)))
            .fold(None, find_min_opt)
            .and_then(|(s, _)| s.intersect(point, dir))
    }
}

/// Iterator that iterates over a single line
pub struct LineIter<'a> {
    h_res: usize,
    x: usize,
    right_step: Vec3d,
    point: Vec3d,
    scene: &'a Scene,
}

impl<'a> LineIter<'a> {
    fn new(scene: &Scene, h: usize, v: usize, l: usize) -> LineIter {
        let left = scene.camera_dir.cross(scene.camera_up).normalize();
        let up = left.cross(scene.camera_dir).normalize();
        let mut point = left + up + scene.camera_dir;
        let right_step = left * (-2.0 / h as f64);
        let down_step = up * (-2.0 / v as f64);

        point = point + down_step * (l as f64);
        LineIter {
            h_res: h,
            x: 0,
            point: point,
            right_step: right_step,
            scene: scene,
        }
    }
}

impl<'a> Iterator for LineIter<'a> {
    type Item = Color;

    fn next(&mut self) -> Option<Self::Item> {
        if self.x >= self.h_res {
            return None;
        }
        self.x += 1;

        self.point = self.point + self.right_step;

        let c = self.scene
            .trace(self.scene.camera_pos, self.point.normalize(), 0);

        Some(c)
    }
}

// Calculate color with Phong model
fn phong(view_point: Vec3d, intersection: &Intersection, light: &Light) -> Color {
    let point_material = intersection.material;
    let light_pos = light.get_pos();
    let light_color = light.get_color();

    let mut d = (light_pos - intersection.point)
        .normalize()
        .dot(intersection.normal);

    if d < 0.0 {
        d = 0.0;
    }

    let v = (view_point - intersection.point).normalize();
    let lt = (light_pos - intersection.point).normalize();
    let r = intersection.normal * (2.0 * intersection.normal.dot(lt)) - lt;

    let mut s = r.dot(v).powf(point_material.shininess);
    if s < 0.0 {
        s = 0.0;
    }

    let diffuse = light_color * point_material.diffuse_color * d;
    let specular = light_color * point_material.specular_color * s;

    diffuse + specular
}
<commit_msg>Fix indentation in closure<commit_after>use std::io;
use std::iter::Map;
use std::io::BufReader;
use std::fs::File;

use serde_json;

use cgmath::*;
use shape::*;
use vec3d::Vec3d;
use vec3d::Rotatable;
use light::Light;

use color;
use color::Color;

#[derive(Serialize, Deserialize)]
pub struct Scene {
    shapes: Vec<Shape>,
    lights: Vec<Light>,
    camera_pos: Vec3d,
    camera_dir: Vec3d,
    camera_up: Vec3d,
    max_reflection: i32,
}

#[derive(Debug)]
pub enum CraycrayError {
    Io(io::Error),
    Serde(serde_json::Error),
}

impl Scene {
    pub fn new(camera_pos: Vec3d, camera_dir: Vec3d, camera_up: Vec3d) -> Scene {
        Scene {
            shapes: Vec::new(),
            lights: Vec::new(),
            camera_pos: camera_pos,
            camera_dir: camera_dir,
            camera_up: camera_up,
            max_reflection: 4,
        }
    }

    pub fn from_file(filename: &str) -> Result<Scene, CraycrayError> {
        File::open(filename)
            .map_err(CraycrayError::Io)
            .and_then(|f| serde_json::from_reader(BufReader::new(f)).map_err(CraycrayError::Serde))
    }

    pub fn add_shape(&mut self, s: Shape) {
        self.shapes.push(s);
    }

    pub fn step(&mut self) {
        // self.light.translate(&[1.0, 0.0, 0.0]);
    }

    pub fn mv_camera_fwd(&mut self) {
        self.camera_pos = self.camera_pos + self.camera_dir;
    }

    pub fn mv_camera_back(&mut self) {
        self.camera_pos = self.camera_pos - self.camera_dir;
    }

    pub fn rot_camera(&mut self, x_rot: f64, y_rot: f64) {
        // project camera_dir to X plane
        let mut x_proj = self.camera_dir;
        x_proj.y = 0.0;
        x_proj = x_proj.normalize();

        let angle = if x_proj.x < 0.0 {
            -Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        } else {
            Vec3d::new(0.0, 0.0, 1.0).dot(x_proj).acos()
        };

        self.camera_dir = self.camera_dir
            .rot_y(x_rot)
            .rot_y(-angle)
            .rot_x(y_rot)
            .rot_y(angle)
            .normalize();
    }

    /// Returns an iterator for a line at given resolution
    pub fn line_iter(&self, h: usize, v: usize, l: usize) -> LineIter {
        LineIter::new(self, h, v, l)
    }

    /// line_iter converted to (u8, u8, u8)
    pub fn line_iter_u8(&self,
                        h: usize,
                        v: usize,
                        l: usize)
                        -> Map<LineIter, fn(Color) -> (u8, u8, u8)> {
        self.line_iter(h, v, l).map(Color::col_to_u8)
    }

    // Recursively trace lines
    fn trace(&self, point: Vec3d, dir: Vec3d, depth: i32) -> Color {
        if depth >= self.max_reflection {
            return color::BLACK;
        }

        if let Some(intersect) = self.closest_q(point, dir) {
            let local = self.lights
                .iter()
                .map(|l| {
                    let (f_unit, dist) = l.feeler(intersect.point);
                    let direct_light = self.is_direct_light(intersect.point, f_unit, dist);
                    if direct_light {
                        phong(point, &intersect, l)
                    } else {
                        color::BLACK
                    }
                })
                .sum::<Color>() + intersect.material.ambient_color;

            let tmp = (intersect.point - point).normalize();
            let reflection_dir = tmp - (intersect.normal * 2.0 * tmp.dot(intersect.normal));

            let reflected = self.trace(intersect.point, reflection_dir, depth + 1);

            local + (reflected * intersect.material.reflectivity)
        } else {
            color::BLACK
        }
    }

    // Is there anything on the path to the light
    fn is_direct_light(&self, point: Vec3d, dir: Vec3d, dl: f64) -> bool {
        !self.shapes
             .iter()
             .map(|x| x.intersect_dist(point, dir))
             .any(|dist_opt| dist_opt.map_or(false, |i| i < dl))
    }

    // Checks against all objects and returns closest intersection
    fn closest_q(&self, point: Vec3d, dir: Vec3d) -> Option<Intersection> {
        let find_min_opt = |min, (s, op_val)| {
            match (min, op_val) {
                (Some((_, min_val)), Some(val)) if val < min_val => Some((s, val)),
                (None, Some(val)) => Some((s, val)),
                _ => min,
            }
        };

        self.shapes
            .iter()
            .map(|x| (x, x.intersect_dist(point, dir)))
            .fold(None, find_min_opt)
            .and_then(|(s, _)| s.intersect(point, dir))
    }
}

/// Iterator that iterates over a single line
pub struct LineIter<'a> {
    h_res: usize,
    x: usize,
    right_step: Vec3d,
    point: Vec3d,
    scene: &'a Scene,
}

impl<'a> LineIter<'a> {
    fn new(scene: &Scene, h: usize, v: usize, l: usize) -> LineIter {
        let left = scene.camera_dir.cross(scene.camera_up).normalize();
        let up = left.cross(scene.camera_dir).normalize();
        let mut point = left + up + scene.camera_dir;
        let right_step = left * (-2.0 / h as f64);
        let down_step = up * (-2.0 / v as f64);

        point = point + down_step * (l as f64);
        LineIter {
            h_res: h,
            x: 0,
            point: point,
            right_step: right_step,
            scene: scene,
        }
    }
}

impl<'a> Iterator for LineIter<'a> {
    type Item = Color;

    fn next(&mut self) -> Option<Self::Item> {
        if self.x >= self.h_res {
            return None;
        }
        self.x += 1;

        self.point = self.point + self.right_step;

        let c = self.scene
            .trace(self.scene.camera_pos, self.point.normalize(), 0);

        Some(c)
    }
}

// Calculate color with Phong model
fn phong(view_point: Vec3d, intersection: &Intersection, light: &Light) -> Color {
    let point_material = intersection.material;
    let light_pos = light.get_pos();
    let light_color = light.get_color();

    let mut d = (light_pos - intersection.point)
        .normalize()
        .dot(intersection.normal);

    if d < 0.0 {
        d = 0.0;
    }

    let v = (view_point - intersection.point).normalize();
    let lt = (light_pos - intersection.point).normalize();
    let r = intersection.normal * (2.0 * intersection.normal.dot(lt)) - lt;

    let mut s = r.dot(v).powf(point_material.shininess);
    if s < 0.0 {
        s = 0.0;
    }

    let diffuse = light_color * point_material.diffuse_color * d;
    let specular = light_color * point_material.specular_color * s;

    diffuse + specular
}
<|endoftext|>


<commit_before>//! Defines the scene struct which contains the various objects defining the scene.
//! This includes the geometry, instances of the geometry, the camera and so on.

use std::sync::Arc;
use std::path::Path;

use linalg::{Transform, Point, Vector, Ray};
use film::{Camera, Colorf};
use geometry::{Sphere, Plane, Instance, BoundableGeom, Intersection, Mesh, BVH};
use material::{Matte, SpecularMetal, Glass, Material, Merl};
use integrator::{self, Integrator};
use light::{self, Light};

/// The scene containing the objects and camera configuration we'd like to render,
/// shared immutably among the ray tracing threads
pub struct Scene {
    pub camera: Camera,
    pub bvh: BVH<Instance>,
    pub integrator: Arc<Box<Integrator + Send + Sync>>,
    /// TODO: Only one light for now
    pub light: Arc<Box<Light + Send + Sync>>,
}

impl Scene {
    /// Create our (currently) hard-coded scene, passing in the render target
    /// dimensions so we can set the projection matrix for the camera
    pub fn new(w: usize, h: usize) -> Scene {
        let sphere = Arc::new(Box::new(Sphere::new(1.0)) as Box<BoundableGeom + Send + Sync>);
        let plane = Arc::new(Box::new(Plane) as Box<BoundableGeom + Send + Sync>);

        let white_wall = Arc::new(Box::new(Matte::new(&Colorf::new(1.0, 1.0, 1.0), 1.0))
                                  as Box<Material + Send + Sync>);
        let red_wall = Arc::new(Box::new(Matte::new(&Colorf::new(1.0, 0.2, 0.2), 1.0))
                                as Box<Material + Send + Sync>);
        let blue_wall = Arc::new(Box::new(Matte::new(&Colorf::new(0.2, 0.2, 1.0), 1.0))
                                 as Box<Material + Send + Sync>);

        /*
        let mut models = Mesh::load_obj(Path::new("./rust-logo.obj"));
        let rust_logo = Arc::new(Box::new(models.remove("rust_logo").unwrap()) as Box<BoundableGeom + Send + Sync>);

        let mut models = Mesh::load_obj(Path::new("./buddha.obj"));
        let buddha = Arc::new(Box::new(models.remove("buddha").unwrap()) as Box<BoundableGeom + Send + Sync>);

        let mut models = Mesh::load_obj(Path::new("./dragon.obj"));
        let dragon = Arc::new(Box::new(models.remove("dragon").unwrap()) as Box<BoundableGeom + Send + Sync>);

        let oxidized_steel = Arc::new(Box::new(Merl::load_file(Path::new("black-oxidized-steel.binary")))
                                      as Box<Material + Send + Sync>);
        let gold_paint = Arc::new(Box::new(Merl::load_file(Path::new("gold-metallic-paint.binary")))
                                  as Box<Material + Send + Sync>);
        let blue_acrylic = Arc::new(Box::new(Merl::load_file(Path::new("blue-acrylic.binary")))
                                    as Box<Material + Send + Sync>);
        */

        let instances = vec![
            /*
            Instance::new(rust_logo, oxidized_steel, Transform::translate(&Vector::new(0.0, 6.0, 12.0))
                          * Transform::rotate_z(180.0) * Transform::rotate_y(90.0)
                          * Transform::scale(&Vector::broadcast(12.0)), "rust_logo"),
            Instance::new(buddha, gold_paint, Transform::translate(&Vector::new(-9.0, 0.5, 7.55))
                          * Transform::rotate_z(-140.0) * Transform::rotate_x(90.0)
                          * Transform::scale(&Vector::broadcast(17.0)), "buddha"),
            Instance::new(dragon, blue_acrylic, Transform::translate(&Vector::new(8.25, 3.5, 3.7))
                          * Transform::rotate_z(120.0) * Transform::rotate_x(90.0)
                          * Transform::scale(&Vector::broadcast(13.0)), "dragon"),
            */
            // The back wall
            Instance::new(plane.clone(), white_wall.clone(), Transform::translate(&Vector::new(0.0, 20.0, 12.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_x(90.0), "back_wall"),
            // The left wall
            Instance::new(plane.clone(), red_wall.clone(), Transform::translate(&Vector::new(-15.0, 0.0, 12.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_y(90.0), "left_wall"),
            // The right wall
            Instance::new(plane.clone(), blue_wall.clone(), Transform::translate(&Vector::new(15.0, 0.0, 12.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_y(-90.0), "right_wall"),
            // The top wall
            Instance::new(plane.clone(), white_wall.clone(), Transform::translate(&Vector::new(0.0, 0.0, 24.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_x(180.0), "top_wall"),
            // The bottom wall
            Instance::new(plane.clone(), white_wall.clone(), Transform::translate(&Vector::new(0.0, 0.0, 0.0))
                          * Transform::scale(&Vector::broadcast(32.0)), "bottom_wall"),
            // The reflective sphere
            Instance::new(sphere.clone(),
            Arc::new(Box::new(SpecularMetal::new(&Colorf::new(0.155, 0.116, 0.138), &Colorf::new(4.828, 3.122, 2.146)))
                     as Box<Material + Send + Sync>), Transform::translate(&Vector::new(-6.0, 8.0, 5.0))
                    * Transform::scale(&Vector::broadcast(5.0)), "metal_sphere"),
            // The glass sphere
            Instance::new(sphere.clone(),
            Arc::new(Box::new(Glass::new(&Colorf::broadcast(1.0), &Colorf::broadcast(1.0), 1.52))
                     as Box<Material + Send + Sync>), Transform::translate(&Vector::new(6.0, -2.0, 5.0))
                     * Transform::scale(&Vector::broadcast(5.0)), "glass_sphere")
        ];
        let light_color = Colorf::broadcast(200.0) * Colorf::new(0.780131, 0.780409, 0.775833);
        Scene {
            camera: Camera::new(Transform::look_at(&Point::new(0.0, -60.0, 12.0),
                &Point::new(0.0, 0.0, 12.0), &Vector::new(0.0, 0.0, 1.0)), 30.0, (w, h)),
            bvh: BVH::new(4, instances),
            integrator: Arc::new(Box::new(integrator::Path::new(4, 8)) as Box<Integrator + Send + Sync>),
            light: Arc::new(Box::new(light::Point::new(&Point::new(0.0, 0.0, 22.0), &light_color))
                            as Box<Light + Send + Sync>),
        }
    }
    /// Test the ray for intersections against the objects in the scene.
    /// Returns Some(Intersection) if an intersection was found and None if not.
    pub fn intersect(&self, ray: &mut Ray) -> Option<Intersection> {
        self.bvh.intersect(ray, |r, i| i.intersect(r))
    }
}

<commit_msg>Testing plastic mat<commit_after>//! Defines the scene struct which contains the various objects defining the scene.
//! This includes the geometry, instances of the geometry, the camera and so on.

use std::sync::Arc;
use std::path::Path;

use linalg::{Transform, Point, Vector, Ray};
use film::{Camera, Colorf};
use geometry::{Sphere, Plane, Instance, BoundableGeom, Intersection, Mesh, BVH};
use material::{Matte, SpecularMetal, Glass, Material, Merl, Plastic};
use integrator::{self, Integrator};
use light::{self, Light};

/// The scene containing the objects and camera configuration we'd like to render,
/// shared immutably among the ray tracing threads
pub struct Scene {
    pub camera: Camera,
    pub bvh: BVH<Instance>,
    pub integrator: Arc<Box<Integrator + Send + Sync>>,
    /// TODO: Only one light for now
    pub light: Arc<Box<Light + Send + Sync>>,
}

impl Scene {
    /// Create our (currently) hard-coded scene, passing in the render target
    /// dimensions so we can set the projection matrix for the camera
    pub fn new(w: usize, h: usize) -> Scene {
        let sphere = Arc::new(Box::new(Sphere::new(1.0)) as Box<BoundableGeom + Send + Sync>);
        let plane = Arc::new(Box::new(Plane) as Box<BoundableGeom + Send + Sync>);

        let white_wall = Arc::new(Box::new(Matte::new(&Colorf::new(1.0, 1.0, 1.0), 1.0))
                                  as Box<Material + Send + Sync>);
        let red_wall = Arc::new(Box::new(Matte::new(&Colorf::new(1.0, 0.2, 0.2), 1.0))
                                as Box<Material + Send + Sync>);
        let blue_wall = Arc::new(Box::new(Matte::new(&Colorf::new(0.2, 0.2, 1.0), 1.0))
                                 as Box<Material + Send + Sync>);
        let plastic = Arc::new(Box::new(Plastic::new(&Colorf::broadcast(0.2),
                                        &Colorf::broadcast(0.7), 0.6))
                              as Box<Material + Send + Sync>);

        /*
        let mut models = Mesh::load_obj(Path::new("./rust-logo.obj"));
        let rust_logo = Arc::new(Box::new(models.remove("rust_logo").unwrap()) as Box<BoundableGeom + Send + Sync>);

        let mut models = Mesh::load_obj(Path::new("./buddha.obj"));
        let buddha = Arc::new(Box::new(models.remove("buddha").unwrap()) as Box<BoundableGeom + Send + Sync>);

        let mut models = Mesh::load_obj(Path::new("./dragon.obj"));
        let dragon = Arc::new(Box::new(models.remove("dragon").unwrap()) as Box<BoundableGeom + Send + Sync>);

        let oxidized_steel = Arc::new(Box::new(Merl::load_file(Path::new("black-oxidized-steel.binary")))
                                      as Box<Material + Send + Sync>);
        let gold_paint = Arc::new(Box::new(Merl::load_file(Path::new("gold-metallic-paint.binary")))
                                  as Box<Material + Send + Sync>);
        let blue_acrylic = Arc::new(Box::new(Merl::load_file(Path::new("blue-acrylic.binary")))
                                    as Box<Material + Send + Sync>);
        */

        let instances = vec![
            /*
            Instance::new(rust_logo, oxidized_steel, Transform::translate(&Vector::new(0.0, 6.0, 12.0))
                          * Transform::rotate_z(180.0) * Transform::rotate_y(90.0)
                          * Transform::scale(&Vector::broadcast(12.0)), "rust_logo"),
            Instance::new(buddha, gold_paint, Transform::translate(&Vector::new(-9.0, 0.5, 7.55))
                          * Transform::rotate_z(-140.0) * Transform::rotate_x(90.0)
                          * Transform::scale(&Vector::broadcast(17.0)), "buddha"),
            Instance::new(dragon, blue_acrylic, Transform::translate(&Vector::new(8.25, 3.5, 3.7))
                          * Transform::rotate_z(120.0) * Transform::rotate_x(90.0)
                          * Transform::scale(&Vector::broadcast(13.0)), "dragon"),
            */
            // The back wall
            Instance::new(plane.clone(), white_wall.clone(), Transform::translate(&Vector::new(0.0, 20.0, 12.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_x(90.0), "back_wall"),
            // The left wall
            Instance::new(plane.clone(), red_wall.clone(), Transform::translate(&Vector::new(-15.0, 0.0, 12.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_y(90.0), "left_wall"),
            // The right wall
            Instance::new(plane.clone(), blue_wall.clone(), Transform::translate(&Vector::new(15.0, 0.0, 12.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_y(-90.0), "right_wall"),
            // The top wall
            Instance::new(plane.clone(), white_wall.clone(), Transform::translate(&Vector::new(0.0, 0.0, 24.0))
                          * Transform::scale(&Vector::broadcast(32.0)) * Transform::rotate_x(180.0), "top_wall"),
            // The bottom wall
            Instance::new(plane.clone(), white_wall.clone(), Transform::translate(&Vector::new(0.0, 0.0, 0.0))
                          * Transform::scale(&Vector::broadcast(32.0)), "bottom_wall"),
            // The reflective sphere
            Instance::new(sphere.clone(), plastic, Transform::translate(&Vector::new(-6.0, 8.0, 5.0))
                    * Transform::scale(&Vector::broadcast(5.0)), "metal_sphere"),
            // The glass sphere
            /*
            Instance::new(sphere.clone(),
            Arc::new(Box::new(Glass::new(&Colorf::broadcast(1.0), &Colorf::broadcast(1.0), 1.52))
                     as Box<Material + Send + Sync>), Transform::translate(&Vector::new(6.0, -2.0, 5.0))
                     * Transform::scale(&Vector::broadcast(5.0)), "glass_sphere")
            */
        ];
        let light_color = Colorf::broadcast(200.0) * Colorf::new(0.780131, 0.780409, 0.775833);
        Scene {
            camera: Camera::new(Transform::look_at(&Point::new(0.0, -60.0, 12.0),
                &Point::new(0.0, 0.0, 12.0), &Vector::new(0.0, 0.0, 1.0)), 30.0, (w, h)),
            bvh: BVH::new(4, instances),
            integrator: Arc::new(Box::new(integrator::Path::new(4, 8)) as Box<Integrator + Send + Sync>),
            light: Arc::new(Box::new(light::Point::new(&Point::new(0.0, 0.0, 22.0), &light_color))
                            as Box<Light + Send + Sync>),
        }
    }
    /// Test the ray for intersections against the objects in the scene.
    /// Returns Some(Intersection) if an intersection was found and None if not.
    pub fn intersect(&self, ray: &mut Ray) -> Option<Intersection> {
        self.bvh.intersect(ray, |r, i| i.intersect(r))
    }
}

<|endoftext|>


<commit_before>use iron::headers::{
	AcceptRanges, ByteRangeSpec, ContentLength, ContentRange, ContentRangeSpec, Range, RangeUnit,
};
use iron::modifier::Modifier;
use iron::modifiers::Header;
use iron::prelude::*;
use iron::response::WriteBody;
use iron::status::{self, Status};
use rocket;
use rocket::response::{self, Responder};
use std::cmp;
use std::fs::{self, File};
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::path::Path;
use std::str::FromStr;

use errors::{Error, ErrorKind};

pub fn deliver(path: &Path, range_header: Option<&Range>) -> IronResult<Response> {
	match fs::metadata(path) {
		Ok(meta) => meta,
		Err(e) => {
			let status = match e.kind() {
				io::ErrorKind::NotFound => status::NotFound,
				io::ErrorKind::PermissionDenied => status::Forbidden,
				_ => status::InternalServerError,
			};
			return Err(IronError::new(e, status));
		}
	};

	let accept_range_header = Header(AcceptRanges(vec![RangeUnit::Bytes]));
	let range_header = range_header.cloned();

	match range_header {
		None => Ok(Response::with((status::Ok, path, accept_range_header))),
		Some(range) => match range {
			Range::Bytes(vec_range) => {
				if let Ok(partial_file) = PartialFile::from_path(path, vec_range) {
					Ok(Response::with((
						status::Ok,
						partial_file,
						accept_range_header,
					)))
				} else {
					Err(Error::from(ErrorKind::FileNotFound).into())
				}
			}
			_ => Ok(Response::with(status::RangeNotSatisfiable)),
		},
	}
}

pub enum PartialFileRange {
	AllFrom(u64),
	FromTo(u64, u64),
	Last(u64),
}

impl From<ByteRangeSpec> for PartialFileRange {
	fn from(b: ByteRangeSpec) -> PartialFileRange {
		match b {
			ByteRangeSpec::AllFrom(from) => PartialFileRange::AllFrom(from),
			ByteRangeSpec::FromTo(from, to) => PartialFileRange::FromTo(from, to),
			ByteRangeSpec::Last(last) => PartialFileRange::Last(last),
		}
	}
}

pub struct PartialFile {
	file: File,
	range: PartialFileRange,
}

impl From<Vec<ByteRangeSpec>> for PartialFileRange {
	fn from(v: Vec<ByteRangeSpec>) -> PartialFileRange {
		match v.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		}
	}
}

impl PartialFile {
	pub fn new<Range>(file: File, range: Range) -> PartialFile
	where
		Range: Into<PartialFileRange>,
	{
		let range = range.into();
		PartialFile { file, range }
	}

	pub fn from_path<P: AsRef<Path>, Range>(path: P, range: Range) -> Result<PartialFile, io::Error>
	where
		Range: Into<PartialFileRange>,
	{
		let file = File::open(path.as_ref())?;
		Ok(Self::new(file, range))
	}
}

impl Modifier<Response> for PartialFile {
	fn modify(self, res: &mut Response) {
		let metadata: Option<_> = self.file.metadata().ok();
		let file_length: Option<u64> = metadata.map(|m| m.len());
		let range: Option<(u64, u64)> = truncate_range(&self.range, &file_length);

		if let Some(range) = range {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: Some(range),
				instance_length: file_length,
			});
			let content_len = range.1 - range.0 + 1;
			res.headers.set(ContentLength(content_len));
			res.headers.set(content_range);
			let partial_content = PartialContentBody {
				file: self.file,
				offset: range.0,
				len: content_len,
			};
			res.status = Some(Status::PartialContent);
			res.body = Some(Box::new(partial_content));
		} else {
			if let Some(file_length) = file_length {
				res.headers.set(ContentRange(ContentRangeSpec::Bytes {
					range: None,
					instance_length: Some(file_length),
				}));
			};
			res.status = Some(Status::RangeNotSatisfiable);
		}
	}
}

struct PartialContentBody {
	pub file: File,
	pub offset: u64,
	pub len: u64,
}

impl WriteBody for PartialContentBody {
	fn write_body(&mut self, res: &mut Write) -> io::Result<()> {
		self.file.seek(SeekFrom::Start(self.offset))?;
		let mut limiter = <File as Read>::by_ref(&mut self.file).take(self.len);
		io::copy(&mut limiter, res).map(|_| ())
	}
}

pub struct RangeResponder<R> {
	original: R,
}

impl<'r, R: Responder<'r>> RangeResponder<R> {
	pub fn new(original: R) -> RangeResponder<R> {
		RangeResponder{ original }
	}

	fn ignore_range(self, request: &rocket::request::Request) -> response::Result<'r> {
		let mut response = self.original.respond_to(request)?;
		response.set_status(rocket::http::Status::RangeNotSatisfiable);
		Ok(response)
	}
}

fn truncate_range(range: &PartialFileRange, file_length: &Option<u64>) -> Option<(u64, u64)> {
	use self::PartialFileRange::*;

	match (range, file_length) {
		(FromTo(from, to), Some(file_length)) => {
			if from <= to && from < file_length {
				Some((*from, cmp::min(*to, file_length - 1)))
			} else {
				None
			}
		}
		(AllFrom(from), Some(file_length)) => {
			if from < file_length {
				Some((*from, file_length - 1))
			} else {
				None
			}
		}
		(Last(last), Some(file_length)) => {
			if last < file_length {
				Some((file_length - last, file_length - 1))
			} else {
				Some((0, file_length - 1))
			}
		}
		(_, None) => None,
	}
}

impl<'r> Responder<'r> for RangeResponder<File> {

	fn respond_to(mut self, request: &rocket::request::Request) -> response::Result<'r> {

		use rocket::http::hyper::header::*;

		let range_header = request.headers().get_one("Range");
		let range_header = match range_header {
			None => return Ok(self.original.respond_to(request)?),
			Some(h) => h,
		};

		let vec_range = match Range::from_str(range_header) {
			Ok(Range::Bytes(v)) => v,
			_ => return self.ignore_range(request),
		};

		let partial_file_range = match vec_range.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		};

		let metadata: Option<_> = self.original.metadata().ok();
		let file_length: Option<u64> = metadata.map(|m| m.len());
		let range: Option<(u64, u64)> = truncate_range(&partial_file_range, &file_length);

		if let Some((from, to)) = range {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: range,
				instance_length: file_length,
			});
			let content_len = to - from + 1;

			match self.original.seek(SeekFrom::Start(from)) {
				Ok(_) => (),
				Err(_) => return Err(rocket::http::Status::InternalServerError),
			}
			let partial_original = self.original.take(content_len).into_inner();
			let mut response = partial_original.respond_to(request)?;
			response.set_header(ContentLength(content_len));
			response.set_header(content_range);
			response.set_status(rocket::http::Status::PartialContent);

			Ok(response)
		} else {
			self.ignore_range(request)
		}
    }
}
<commit_msg>Formatting<commit_after>use iron::headers::{
	AcceptRanges, ByteRangeSpec, ContentLength, ContentRange, ContentRangeSpec, Range, RangeUnit,
};
use iron::modifier::Modifier;
use iron::modifiers::Header;
use iron::prelude::*;
use iron::response::WriteBody;
use iron::status::{self, Status};
use rocket;
use rocket::response::{self, Responder};
use std::cmp;
use std::fs::{self, File};
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::path::Path;
use std::str::FromStr;

use errors::{Error, ErrorKind};

pub fn deliver(path: &Path, range_header: Option<&Range>) -> IronResult<Response> {
	match fs::metadata(path) {
		Ok(meta) => meta,
		Err(e) => {
			let status = match e.kind() {
				io::ErrorKind::NotFound => status::NotFound,
				io::ErrorKind::PermissionDenied => status::Forbidden,
				_ => status::InternalServerError,
			};
			return Err(IronError::new(e, status));
		}
	};

	let accept_range_header = Header(AcceptRanges(vec![RangeUnit::Bytes]));
	let range_header = range_header.cloned();

	match range_header {
		None => Ok(Response::with((status::Ok, path, accept_range_header))),
		Some(range) => match range {
			Range::Bytes(vec_range) => {
				if let Ok(partial_file) = PartialFile::from_path(path, vec_range) {
					Ok(Response::with((
						status::Ok,
						partial_file,
						accept_range_header,
					)))
				} else {
					Err(Error::from(ErrorKind::FileNotFound).into())
				}
			}
			_ => Ok(Response::with(status::RangeNotSatisfiable)),
		},
	}
}

pub enum PartialFileRange {
	AllFrom(u64),
	FromTo(u64, u64),
	Last(u64),
}

impl From<ByteRangeSpec> for PartialFileRange {
	fn from(b: ByteRangeSpec) -> PartialFileRange {
		match b {
			ByteRangeSpec::AllFrom(from) => PartialFileRange::AllFrom(from),
			ByteRangeSpec::FromTo(from, to) => PartialFileRange::FromTo(from, to),
			ByteRangeSpec::Last(last) => PartialFileRange::Last(last),
		}
	}
}

pub struct PartialFile {
	file: File,
	range: PartialFileRange,
}

impl From<Vec<ByteRangeSpec>> for PartialFileRange {
	fn from(v: Vec<ByteRangeSpec>) -> PartialFileRange {
		match v.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		}
	}
}

impl PartialFile {
	pub fn new<Range>(file: File, range: Range) -> PartialFile
	where
		Range: Into<PartialFileRange>,
	{
		let range = range.into();
		PartialFile { file, range }
	}

	pub fn from_path<P: AsRef<Path>, Range>(path: P, range: Range) -> Result<PartialFile, io::Error>
	where
		Range: Into<PartialFileRange>,
	{
		let file = File::open(path.as_ref())?;
		Ok(Self::new(file, range))
	}
}

impl Modifier<Response> for PartialFile {
	fn modify(self, res: &mut Response) {
		let metadata: Option<_> = self.file.metadata().ok();
		let file_length: Option<u64> = metadata.map(|m| m.len());
		let range: Option<(u64, u64)> = truncate_range(&self.range, &file_length);

		if let Some(range) = range {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: Some(range),
				instance_length: file_length,
			});
			let content_len = range.1 - range.0 + 1;
			res.headers.set(ContentLength(content_len));
			res.headers.set(content_range);
			let partial_content = PartialContentBody {
				file: self.file,
				offset: range.0,
				len: content_len,
			};
			res.status = Some(Status::PartialContent);
			res.body = Some(Box::new(partial_content));
		} else {
			if let Some(file_length) = file_length {
				res.headers.set(ContentRange(ContentRangeSpec::Bytes {
					range: None,
					instance_length: Some(file_length),
				}));
			};
			res.status = Some(Status::RangeNotSatisfiable);
		}
	}
}

struct PartialContentBody {
	pub file: File,
	pub offset: u64,
	pub len: u64,
}

impl WriteBody for PartialContentBody {
	fn write_body(&mut self, res: &mut Write) -> io::Result<()> {
		self.file.seek(SeekFrom::Start(self.offset))?;
		let mut limiter = <File as Read>::by_ref(&mut self.file).take(self.len);
		io::copy(&mut limiter, res).map(|_| ())
	}
}

pub struct RangeResponder<R> {
	original: R,
}

impl<'r, R: Responder<'r>> RangeResponder<R> {
	pub fn new(original: R) -> RangeResponder<R> {
		RangeResponder { original }
	}

	fn ignore_range(self, request: &rocket::request::Request) -> response::Result<'r> {
		let mut response = self.original.respond_to(request)?;
		response.set_status(rocket::http::Status::RangeNotSatisfiable);
		Ok(response)
	}
}

fn truncate_range(range: &PartialFileRange, file_length: &Option<u64>) -> Option<(u64, u64)> {
	use self::PartialFileRange::*;

	match (range, file_length) {
		(FromTo(from, to), Some(file_length)) => {
			if from <= to && from < file_length {
				Some((*from, cmp::min(*to, file_length - 1)))
			} else {
				None
			}
		}
		(AllFrom(from), Some(file_length)) => {
			if from < file_length {
				Some((*from, file_length - 1))
			} else {
				None
			}
		}
		(Last(last), Some(file_length)) => {
			if last < file_length {
				Some((file_length - last, file_length - 1))
			} else {
				Some((0, file_length - 1))
			}
		}
		(_, None) => None,
	}
}

impl<'r> Responder<'r> for RangeResponder<File> {
	fn respond_to(mut self, request: &rocket::request::Request) -> response::Result<'r> {
		use rocket::http::hyper::header::*;

		let range_header = request.headers().get_one("Range");
		let range_header = match range_header {
			None => return Ok(self.original.respond_to(request)?),
			Some(h) => h,
		};

		let vec_range = match Range::from_str(range_header) {
			Ok(Range::Bytes(v)) => v,
			_ => return self.ignore_range(request),
		};

		let partial_file_range = match vec_range.into_iter().next() {
			None => PartialFileRange::AllFrom(0),
			Some(byte_range) => PartialFileRange::from(byte_range),
		};

		let metadata: Option<_> = self.original.metadata().ok();
		let file_length: Option<u64> = metadata.map(|m| m.len());
		let range: Option<(u64, u64)> = truncate_range(&partial_file_range, &file_length);

		if let Some((from, to)) = range {
			let content_range = ContentRange(ContentRangeSpec::Bytes {
				range: range,
				instance_length: file_length,
			});
			let content_len = to - from + 1;

			match self.original.seek(SeekFrom::Start(from)) {
				Ok(_) => (),
				Err(_) => return Err(rocket::http::Status::InternalServerError),
			}
			let partial_original = self.original.take(content_len).into_inner();
			let mut response = partial_original.respond_to(request)?;
			response.set_header(ContentLength(content_len));
			response.set_header(content_range);
			response.set_status(rocket::http::Status::PartialContent);

			Ok(response)
		} else {
			self.ignore_range(request)
		}
	}
}
<|endoftext|>


<commit_before>

use folder::Folder;
use album::Album;
use version::Version;
use master::Master;
use ::AplibObject;

pub enum Wrapper {
    Album(Box<Album>),
    Folder(Box<Folder>),
    Master(Box<Master>),
    Version(Box<Version>),
    None
}

impl Wrapper {
    pub fn uuid(&self) -> Option<&String> {
        return match *self {
            Wrapper::Album(ref o) => {
                Some(o.uuid())
            },
            Wrapper::Folder(ref o) => {
                Some(o.uuid())
            },
            Wrapper::Version(ref o) => {
                Some(o.uuid())
            },
            Wrapper::Master(ref o) => {
                Some(o.uuid())
            },
            Wrapper::None => Option::None
        };
    }
}
<commit_msg>Missing license.<commit_after>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use folder::Folder;
use album::Album;
use version::Version;
use master::Master;
use ::AplibObject;

pub enum Wrapper {
    Album(Box<Album>),
    Folder(Box<Folder>),
    Master(Box<Master>),
    Version(Box<Version>),
    None
}

impl Wrapper {
    pub fn uuid(&self) -> Option<&String> {
        return match *self {
            Wrapper::Album(ref o) => {
                Some(o.uuid())
            },
            Wrapper::Folder(ref o) => {
                Some(o.uuid())
            },
            Wrapper::Version(ref o) => {
                Some(o.uuid())
            },
            Wrapper::Master(ref o) => {
                Some(o.uuid())
            },
            Wrapper::None => Option::None
        };
    }
}
<|endoftext|>


<commit_before>use yansi::{Color, Style};

pub(crate) struct VisibilityTheme {
    pub pub_crate: Style,
    pub pub_module: Style,
    pub pub_private: Style,
    pub pub_public: Style,
    pub pub_super: Style,
}

pub(crate) struct Theme {
    pub name: Style,
    pub visibility: VisibilityTheme,
    pub cfg: Style,
    pub orphan: Style,
}

// GREEN:  Color::RGB(129, 193, 105)
// YELLOW: Color::RGB(248, 192,  76)
// ORANGE: Color::RGB(254, 148,  84)
// RED:    Color::RGB(219,  83, 103)
// PURPLE: Color::RGB(186, 111, 167)
// BLUE:   Color::RGB( 83, 151, 200)
pub(crate) fn theme() -> Theme {
    Theme {
        name: Style::default(),
        visibility: VisibilityTheme {
            pub_crate: Style::new(Color::RGB(248, 192, 76)), // YELLOW TEXT
            pub_module: Style::new(Color::RGB(254, 148, 84)), // ORANGE TEXT
            pub_private: Style::new(Color::RGB(219, 83, 103)), // RED TEXT
            pub_public: Style::new(Color::RGB(129, 193, 105)), // GREEN TEXT
            pub_super: Style::new(Color::RGB(254, 148, 84)), // ORANGE TEXT
        },
        cfg: Style::new(Color::RGB(83, 151, 200)), // BLUE TEXT
        orphan: Style::new(Color::RGB(186, 111, 167)), // orphan: Style::new(Color::RGB(0, 0, 0)).bg(Color::RGB(219, 83, 103)), // RED BACKGROUND

                                                       // Style::default().dimmed().bg(Color::RGB(219, 83, 103)), // RED BACKGROUND
    }
}
<commit_msg>Extended color/theme support<commit_after>pub use yansi::Style;

#[derive(Copy, Clone, Debug)]
pub(crate) struct Rgb {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}

impl From<Rgb> for yansi::Color {
    fn from(rgba: Rgb) -> Self {
        yansi::Color::RGB(rgba.r, rgba.g, rgba.b)
    }
}

#[derive(Clone, Debug)]
pub(crate) struct ColorPalette {
    pub purple: Rgb,
    pub red: Rgb,
    pub orange: Rgb,
    pub yellow: Rgb,
    pub green: Rgb,
    pub cyan: Rgb,
    pub blue: Rgb,
}

pub(crate) fn color_palette() -> ColorPalette {
    ColorPalette {
        purple: Rgb {
            r: 186,
            g: 111,
            b: 167,
        },
        red: Rgb {
            r: 219,
            g: 83,
            b: 103,
        },
        orange: Rgb {
            r: 254,
            g: 148,
            b: 84,
        },
        yellow: Rgb {
            r: 248,
            g: 192,
            b: 76,
        },
        green: Rgb {
            r: 129,
            g: 193,
            b: 105,
        },
        cyan: Rgb {
            r: 105,
            g: 190,
            b: 210,
        },
        blue: Rgb {
            r: 83,
            g: 151,
            b: 200,
        },
    }
}

#[derive(Clone, Debug)]
pub(crate) struct VisibilityColors {
    pub pub_crate: Rgb,
    pub pub_module: Rgb,
    pub pub_private: Rgb,
    pub pub_global: Rgb,
    pub pub_super: Rgb,
}

#[derive(Clone, Debug)]
pub(crate) struct Colors {
    pub kind: Rgb,

    pub visibility: VisibilityColors,
    pub cfg: Rgb,
    pub orphan: Rgb,
}

pub(crate) fn colors() -> Colors {
    let color_palette = color_palette();

    Colors {
        kind: color_palette.blue,
        visibility: VisibilityColors {
            pub_crate: color_palette.yellow,
            pub_module: color_palette.orange,
            pub_private: color_palette.red,
            pub_global: color_palette.green,
            pub_super: color_palette.orange,
        },
        cfg: color_palette.cyan,
        orphan: color_palette.purple,
    }
}

#[derive(Clone, Debug)]
pub(crate) struct VisibilityStyles {
    pub pub_crate: Style,
    pub pub_module: Style,
    pub pub_private: Style,
    pub pub_global: Style,
    pub pub_super: Style,
}

#[derive(Clone, Debug)]
pub(crate) struct Styles {
    pub kind: Style,
    pub name: Style,

    pub visibility: VisibilityStyles,
    pub cfg: Style,
    pub orphan: Style,
}

pub(crate) fn styles() -> Styles {
    let colors = colors();
    Styles {
        kind: Style::new(colors.kind.into()),
        name: Style::default(),
        visibility: VisibilityStyles {
            pub_crate: Style::new(colors.visibility.pub_crate.into()),
            pub_module: Style::new(colors.visibility.pub_module.into()),
            pub_private: Style::new(colors.visibility.pub_private.into()),
            pub_global: Style::new(colors.visibility.pub_global.into()),
            pub_super: Style::new(colors.visibility.pub_super.into()),
        },
        cfg: Style::new(colors.cfg.into()),
        orphan: Style::new(colors.orphan.into()),
    }
}
<|endoftext|>