<commit_before>extern crate pancurses;

use self::super::find_closest;
use backend;
use event::{Event, Key};
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use theme::{Color, ColorStyle, ColorPair, Effect};
use utf8;

pub struct Concrete {
    current_style: Cell<ColorPair>,
    pairs: RefCell<HashMap<ColorPair, i32>>,
    window: pancurses::Window,
}

impl Concrete {
    /// Save a new color pair.
    fn insert_color(&self, pairs: &mut HashMap<ColorPair, i32>,
                    pair: ColorPair)
                    -> i32 {

        let n = 1 + pairs.len() as i32;

        // TODO: when COLORS_PAIRS is available...
        let target = if 16 > n {
            // We still have plenty of space for everyone.
            n
        } else {
            // The world is too small for both of us.
            let target = n - 1;
            // Remove the mapping to n-1
            pairs.retain(|_, &mut v| v != target);
            target
        };
        pairs.insert(pair, target);
        pancurses::init_pair(target as i16,
                             find_closest(&pair.front),
                             find_closest(&pair.back));
        target
    }

    /// Checks the pair in the cache, or re-define a color if needed.
    fn get_or_create(&self, pair: ColorPair) -> i32 {

        let mut pairs = self.pairs.borrow_mut();

        // Find if we have this color in stock
        if pairs.contains_key(&pair) {
            // We got it!
            pairs[&pair]
        } else {
            self.insert_color(&mut *pairs, pair)
        }
    }

    fn set_colors(&self, pair: ColorPair) {

        let i = self.get_or_create(pair);

        self.current_style.set(pair);
        let style = pancurses::COLOR_PAIR(i as u32);
        self.window.attron(style);
    }
}

impl backend::Backend for Concrete {
    fn init() -> Self {
        ::std::env::set_var("ESCDELAY", "25");
        let window = pancurses::initscr();
        window.keypad(true);
        pancurses::noecho();
        pancurses::cbreak();
        pancurses::start_color();
        pancurses::curs_set(0);

        Concrete {
            current_style: Cell::new(ColorPair::from_256colors(0, 0)),
            pairs: RefCell::new(HashMap::new()),
            window: window,
        }
    }

    fn screen_size(&self) -> (usize, usize) {
        let (y, x) = self.window.get_max_yx();
        (x as usize, y as usize)
    }

    fn has_colors(&self) -> bool {
        pancurses::has_colors()
    }

    fn finish(&mut self) {
        pancurses::endwin();
    }

    fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) {
        let current = self.current_style.get();

        if current != colors {
            self.set_colors(colors);
        }

        f();

        if current != colors {
            self.set_colors(current);
        }
    }

    fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
        let style = match effect {
            Effect::Reverse => pancurses::Attribute::Reverse,
            Effect::Simple => pancurses::Attribute::Normal,
        };
        self.window.attron(style);
        f();
        self.window.attroff(style);
    }

    fn clear(&self, color: Color) {
        let id = self.get_or_create(ColorPair {
                                        front: color,
                                        back: color,
                                    });
        self.window.bkgd(pancurses::ColorPair(id as u8));
        self.window.clear();
    }

    fn refresh(&mut self) {
        self.window.refresh();
    }

    fn print_at(&self, (x, y): (usize, usize), text: &str) {
        self.window.mvaddstr(y as i32, x as i32, text);
    }

    fn poll_event(&self) -> Event {
        // TODO: there seems to not be any indication
        // of Ctrl/Alt/Shift in these :v
        if let Some(ev) = self.window.getch() {
            match ev {
                pancurses::Input::Character('\n') => Event::Key(Key::Enter),
                // TODO: wait for a very short delay. If more keys are
                // pipelined, it may be an escape sequence.
                pancurses::Input::Character('\u{7f}') |
                pancurses::Input::Character('\u{8}') => {
                    Event::Key(Key::Backspace)
                }
                pancurses::Input::Character('\u{9}') => Event::Key(Key::Tab),
                pancurses::Input::Character('\u{1b}') => Event::Key(Key::Esc),
                pancurses::Input::Character(c) if 32 <= (c as u32) &&
                                                  (c as u32) <= 255 => {
                    Event::Char(utf8::read_char(c as u8, || {
                        self.window
                            .getch()
                            .and_then(|i| match i {
                                          pancurses::Input::Character(c) => {
                                              Some(c as u8)
                                          }
                                          _ => None,
                                      })
                    })
                                        .unwrap())
                }
                pancurses::Input::Character(c) => {
                    let mut bytes = [0u8; 4];
                    Event::Unknown(c.encode_utf8(&mut bytes)
                                       .as_bytes()
                                       .to_vec())
                }
                // TODO: Some key combos are not recognized by pancurses,
                // but are sent as Unknown. We could still parse them here.
                pancurses::Input::Unknown(other) => {
                    Event::Unknown((0..4)
                                       .map(|i| {
                                                ((other >> (8 * i)) & 0xFF) as
                                                u8
                                            })
                                       .collect())
                }
                // TODO: I honestly have no fucking idea what KeyCodeYes is
                pancurses::Input::KeyCodeYes => Event::Refresh,
                pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
                pancurses::Input::KeyDown => Event::Key(Key::Down),
                pancurses::Input::KeyUp => Event::Key(Key::Up),
                pancurses::Input::KeyLeft => Event::Key(Key::Left),
                pancurses::Input::KeyRight => Event::Key(Key::Right),
                pancurses::Input::KeyHome => Event::Key(Key::Home),
                pancurses::Input::KeyBackspace => Event::Key(Key::Backspace),
                pancurses::Input::KeyF0 => Event::Key(Key::F0),
                pancurses::Input::KeyF1 => Event::Key(Key::F1),
                pancurses::Input::KeyF2 => Event::Key(Key::F2),
                pancurses::Input::KeyF3 => Event::Key(Key::F3),
                pancurses::Input::KeyF4 => Event::Key(Key::F4),
                pancurses::Input::KeyF5 => Event::Key(Key::F5),
                pancurses::Input::KeyF6 => Event::Key(Key::F6),
                pancurses::Input::KeyF7 => Event::Key(Key::F7),
                pancurses::Input::KeyF8 => Event::Key(Key::F8),
                pancurses::Input::KeyF9 => Event::Key(Key::F9),
                pancurses::Input::KeyF10 => Event::Key(Key::F10),
                pancurses::Input::KeyF11 => Event::Key(Key::F11),
                pancurses::Input::KeyF12 => Event::Key(Key::F12),
                pancurses::Input::KeyF13 => Event::Shift(Key::F1),
                pancurses::Input::KeyF14 => Event::Shift(Key::F2),
                pancurses::Input::KeyF15 => Event::Shift(Key::F3),
                pancurses::Input::KeyDL => Event::Refresh,
                pancurses::Input::KeyIL => Event::Refresh,
                pancurses::Input::KeyDC => Event::Key(Key::Del),
                pancurses::Input::KeyIC => Event::Key(Key::Ins),
                pancurses::Input::KeyEIC => Event::Refresh,
                pancurses::Input::KeyClear => Event::Refresh,
                pancurses::Input::KeyEOS => Event::Refresh,
                pancurses::Input::KeyEOL => Event::Refresh,
                pancurses::Input::KeySF => Event::Shift(Key::Down),
                pancurses::Input::KeySR => Event::Shift(Key::Up),
                pancurses::Input::KeyNPage => Event::Key(Key::PageDown),
                pancurses::Input::KeyPPage => Event::Key(Key::PageUp),
                pancurses::Input::KeySTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyCTab => Event::Ctrl(Key::Tab),
                pancurses::Input::KeyCATab => Event::CtrlAlt(Key::Tab),
                pancurses::Input::KeyEnter => Event::Key(Key::Enter),
                pancurses::Input::KeySReset => Event::Refresh,
                pancurses::Input::KeyReset => Event::Refresh,
                pancurses::Input::KeyPrint => Event::Refresh,
                pancurses::Input::KeyLL => Event::Refresh,
                pancurses::Input::KeyAbort => Event::Refresh,
                pancurses::Input::KeySHelp => Event::Refresh,
                pancurses::Input::KeyLHelp => Event::Refresh,
                pancurses::Input::KeyBTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyBeg => Event::Refresh,
                pancurses::Input::KeyCancel => Event::Refresh,
                pancurses::Input::KeyClose => Event::Refresh,
                pancurses::Input::KeyCommand => Event::Refresh,
                pancurses::Input::KeyCopy => Event::Refresh,
                pancurses::Input::KeyCreate => Event::Refresh,
                pancurses::Input::KeyEnd => Event::Key(Key::End),
                pancurses::Input::KeyExit => Event::Refresh,
                pancurses::Input::KeyFind => Event::Refresh,
                pancurses::Input::KeyHelp => Event::Refresh,
                pancurses::Input::KeyMark => Event::Refresh,
                pancurses::Input::KeyMessage => Event::Refresh,
                pancurses::Input::KeyMove => Event::Refresh,
                pancurses::Input::KeyNext => Event::Refresh,
                pancurses::Input::KeyOpen => Event::Refresh,
                pancurses::Input::KeyOptions => Event::Refresh,
                pancurses::Input::KeyPrevious => Event::Refresh,
                pancurses::Input::KeyRedo => Event::Refresh,
                pancurses::Input::KeyReference => Event::Refresh,
                pancurses::Input::KeyRefresh => Event::Refresh,
                pancurses::Input::KeyReplace => Event::Refresh,
                pancurses::Input::KeyRestart => Event::Refresh,
                pancurses::Input::KeyResume => Event::Refresh,
                pancurses::Input::KeySave => Event::Refresh,
                pancurses::Input::KeySBeg => Event::Refresh,
                pancurses::Input::KeySCancel => Event::Refresh,
                pancurses::Input::KeySCommand => Event::Refresh,
                pancurses::Input::KeySCopy => Event::Refresh,
                pancurses::Input::KeySCreate => Event::Refresh,
                pancurses::Input::KeySDC => Event::Shift(Key::Del),
                pancurses::Input::KeySDL => Event::Refresh,
                pancurses::Input::KeySelect => Event::Refresh,
                pancurses::Input::KeySEnd => Event::Shift(Key::End),
                pancurses::Input::KeySEOL => Event::Refresh,
                pancurses::Input::KeySExit => Event::Refresh,
                pancurses::Input::KeySFind => Event::Refresh,
                pancurses::Input::KeySHome => Event::Shift(Key::Home),
                pancurses::Input::KeySIC => Event::Shift(Key::Ins),
                pancurses::Input::KeySLeft => Event::Shift(Key::Left),
                pancurses::Input::KeySMessage => Event::Refresh,
                pancurses::Input::KeySMove => Event::Refresh,
                pancurses::Input::KeySNext => Event::Shift(Key::PageDown),
                pancurses::Input::KeySOptions => Event::Refresh,
                pancurses::Input::KeySPrevious => Event::Shift(Key::PageUp),
                pancurses::Input::KeySPrint => Event::Refresh,
                pancurses::Input::KeySRedo => Event::Refresh,
                pancurses::Input::KeySReplace => Event::Refresh,
                pancurses::Input::KeySRight => Event::Shift(Key::Right),
                pancurses::Input::KeySResume => Event::Refresh,
                pancurses::Input::KeySSave => Event::Refresh,
                pancurses::Input::KeySSuspend => Event::Refresh,
                pancurses::Input::KeySUndo => Event::Refresh,
                pancurses::Input::KeySuspend => Event::Refresh,
                pancurses::Input::KeyUndo => Event::Refresh,
                pancurses::Input::KeyResize => Event::WindowResize,
                pancurses::Input::KeyEvent => Event::Refresh,
                // TODO: mouse support
                pancurses::Input::KeyMouse => Event::Refresh,
                pancurses::Input::KeyA1 => Event::Refresh,
                pancurses::Input::KeyA3 => Event::Refresh,
                pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
                pancurses::Input::KeyC1 => Event::Refresh,
                pancurses::Input::KeyC3 => Event::Refresh,
            }
        } else {
            Event::Refresh
        }
    }

    fn set_refresh_rate(&mut self, fps: u32) {
        if fps == 0 {
            self.window.timeout(-1);
        } else {
            self.window.timeout(1000 / fps as i32);
        }
    }
}
<commit_msg>Use pancurses::chtype directly<commit_after>extern crate pancurses;

use self::super::find_closest;
use backend;
use event::{Event, Key};
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use theme::{Color, ColorPair, Effect};
use utf8;

pub struct Concrete {
    current_style: Cell<ColorPair>,
    pairs: RefCell<HashMap<ColorPair, i32>>,
    window: pancurses::Window,
}

impl Concrete {
    /// Save a new color pair.
    fn insert_color(&self, pairs: &mut HashMap<ColorPair, i32>,
                    pair: ColorPair)
                    -> i32 {

        let n = 1 + pairs.len() as i32;

        // TODO: when COLORS_PAIRS is available...
        let target = if 16 > n {
            // We still have plenty of space for everyone.
            n
        } else {
            // The world is too small for both of us.
            let target = n - 1;
            // Remove the mapping to n-1
            pairs.retain(|_, &mut v| v != target);
            target
        };
        pairs.insert(pair, target);
        pancurses::init_pair(target as i16,
                             find_closest(&pair.front),
                             find_closest(&pair.back));
        target
    }

    /// Checks the pair in the cache, or re-define a color if needed.
    fn get_or_create(&self, pair: ColorPair) -> i32 {

        let mut pairs = self.pairs.borrow_mut();

        // Find if we have this color in stock
        if pairs.contains_key(&pair) {
            // We got it!
            pairs[&pair]
        } else {
            self.insert_color(&mut *pairs, pair)
        }
    }

    fn set_colors(&self, pair: ColorPair) {

        let i = self.get_or_create(pair);

        self.current_style.set(pair);
        let style = pancurses::COLOR_PAIR(i as pancurses::chtype);
        self.window.attron(style);
    }
}

impl backend::Backend for Concrete {
    fn init() -> Self {
        ::std::env::set_var("ESCDELAY", "25");
        let window = pancurses::initscr();
        window.keypad(true);
        pancurses::noecho();
        pancurses::cbreak();
        pancurses::start_color();
        pancurses::curs_set(0);

        Concrete {
            current_style: Cell::new(ColorPair::from_256colors(0, 0)),
            pairs: RefCell::new(HashMap::new()),
            window: window,
        }
    }

    fn screen_size(&self) -> (usize, usize) {
        let (y, x) = self.window.get_max_yx();
        (x as usize, y as usize)
    }

    fn has_colors(&self) -> bool {
        pancurses::has_colors()
    }

    fn finish(&mut self) {
        pancurses::endwin();
    }

    fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) {
        let current = self.current_style.get();

        if current != colors {
            self.set_colors(colors);
        }

        f();

        if current != colors {
            self.set_colors(current);
        }
    }

    fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
        let style = match effect {
            Effect::Reverse => pancurses::Attribute::Reverse,
            Effect::Simple => pancurses::Attribute::Normal,
        };
        self.window.attron(style);
        f();
        self.window.attroff(style);
    }

    fn clear(&self, color: Color) {
        let id = self.get_or_create(ColorPair {
                                        front: color,
                                        back: color,
                                    });
        self.window.bkgd(pancurses::ColorPair(id as u8));
        self.window.clear();
    }

    fn refresh(&mut self) {
        self.window.refresh();
    }

    fn print_at(&self, (x, y): (usize, usize), text: &str) {
        self.window.mvaddstr(y as i32, x as i32, text);
    }

    fn poll_event(&self) -> Event {
        // TODO: there seems to not be any indication
        // of Ctrl/Alt/Shift in these :v
        if let Some(ev) = self.window.getch() {
            match ev {
                pancurses::Input::Character('\n') => Event::Key(Key::Enter),
                // TODO: wait for a very short delay. If more keys are
                // pipelined, it may be an escape sequence.
                pancurses::Input::Character('\u{7f}') |
                pancurses::Input::Character('\u{8}') => {
                    Event::Key(Key::Backspace)
                }
                pancurses::Input::Character('\u{9}') => Event::Key(Key::Tab),
                pancurses::Input::Character('\u{1b}') => Event::Key(Key::Esc),
                pancurses::Input::Character(c) if 32 <= (c as u32) &&
                                                  (c as u32) <= 255 => {
                    Event::Char(utf8::read_char(c as u8, || {
                        self.window
                            .getch()
                            .and_then(|i| match i {
                                          pancurses::Input::Character(c) => {
                                              Some(c as u8)
                                          }
                                          _ => None,
                                      })
                    })
                                        .unwrap())
                }
                pancurses::Input::Character(c) => {
                    let mut bytes = [0u8; 4];
                    Event::Unknown(c.encode_utf8(&mut bytes)
                                       .as_bytes()
                                       .to_vec())
                }
                // TODO: Some key combos are not recognized by pancurses,
                // but are sent as Unknown. We could still parse them here.
                pancurses::Input::Unknown(other) => {
                    Event::Unknown((0..4)
                                       .map(|i| {
                                                ((other >> (8 * i)) & 0xFF) as
                                                u8
                                            })
                                       .collect())
                }
                // TODO: I honestly have no fucking idea what KeyCodeYes is
                pancurses::Input::KeyCodeYes => Event::Refresh,
                pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
                pancurses::Input::KeyDown => Event::Key(Key::Down),
                pancurses::Input::KeyUp => Event::Key(Key::Up),
                pancurses::Input::KeyLeft => Event::Key(Key::Left),
                pancurses::Input::KeyRight => Event::Key(Key::Right),
                pancurses::Input::KeyHome => Event::Key(Key::Home),
                pancurses::Input::KeyBackspace => Event::Key(Key::Backspace),
                pancurses::Input::KeyF0 => Event::Key(Key::F0),
                pancurses::Input::KeyF1 => Event::Key(Key::F1),
                pancurses::Input::KeyF2 => Event::Key(Key::F2),
                pancurses::Input::KeyF3 => Event::Key(Key::F3),
                pancurses::Input::KeyF4 => Event::Key(Key::F4),
                pancurses::Input::KeyF5 => Event::Key(Key::F5),
                pancurses::Input::KeyF6 => Event::Key(Key::F6),
                pancurses::Input::KeyF7 => Event::Key(Key::F7),
                pancurses::Input::KeyF8 => Event::Key(Key::F8),
                pancurses::Input::KeyF9 => Event::Key(Key::F9),
                pancurses::Input::KeyF10 => Event::Key(Key::F10),
                pancurses::Input::KeyF11 => Event::Key(Key::F11),
                pancurses::Input::KeyF12 => Event::Key(Key::F12),
                pancurses::Input::KeyF13 => Event::Shift(Key::F1),
                pancurses::Input::KeyF14 => Event::Shift(Key::F2),
                pancurses::Input::KeyF15 => Event::Shift(Key::F3),
                pancurses::Input::KeyDL => Event::Refresh,
                pancurses::Input::KeyIL => Event::Refresh,
                pancurses::Input::KeyDC => Event::Key(Key::Del),
                pancurses::Input::KeyIC => Event::Key(Key::Ins),
                pancurses::Input::KeyEIC => Event::Refresh,
                pancurses::Input::KeyClear => Event::Refresh,
                pancurses::Input::KeyEOS => Event::Refresh,
                pancurses::Input::KeyEOL => Event::Refresh,
                pancurses::Input::KeySF => Event::Shift(Key::Down),
                pancurses::Input::KeySR => Event::Shift(Key::Up),
                pancurses::Input::KeyNPage => Event::Key(Key::PageDown),
                pancurses::Input::KeyPPage => Event::Key(Key::PageUp),
                pancurses::Input::KeySTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyCTab => Event::Ctrl(Key::Tab),
                pancurses::Input::KeyCATab => Event::CtrlAlt(Key::Tab),
                pancurses::Input::KeyEnter => Event::Key(Key::Enter),
                pancurses::Input::KeySReset => Event::Refresh,
                pancurses::Input::KeyReset => Event::Refresh,
                pancurses::Input::KeyPrint => Event::Refresh,
                pancurses::Input::KeyLL => Event::Refresh,
                pancurses::Input::KeyAbort => Event::Refresh,
                pancurses::Input::KeySHelp => Event::Refresh,
                pancurses::Input::KeyLHelp => Event::Refresh,
                pancurses::Input::KeyBTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyBeg => Event::Refresh,
                pancurses::Input::KeyCancel => Event::Refresh,
                pancurses::Input::KeyClose => Event::Refresh,
                pancurses::Input::KeyCommand => Event::Refresh,
                pancurses::Input::KeyCopy => Event::Refresh,
                pancurses::Input::KeyCreate => Event::Refresh,
                pancurses::Input::KeyEnd => Event::Key(Key::End),
                pancurses::Input::KeyExit => Event::Refresh,
                pancurses::Input::KeyFind => Event::Refresh,
                pancurses::Input::KeyHelp => Event::Refresh,
                pancurses::Input::KeyMark => Event::Refresh,
                pancurses::Input::KeyMessage => Event::Refresh,
                pancurses::Input::KeyMove => Event::Refresh,
                pancurses::Input::KeyNext => Event::Refresh,
                pancurses::Input::KeyOpen => Event::Refresh,
                pancurses::Input::KeyOptions => Event::Refresh,
                pancurses::Input::KeyPrevious => Event::Refresh,
                pancurses::Input::KeyRedo => Event::Refresh,
                pancurses::Input::KeyReference => Event::Refresh,
                pancurses::Input::KeyRefresh => Event::Refresh,
                pancurses::Input::KeyReplace => Event::Refresh,
                pancurses::Input::KeyRestart => Event::Refresh,
                pancurses::Input::KeyResume => Event::Refresh,
                pancurses::Input::KeySave => Event::Refresh,
                pancurses::Input::KeySBeg => Event::Refresh,
                pancurses::Input::KeySCancel => Event::Refresh,
                pancurses::Input::KeySCommand => Event::Refresh,
                pancurses::Input::KeySCopy => Event::Refresh,
                pancurses::Input::KeySCreate => Event::Refresh,
                pancurses::Input::KeySDC => Event::Shift(Key::Del),
                pancurses::Input::KeySDL => Event::Refresh,
                pancurses::Input::KeySelect => Event::Refresh,
                pancurses::Input::KeySEnd => Event::Shift(Key::End),
                pancurses::Input::KeySEOL => Event::Refresh,
                pancurses::Input::KeySExit => Event::Refresh,
                pancurses::Input::KeySFind => Event::Refresh,
                pancurses::Input::KeySHome => Event::Shift(Key::Home),
                pancurses::Input::KeySIC => Event::Shift(Key::Ins),
                pancurses::Input::KeySLeft => Event::Shift(Key::Left),
                pancurses::Input::KeySMessage => Event::Refresh,
                pancurses::Input::KeySMove => Event::Refresh,
                pancurses::Input::KeySNext => Event::Shift(Key::PageDown),
                pancurses::Input::KeySOptions => Event::Refresh,
                pancurses::Input::KeySPrevious => Event::Shift(Key::PageUp),
                pancurses::Input::KeySPrint => Event::Refresh,
                pancurses::Input::KeySRedo => Event::Refresh,
                pancurses::Input::KeySReplace => Event::Refresh,
                pancurses::Input::KeySRight => Event::Shift(Key::Right),
                pancurses::Input::KeySResume => Event::Refresh,
                pancurses::Input::KeySSave => Event::Refresh,
                pancurses::Input::KeySSuspend => Event::Refresh,
                pancurses::Input::KeySUndo => Event::Refresh,
                pancurses::Input::KeySuspend => Event::Refresh,
                pancurses::Input::KeyUndo => Event::Refresh,
                pancurses::Input::KeyResize => Event::WindowResize,
                pancurses::Input::KeyEvent => Event::Refresh,
                // TODO: mouse support
                pancurses::Input::KeyMouse => Event::Refresh,
                pancurses::Input::KeyA1 => Event::Refresh,
                pancurses::Input::KeyA3 => Event::Refresh,
                pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
                pancurses::Input::KeyC1 => Event::Refresh,
                pancurses::Input::KeyC3 => Event::Refresh,
            }
        } else {
            Event::Refresh
        }
    }

    fn set_refresh_rate(&mut self, fps: u32) {
        if fps == 0 {
            self.window.timeout(-1);
        } else {
            self.window.timeout(1000 / fps as i32);
        }
    }
}
<|endoftext|>


<commit_before>extern crate matroska;
extern crate av_format;
extern crate av_data;
#[macro_use] extern crate nom;

use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_data::timeinfo::TimeInfo;
use av_data::params::*;
use av_data::rational::Rational64;
use av_format::stream::Stream;
use av_format::buffer::{AccReader, Buffered};
use av_format::demuxer::{self, Demuxer, Event};
use av_format::demuxer::{Descr, Descriptor};
use av_format::muxer::{self};
use av_format::common::GlobalInfo;
use std::collections::VecDeque;
use std::io::{Cursor, Seek};
use std::sync::Arc;
use std::fs::File;

use matroska::ebml::{ebml_header, EBMLHeader};
use matroska::elements::{segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry,
               SegmentElement, simple_block};
use matroska::demuxer::{MkvDemuxer, MKV_DESC};
use matroska::muxer::MkvMuxer;

fn main() {
  const webm: &'static [u8] = include_bytes!("../../assets/bbb-vp9-opus.webm");
  let d = MKV_DESC.create();
  let c = Cursor::new(webm);
  let acc = AccReader::with_capacity(4096, c);
  let input = Box::new(acc);
  let mut demuxer = demuxer::Context::new(d, input);

  println!("read headers: {:?}", demuxer.read_headers().unwrap());
  println!("global info: {:#?}", demuxer.info);

  let mux = Box::new(MkvMuxer::Webm());
  //let mut output:Vec<u8> = Vec::with_capacity(24000);
  let mut output = File::create("output.webm").unwrap();

  let mut muxer = muxer::Context::new(mux, Box::new(output));
  muxer.configure().unwrap();
  muxer.set_global_info(demuxer.info.clone()).unwrap();
  muxer.write_header().unwrap();

  /*
  loop {
    match demuxer.read_event() {
      Ok(event) => {
        //println!("event: {:?}", event);
        match event {
          Event::MoreDataNeeded(sz) => panic!("we needed more data"),
          Event::NewStream(s) => panic!("new stream :{:?}", s),
          Event::NewPacket(packet) => {
            //println!("writing packet");
            muxer.write_packet(Arc::new(packet)).unwrap();
          }
        }
      },
      Err(e) => {
        println!("error: {:?}", e);
        muxer.write_trailer();
        break;
      }
    }
  }
  */
}

<commit_msg>reactivate packet writing in matroska_remux<commit_after>extern crate matroska;
extern crate av_format;
extern crate av_data;
#[macro_use] extern crate nom;

use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_data::timeinfo::TimeInfo;
use av_data::params::*;
use av_data::rational::Rational64;
use av_format::stream::Stream;
use av_format::buffer::{AccReader, Buffered};
use av_format::demuxer::{self, Demuxer, Event};
use av_format::demuxer::{Descr, Descriptor};
use av_format::muxer::{self};
use av_format::common::GlobalInfo;
use std::collections::VecDeque;
use std::io::{Cursor, Seek};
use std::sync::Arc;
use std::fs::File;

use matroska::ebml::{ebml_header, EBMLHeader};
use matroska::elements::{segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry,
               SegmentElement, simple_block};
use matroska::demuxer::{MkvDemuxer, MKV_DESC};
use matroska::muxer::MkvMuxer;

fn main() {
  //const webm: &'static [u8] = include_bytes!("../../assets/big-buck-bunny_trailer.webm");
  const webm: &'static [u8] = include_bytes!("../../assets/bbb-vp9-opus.webm");
  //const webm: &'static [u8] = include_bytes!("../../assets/single_stream.mkv");
  let d = MKV_DESC.create();
  let c = Cursor::new(webm);
  //let acc = AccReader::with_capacity(5242880, c);
  let acc = AccReader::with_capacity(20000, c);
  let input = Box::new(acc);
  let mut demuxer = demuxer::Context::new(d, input);

  println!("read headers: {:?}", demuxer.read_headers().unwrap());
  println!("global info: {:#?}", demuxer.info);

  let mux = Box::new(MkvMuxer::Webm());
  //let mut output:Vec<u8> = Vec::with_capacity(24000);
  let mut output = File::create("output.webm").unwrap();

  let mut muxer = muxer::Context::new(mux, Box::new(output));
  muxer.configure().unwrap();
  muxer.set_global_info(demuxer.info.clone()).unwrap();
  muxer.write_header().unwrap();

  loop {
    match demuxer.read_event() {
      Ok(event) => {
        //println!("event: {:?}", event);
        match event {
          Event::MoreDataNeeded(sz) => panic!("we needed more data"),
          Event::NewStream(s) => panic!("new stream :{:?}", s),
          Event::NewPacket(packet) => {
            //println!("writing packet");
            muxer.write_packet(Arc::new(packet)).unwrap();
          }
        }
      },
      Err(e) => {
        println!("error: {:?}", e);
        muxer.write_trailer();
        break;
      }
    }
  }
}

<|endoftext|>


<commit_before>use combustion::board::Board;

use std::env;
use std::process::exit;

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

    if args.len() != 2 {
        println!("Error: exactly one argument required. Exiting...");
        exit(1);
    }

    let board = Board::from_fen(&args[1]).unwrap();

    for mv in &board.legal_moves().unwrap() {
        println!("{}", mv);
    }
}
<commit_msg>work on possible moves<commit_after>use combustion::board::Board;
use combustion::moves::Move;
use combustion::piece::Color;

use std::env;
use std::process::exit;

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

    if args.len() < 2 {
        println!("Error: at least one argument required. Exiting...");
        exit(1);
    }

    let mut board = if args[1] == "startpos" {
        Board::initial()
    } else {
        Board::from_fen(&args[1]).unwrap()
    };

    let mut to_move = Color::White;

    for mv_str in args.iter().skip(2) {
        // should be UCI format
        let mv = Move::from_xboard_format(mv_str, &board).unwrap();
        board = board.make_move(&mv).unwrap();
    }

    for mv in &board.legal_moves().unwrap() {
        println!("{}", mv);
    }
}
<|endoftext|>


<commit_before>use combustion::board::Board;
use combustion::moves::Move;

use std::env;

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

    let mut board = Board::initial();

    for mv_str in args.iter().skip(2) {
        // should be UCI format
        let mv = Move::from_xboard_format(mv_str, &board).unwrap();
        board = board.make_move(&mv).unwrap();
    }

    for mv in &board.legal_moves().unwrap() {
        println!("{}", mv.to_xboard_format(board.color_to_move));
    }
}
<commit_msg>fix small bug<commit_after>use combustion::board::Board;
use combustion::moves::Move;

use std::env;

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

    let mut board = Board::initial();

    for mv_str in args.iter().skip(1) {
        // should be UCI format
        let mv = Move::from_xboard_format(mv_str, &board).unwrap();
        board = board.make_move(&mv).unwrap();
    }

    for mv in &board.legal_moves().unwrap() {
        println!("{}", mv.to_xboard_format(board.color_to_move));
    }
}
<|endoftext|>


<commit_before><commit_msg>Issue #33: Refactor IsPointMap<commit_after><|endoftext|>


<commit_before>#![deny(broken_intra_doc_links)]

// ignore-tidy-linelength

// @has intra_link_primitive_non_default_impl/fn.f.html
/// [`str::trim`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim'
/// [`str::to_lowercase`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
/// [`str::into_boxed_bytes`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
/// [`str::replace`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace'
pub fn f() {}
<commit_msg>Add test for f32 and f64 methods<commit_after>#![deny(broken_intra_doc_links)]

// ignore-tidy-linelength

// @has intra_link_primitive_non_default_impl/fn.str_methods.html
/// [`str::trim`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim'
/// [`str::to_lowercase`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
/// [`str::into_boxed_bytes`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
/// [`str::replace`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace'
pub fn str_methods() {}

// @has intra_link_primitive_non_default_impl/fn.f32_methods.html
/// [f32::powi]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.powi"]' 'f32::powi'
/// [f32::sqrt]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
/// [f32::mul_add]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
pub fn f32_methods() {}

// @has intra_link_primitive_non_default_impl/fn.f64_methods.html
/// [`f64::powi`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi"]' 'f64::powi'
/// [`f64::sqrt`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
/// [`f64::mul_add`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
pub fn f64_methods() {}
<|endoftext|>


<commit_before>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// 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 std::thread;

use mio;

use domain::types::*;

pub mod types;
pub use self::types::*;

pub struct FsuipcDomain {
    worker: thread::JoinHandle<()>,
    tx: mio::Sender<Command>
}

impl FsuipcDomain {
    pub fn new() -> FsuipcDomain {
        let (worker, tx) = spawn_worker();
        FsuipcDomain { worker: worker, tx: tx }
    }

    pub fn shutdown() {
        // TODO: send a msg using tx and wait for worker to stop
        unimplemented!()
    }
}

pub struct FsuipcContext;

impl FsuipcContext {
    pub fn new()  -> FsuipcContext {
        FsuipcContext
    }
}

fn spawn_worker() -> (thread::JoinHandle<()>, mio::Sender<Command>) {
    let event_loop = mio::EventLoop::new().unwrap();
    let tx = event_loop.channel();
    let worker = thread::spawn(move || {
        let mut event_loop = event_loop;
        let mut ctx = FsuipcContext::new();
        event_loop.run(&mut ctx);
    });
    (worker, tx)
}

impl mio::Handler for FsuipcContext {
    type Timeout = ();
    type Message = Command;

    fn ready(&mut self,
             event_loop: &mut mio::EventLoop<FsuipcContext>,
             token: mio::Token,
             events: mio::EventSet) {
    }
}
<commit_msg>Implement shutdown in `fsuipc::Domain`<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// 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 std::thread;

use mio;

use domain::types::*;
use util::Consume;

pub mod types;
pub use self::types::*;

enum Envelope {
    Cmd(Command),
    Shutdown
}

pub struct Domain {
    worker: thread::JoinHandle<()>,
    tx: mio::Sender<Envelope>
}

impl Domain {
    pub fn new() -> Domain {
        let (worker, tx) = spawn_worker();
        Domain { worker: worker, tx: tx }
    }

    pub fn shutdown(self) {
        self.tx.send(Envelope::Shutdown).unwrap();
        self.worker.join().unwrap();
    }
}

impl Consume for Domain {
    type Item = Command;
    type Error = mio::NotifyError<Envelope>;
    fn consume(&mut self, cmd: Command) -> Result<(), mio::NotifyError<Envelope>> {
        self.tx.send(Envelope::Cmd(cmd))
    }
}

struct Context;

impl Context {
    pub fn new()  -> Context {
        Context
    }
}

fn spawn_worker() -> (thread::JoinHandle<()>, mio::Sender<Envelope>) {
    let event_loop = mio::EventLoop::new().unwrap();
    let tx = event_loop.channel();
    let worker = thread::spawn(move || {
        let mut event_loop = event_loop;
        let mut ctx = Context::new();
        event_loop.run(&mut ctx);
    });
    (worker, tx)
}

impl mio::Handler for Context {
    type Timeout = ();
    type Message = Envelope;

    fn ready(&mut self,
             event_loop: &mut mio::EventLoop<Context>,
             token: mio::Token,
             events: mio::EventSet) {
    }

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Context>, msg: Envelope) {
        match msg {
            Envelope::Shutdown => event_loop.shutdown(),
            _ => {},
        }
    }
}

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

    #[test]
    fn should_init_and_shutdown() {
        let mut domain = Domain::new();
        domain.shutdown();
    }
}
<|endoftext|>


<commit_before>
// Copyright 2014-2015 Johannes Köster, Peer Aramillo Irizar.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the DNA alphabet.
//!
//! # Example
//!
//! ```
//! use bio::alphabets;
//! let alphabet = alphabets::dna::alphabet();
//! assert!(alphabet.is_word(b"GATTACA"));
//! assert!(alphabet.is_word(b"gattaca"));
//! assert!(!alphabet.is_word(b"ACGU"));
//! ```

use alphabets::Alphabet;
use utils::IntoTextIterator;

/// The DNA alphabet (uppercase and lowercase).
pub fn alphabet() -> Alphabet {
    Alphabet::new(b"ACGTacgt")
}

/// The DNA alphabet including N (uppercase and lowercase).
pub fn n_alphabet() -> Alphabet {
    Alphabet::new(b"ACGTNacgtn")
}

/// The IUPAC DNA alphabet (uppercase and lowercase).
pub fn iupac_alphabet() -> Alphabet {
    Alphabet::new(b"ACGTRYSWKMBDHVNZacgtryswkmbdhvnz")
}

lazy_static! {
    static ref COMPLEMENT: Vec<u8> = {
        let mut comp = Vec::new();
        comp.resize(256, 0);
        for (v, mut a) in comp.iter_mut().enumerate() {
            *a = v as u8;
        }
        for (&a, &b) in b"AGCTYRWSKMDVHBN".iter().zip(b"TCGARYWSMKHBDVN".iter()) {
            comp[a as usize] = b;
            comp[a as usize + 32] = b + 32;  // lowercase variants
        }
        comp
    };
}

/// Return complement of given DNA alphabet character (IUPAC alphabet supported).
pub fn complement(a: u8) -> u8 {
    COMPLEMENT[a as usize]
}

/// Calculate reverse complement of given text (IUPAC alphabet supported).
pub fn revcomp<'a, T: IntoTextIterator<'a>>(text: T) -> Vec<u8>
    where T::IntoIter: DoubleEndedIterator
{
    text.into_iter().rev().map(|&a| complement(a)).collect()
}
<commit_msg>Switch W and S position to match up complements<commit_after>
// Copyright 2014-2015 Johannes Köster, Peer Aramillo Irizar.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the DNA alphabet.
//!
//! # Example
//!
//! ```
//! use bio::alphabets;
//! let alphabet = alphabets::dna::alphabet();
//! assert!(alphabet.is_word(b"GATTACA"));
//! assert!(alphabet.is_word(b"gattaca"));
//! assert!(!alphabet.is_word(b"ACGU"));
//! ```

use alphabets::Alphabet;
use utils::IntoTextIterator;

/// The DNA alphabet (uppercase and lowercase).
pub fn alphabet() -> Alphabet {
    Alphabet::new(b"ACGTacgt")
}

/// The DNA alphabet including N (uppercase and lowercase).
pub fn n_alphabet() -> Alphabet {
    Alphabet::new(b"ACGTNacgtn")
}

/// The IUPAC DNA alphabet (uppercase and lowercase).
pub fn iupac_alphabet() -> Alphabet {
    Alphabet::new(b"ACGTRYSWKMBDHVNZacgtryswkmbdhvnz")
}

lazy_static! {
    static ref COMPLEMENT: Vec<u8> = {
        let mut comp = Vec::new();
        comp.resize(256, 0);
        for (v, mut a) in comp.iter_mut().enumerate() {
            *a = v as u8;
        }
        for (&a, &b) in b"AGCTYRWSKMDVHBN".iter().zip(b"TCGARYSWMKHBDVN".iter()) {
            comp[a as usize] = b;
            comp[a as usize + 32] = b + 32;  // lowercase variants
        }
        comp
    };
}

/// Return complement of given DNA alphabet character (IUPAC alphabet supported).
pub fn complement(a: u8) -> u8 {
    COMPLEMENT[a as usize]
}

/// Calculate reverse complement of given text (IUPAC alphabet supported).
pub fn revcomp<'a, T: IntoTextIterator<'a>>(text: T) -> Vec<u8>
    where T::IntoIter: DoubleEndedIterator
{
    text.into_iter().rev().map(|&a| complement(a)).collect()
}
<|endoftext|>


<commit_before>use std::fs;

use kite_rocksdb::RocksDBIndexStore;

use analysis::AnalyzerSpec;
use analysis::tokenizers::TokenizerSpec;
use analysis::filters::FilterSpec;
use analysis::ngram_generator::Edge;
use index::Index;

use api::persistent;
use api::iron::prelude::*;
use api::iron::status;
use api::router::Router;
use api::utils::json_response;

pub fn view_get_index(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    let indices = system.indices.read().unwrap();

    // Check index exists
    get_index_or_404!(indices, *index_name);

    // TODO
    return Ok(json_response(status::Ok, "{}"));
}

pub fn view_put_index(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    let mut indices = system.indices.write().unwrap();

    // Load data from body
    // let data = json_from_request_body!(req);

    // Create index
    let mut indices_dir = system.get_indices_dir();
    indices_dir.push(index_name);
    indices_dir.set_extension("rsi");
    let mut index = Index::new(index_name.clone().to_owned(), RocksDBIndexStore::create(indices_dir).unwrap());

    // Insert standard and edgengram analyzers
    // TODO: Load these from index settings
    index.analyzers.insert("standard".to_string(), AnalyzerSpec {
        tokenizer: TokenizerSpec::Standard,
        filters: vec![
            FilterSpec::Lowercase,
            FilterSpec::ASCIIFolding,
        ]
    });
    index.analyzers.insert("edgengram_analyzer".to_string(), AnalyzerSpec {
        tokenizer: TokenizerSpec::Standard,
        filters: vec![
            FilterSpec::Lowercase,
            FilterSpec::ASCIIFolding,
            FilterSpec::NGram {
                min_size: 2,
                max_size: 15,
                edge: Edge::Left
            },
        ]
    });

    // TODO: load settings

    let index_ref = indices.insert(index);
    indices.aliases.insert(index_name.clone().to_owned(), index_ref);

    system.log.info("[api] created index", b!("index" => *index_name));

    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}

pub fn view_delete_index(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    let mut indices = system.indices.write().unwrap();

    // Make sure the index exists
    get_index_or_404!(indices, *index_name);

    // Remove index from array
    let index_ref = match indices.aliases.get(*index_name) {
        Some(index_ref) => Some(*index_ref),
        None => None
    };

    if let Some(ref index_ref) = index_ref {
        indices.remove(index_ref);
    }

    // Delete file
    let mut indices_dir = system.get_indices_dir();
    indices_dir.push(index_name);
    indices_dir.set_extension("rsi");
    fs::remove_dir_all(&indices_dir).unwrap();

    system.log.info("[api] deleted index", b!("index" => *index_name));

    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}

pub fn view_post_refresh_index(_req: &mut Request) -> IronResult<Response> {
    // let ref system = get_system!(req);
    // let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    // TODO
    // let mut indices = system.indices.write().unwrap();

    // TODO: {"_shards":{"total":10,"successful":5,"failed":0}}
    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}
<commit_msg>Report warning when index data cannot be deleted<commit_after>use std::fs;

use kite_rocksdb::RocksDBIndexStore;

use analysis::AnalyzerSpec;
use analysis::tokenizers::TokenizerSpec;
use analysis::filters::FilterSpec;
use analysis::ngram_generator::Edge;
use index::Index;

use api::persistent;
use api::iron::prelude::*;
use api::iron::status;
use api::router::Router;
use api::utils::json_response;

pub fn view_get_index(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    let indices = system.indices.read().unwrap();

    // Check index exists
    get_index_or_404!(indices, *index_name);

    // TODO
    return Ok(json_response(status::Ok, "{}"));
}

pub fn view_put_index(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    let mut indices = system.indices.write().unwrap();

    // Load data from body
    // let data = json_from_request_body!(req);

    // Create index
    let mut indices_dir = system.get_indices_dir();
    indices_dir.push(index_name);
    indices_dir.set_extension("rsi");
    let mut index = Index::new(index_name.clone().to_owned(), RocksDBIndexStore::create(indices_dir).unwrap());

    // Insert standard and edgengram analyzers
    // TODO: Load these from index settings
    index.analyzers.insert("standard".to_string(), AnalyzerSpec {
        tokenizer: TokenizerSpec::Standard,
        filters: vec![
            FilterSpec::Lowercase,
            FilterSpec::ASCIIFolding,
        ]
    });
    index.analyzers.insert("edgengram_analyzer".to_string(), AnalyzerSpec {
        tokenizer: TokenizerSpec::Standard,
        filters: vec![
            FilterSpec::Lowercase,
            FilterSpec::ASCIIFolding,
            FilterSpec::NGram {
                min_size: 2,
                max_size: 15,
                edge: Edge::Left
            },
        ]
    });

    // TODO: load settings

    let index_ref = indices.insert(index);
    indices.aliases.insert(index_name.clone().to_owned(), index_ref);

    system.log.info("[api] created index", b!("index" => *index_name));

    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}

pub fn view_delete_index(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    let mut indices = system.indices.write().unwrap();

    // Make sure the index exists
    get_index_or_404!(indices, *index_name);

    // Remove index from array
    let index_ref = match indices.aliases.get(*index_name) {
        Some(index_ref) => Some(*index_ref),
        None => None
    };

    if let Some(ref index_ref) = index_ref {
        indices.remove(index_ref);
    }

    // Delete file
    let mut indices_dir = system.get_indices_dir();
    indices_dir.push(index_name);
    indices_dir.set_extension("rsi");
    match fs::remove_dir_all(&indices_dir) {
        Ok(()) => {},
        Err(e) => {
            system.log.warn("[api] failed to delete index data", b!("index" => *index_name, "error" => format!("{}", e)));
        }
    }

    system.log.info("[api] deleted index", b!("index" => *index_name));

    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}

pub fn view_post_refresh_index(_req: &mut Request) -> IronResult<Response> {
    // let ref system = get_system!(req);
    // let ref index_name = read_path_parameter!(req, "index").unwrap_or("");

    // Lock index array
    // TODO
    // let mut indices = system.indices.write().unwrap();

    // TODO: {"_shards":{"total":10,"successful":5,"failed":0}}
    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}
<|endoftext|>


<commit_before><commit_msg>Add unit tests and associated bugfixes for remaining linux parsers<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented unit() and transpose() for rank-2 tensors<commit_after><|endoftext|>


<commit_before><commit_msg>vhost_kern: add IOTLB message support<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use interner::StringKey;
use std::fmt;

#[derive(PartialEq, Debug, Ord, PartialOrd, Eq, Clone)]
pub enum Type {
    Named(StringKey),
    List(Box<Type>),
    NonNull(Box<Type>),
}

impl Type {
    pub fn inner(&self) -> Type {
        match self {
            Type::Named(t) => Type::Named(*t),
            Type::List(of) => of.inner(),
            Type::NonNull(of) => of.inner(),
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum TypeSystemDefinition {
    SchemaDefinition {
        directives: Vec<Directive>,
        operation_types: Vec<OperationTypeDefinition>,
    },
    ObjectTypeExtension {
        name: StringKey,
        interfaces: Vec<StringKey>,
        fields: Vec<FieldDefinition>,
        directives: Vec<Directive>,
    },
    ObjectTypeDefinition {
        name: StringKey,
        interfaces: Vec<StringKey>,
        fields: Vec<FieldDefinition>,
        directives: Vec<Directive>,
    },
    InterfaceTypeDefinition {
        name: StringKey,
        interfaces: Vec<StringKey>,
        directives: Vec<Directive>,
        fields: Vec<FieldDefinition>,
    },
    InterfaceTypeExtension {
        name: StringKey,
        directives: Vec<Directive>,
        fields: Vec<FieldDefinition>,
    },
    UnionTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
        members: Vec<StringKey>,
    },
    DirectiveDefinition {
        name: StringKey,
        arguments: Vec<InputValueDefinition>,
        repeatable: bool,
        locations: Vec<DirectiveLocation>,
    },
    InputObjectTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
        fields: Vec<InputValueDefinition>,
    },
    EnumTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
        values: Vec<EnumValueDefinition>,
    },
    ScalarTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
    },
}

#[derive(PartialEq, Debug)]
pub struct OperationTypeDefinition {
    pub operation: OperationType,
    pub type_: StringKey,
}

#[derive(PartialEq, Debug)]
pub struct EnumValueDefinition {
    pub name: StringKey,
    pub directives: Vec<Directive>,
}

#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub enum DirectiveLocation {
    Query,
    Mutation,
    Subscription,
    Field,
    FragmentDefinition,
    FragmentSpread,
    InlineFragment,
    Schema,
    Scalar,
    Object,
    FieldDefinition,
    ArgumentDefinition,
    Interface,
    Union,
    Enum,
    EnumValue,
    InputObject,
    InputFieldDefinition,
    VariableDefinition,
}

impl fmt::Display for DirectiveLocation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DirectiveLocation::Query => f.write_fmt(format_args!("QUERY")),
            DirectiveLocation::Mutation => f.write_fmt(format_args!("MUTATION")),
            DirectiveLocation::Subscription => f.write_fmt(format_args!("SUBSCRIPTION")),
            DirectiveLocation::Field => f.write_fmt(format_args!("FIELD")),
            DirectiveLocation::FragmentDefinition => {
                f.write_fmt(format_args!("FRAGMENT_DEFINITION"))
            }
            DirectiveLocation::FragmentSpread => f.write_fmt(format_args!("FRAGMENT_SPREAD")),
            DirectiveLocation::InlineFragment => f.write_fmt(format_args!("INLINE_FRAGMENT")),
            DirectiveLocation::Schema => f.write_fmt(format_args!("SCHEMA")),
            DirectiveLocation::Scalar => f.write_fmt(format_args!("SCALAR")),
            DirectiveLocation::Object => f.write_fmt(format_args!("OBJECT")),
            DirectiveLocation::FieldDefinition => f.write_fmt(format_args!("FIELD_DEFINITION")),
            DirectiveLocation::ArgumentDefinition => {
                f.write_fmt(format_args!("ARGUMENT_DEFINITION"))
            }
            DirectiveLocation::Interface => f.write_fmt(format_args!("INTERFACE")),
            DirectiveLocation::Union => f.write_fmt(format_args!("UNION")),
            DirectiveLocation::Enum => f.write_fmt(format_args!("ENUM")),
            DirectiveLocation::EnumValue => f.write_fmt(format_args!("ENUM_VALUE")),
            DirectiveLocation::InputObject => f.write_fmt(format_args!("INPUT_OBJECT")),
            DirectiveLocation::InputFieldDefinition => {
                f.write_fmt(format_args!("INPUT_FIELD_DEFINITION"))
            }
            DirectiveLocation::VariableDefinition => {
                f.write_fmt(format_args!("VARIABLE_DEFINITION"))
            }
        }
    }
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub enum OperationType {
    Query,
    Mutation,
    Subscription,
}

#[derive(PartialEq, Debug)]
pub struct InputValueDefinition {
    pub name: StringKey,
    pub type_: Type,
    pub default_value: Option<Value>,
    pub directives: Vec<Directive>,
}

#[derive(PartialEq, Debug)]
pub struct FieldDefinition {
    pub name: StringKey,
    pub type_: Type,
    pub arguments: Vec<InputValueDefinition>,
    pub directives: Vec<Directive>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Value {
    Null,
    String(String),
    Boolean(bool),
    Enum(StringKey),
    Int(String),
    Float(String),
    List(ListValue),
    Object(ObjectValue),
}
impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Value::String(value) => f.write_fmt(format_args!("\"{}\"", value)),
            Value::Int(value) | Value::Float(value) => f.write_fmt(format_args!("{}", value)),
            Value::Boolean(value) => f.write_fmt(format_args!("{}", value)),
            Value::Enum(value) => f.write_fmt(format_args!("{}", value.lookup())),
            Value::List(value) => f.write_fmt(format_args!("{}", value)),
            Value::Object(value) => f.write_fmt(format_args!("{}", value)),
            _null => f.write_fmt(format_args!("UNKNOWN")),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ListValue {
    pub values: Vec<Value>,
}
impl fmt::Display for ListValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[")?;
        let mut first = true;
        for item in &self.values {
            if first {
                first = false;
            } else {
                write!(f, ", ")?;
            }
            write!(f, "{}", item)?;
        }
        write!(f, "]")
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ObjectValue {
    pub fields: Vec<ObjectField>,
}
impl fmt::Display for ObjectValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{{")?;
        let mut first = true;
        for field in &self.fields {
            if first {
                first = false;
            } else {
                write!(f, ", ")?;
            }
            write!(f, "{}: {}", field.name, field.value)?;
        }
        write!(f, "}}")
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ObjectField {
    pub name: StringKey,
    pub value: Value,
}

#[derive(PartialEq, Debug)]
pub struct Argument {
    pub name: StringKey,
    pub value: Value,
}

#[derive(PartialEq, Debug)]
pub struct Directive {
    pub name: StringKey,
    pub arguments: Vec<Argument>,
}
<commit_msg>Replace f.write_fmt with write!<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use interner::StringKey;
use std::fmt;

#[derive(PartialEq, Debug, Ord, PartialOrd, Eq, Clone)]
pub enum Type {
    Named(StringKey),
    List(Box<Type>),
    NonNull(Box<Type>),
}

impl Type {
    pub fn inner(&self) -> Type {
        match self {
            Type::Named(t) => Type::Named(*t),
            Type::List(of) => of.inner(),
            Type::NonNull(of) => of.inner(),
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum TypeSystemDefinition {
    SchemaDefinition {
        directives: Vec<Directive>,
        operation_types: Vec<OperationTypeDefinition>,
    },
    ObjectTypeExtension {
        name: StringKey,
        interfaces: Vec<StringKey>,
        fields: Vec<FieldDefinition>,
        directives: Vec<Directive>,
    },
    ObjectTypeDefinition {
        name: StringKey,
        interfaces: Vec<StringKey>,
        fields: Vec<FieldDefinition>,
        directives: Vec<Directive>,
    },
    InterfaceTypeDefinition {
        name: StringKey,
        interfaces: Vec<StringKey>,
        directives: Vec<Directive>,
        fields: Vec<FieldDefinition>,
    },
    InterfaceTypeExtension {
        name: StringKey,
        directives: Vec<Directive>,
        fields: Vec<FieldDefinition>,
    },
    UnionTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
        members: Vec<StringKey>,
    },
    DirectiveDefinition {
        name: StringKey,
        arguments: Vec<InputValueDefinition>,
        repeatable: bool,
        locations: Vec<DirectiveLocation>,
    },
    InputObjectTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
        fields: Vec<InputValueDefinition>,
    },
    EnumTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
        values: Vec<EnumValueDefinition>,
    },
    ScalarTypeDefinition {
        name: StringKey,
        directives: Vec<Directive>,
    },
}

#[derive(PartialEq, Debug)]
pub struct OperationTypeDefinition {
    pub operation: OperationType,
    pub type_: StringKey,
}

#[derive(PartialEq, Debug)]
pub struct EnumValueDefinition {
    pub name: StringKey,
    pub directives: Vec<Directive>,
}

#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub enum DirectiveLocation {
    Query,
    Mutation,
    Subscription,
    Field,
    FragmentDefinition,
    FragmentSpread,
    InlineFragment,
    Schema,
    Scalar,
    Object,
    FieldDefinition,
    ArgumentDefinition,
    Interface,
    Union,
    Enum,
    EnumValue,
    InputObject,
    InputFieldDefinition,
    VariableDefinition,
}

impl fmt::Display for DirectiveLocation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DirectiveLocation::Query => write!(f, "QUERY"),
            DirectiveLocation::Mutation => write!(f, "MUTATION"),
            DirectiveLocation::Subscription => write!(f, "SUBSCRIPTION"),
            DirectiveLocation::Field => write!(f, "FIELD"),
            DirectiveLocation::FragmentDefinition => write!(f, "FRAGMENT_DEFINITION"),
            DirectiveLocation::FragmentSpread => write!(f, "FRAGMENT_SPREAD"),
            DirectiveLocation::InlineFragment => write!(f, "INLINE_FRAGMENT"),
            DirectiveLocation::Schema => write!(f, "SCHEMA"),
            DirectiveLocation::Scalar => write!(f, "SCALAR"),
            DirectiveLocation::Object => write!(f, "OBJECT"),
            DirectiveLocation::FieldDefinition => write!(f, "FIELD_DEFINITION"),
            DirectiveLocation::ArgumentDefinition => write!(f, "ARGUMENT_DEFINITION"),
            DirectiveLocation::Interface => write!(f, "INTERFACE"),
            DirectiveLocation::Union => write!(f, "UNION"),
            DirectiveLocation::Enum => write!(f, "ENUM"),
            DirectiveLocation::EnumValue => write!(f, "ENUM_VALUE"),
            DirectiveLocation::InputObject => write!(f, "INPUT_OBJECT"),
            DirectiveLocation::InputFieldDefinition => write!(f, "INPUT_FIELD_DEFINITION"),
            DirectiveLocation::VariableDefinition => write!(f, "VARIABLE_DEFINITION"),
        }
    }
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub enum OperationType {
    Query,
    Mutation,
    Subscription,
}

#[derive(PartialEq, Debug)]
pub struct InputValueDefinition {
    pub name: StringKey,
    pub type_: Type,
    pub default_value: Option<Value>,
    pub directives: Vec<Directive>,
}

#[derive(PartialEq, Debug)]
pub struct FieldDefinition {
    pub name: StringKey,
    pub type_: Type,
    pub arguments: Vec<InputValueDefinition>,
    pub directives: Vec<Directive>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Value {
    Null,
    String(String),
    Boolean(bool),
    Enum(StringKey),
    Int(String),
    Float(String),
    List(ListValue),
    Object(ObjectValue),
}
impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Value::String(value) => write!(f, "\"{}\"", value),
            Value::Int(value) | Value::Float(value) => write!(f, "{}", value),
            Value::Boolean(value) => write!(f, "{}", value),
            Value::Enum(value) => write!(f, "{}", value),
            Value::List(value) => write!(f, "{}", value),
            Value::Object(value) => write!(f, "{}", value),
            _null => write!(f, "UNKNOWN"),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ListValue {
    pub values: Vec<Value>,
}
impl fmt::Display for ListValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[")?;
        let mut first = true;
        for item in &self.values {
            if first {
                first = false;
            } else {
                write!(f, ", ")?;
            }
            write!(f, "{}", item)?;
        }
        write!(f, "]")
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ObjectValue {
    pub fields: Vec<ObjectField>,
}
impl fmt::Display for ObjectValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{{")?;
        let mut first = true;
        for field in &self.fields {
            if first {
                first = false;
            } else {
                write!(f, ", ")?;
            }
            write!(f, "{}: {}", field.name, field.value)?;
        }
        write!(f, "}}")
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ObjectField {
    pub name: StringKey,
    pub value: Value,
}

#[derive(PartialEq, Debug)]
pub struct Argument {
    pub name: StringKey,
    pub value: Value,
}

#[derive(PartialEq, Debug)]
pub struct Directive {
    pub name: StringKey,
    pub arguments: Vec<Argument>,
}
<|endoftext|>


<commit_before>use actions::{ActorAction, ActorMessage, ActorType};
use engine::{Actor, ActorData, Animation, AnimationManager, BoundingBox, Collision, CollisionSide,
             Context, Direction, PositionChange, Renderable, SpriteRectangle, Vector2D, Viewport};
use sdl2::render::Renderer;

const KOOPA_X_MAXSPEED: f64 = 10.0;
const KOOPA_Y_MAXSPEED: f64 = 15.0;
const KOOPA_ACCELERATION: f64 = 0.18;

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum KoopaState {
    Jumping,
    Walking,
    ShellSitting,
    ShellMoving,
}

pub const KOOPA_WIDTH: u32 = 30;
pub const KOOPA_HEIGHT: u32 = 60;

pub struct Koopa {
    id: i32,
    curr_state: KoopaState,
    direction: Direction,
    grounded: bool,
    curr_speed: Vector2D,
    rect: SpriteRectangle,
    anims: AnimationManager<(KoopaState, Direction)>,
}

impl Koopa {
    pub fn new(id: i32, position: (i32, i32), renderer: &mut Renderer, fps: f64) -> Koopa {
        use engine::sprite::AnimationData;
        use engine::sprite::Direction::*;
        use self::KoopaState::*;

        let mut anims = AnimationManager::new(fps);

        let banim = Animation::new(AnimationData {
                                       width: 16,
                                       height: 29,
                                       sprites_in_row: 4,
                                       path: "./assets/koopa.png",
                                   },
                                   renderer);
        let sanim = Animation::new(AnimationData {
                                       width: 16,
                                       height: 16,
                                       sprites_in_row: 4,
                                       path: "./assets/shell.png",
                                   },
                                   renderer);

        let bbox = BoundingBox::Rectangle(SpriteRectangle::new(position.0,
                                                               position.1,
                                                               KOOPA_WIDTH,
                                                               KOOPA_HEIGHT));
        let cbbox = BoundingBox::Rectangle(SpriteRectangle::new(position.0,
                                                                position.1,
                                                                KOOPA_WIDTH,
                                                                KOOPA_WIDTH / 2));

        anims.add((Jumping, Left), banim.range(0, 1), bbox.clone());
        anims.add((Jumping, Right), banim.range(3, 4), bbox.clone());
        anims.add((Walking, Left), banim.range(0, 2), bbox.clone());
        anims.add((Walking, Right), banim.range(2, 4), bbox.clone());
        anims.add((ShellSitting, Left), sanim.range(0, 1), cbbox.clone());
        anims.add((ShellSitting, Right), sanim.range(4, 5), cbbox.clone());
        anims.add((ShellMoving, Left), sanim.range(1, 4), cbbox.clone());

        Koopa {
            id: id,
            curr_state: KoopaState::Walking,
            direction: Direction::Left,
            grounded: false,
            curr_speed: Vector2D { x: 0., y: 0. },
            rect: SpriteRectangle::new(position.0, position.1, KOOPA_WIDTH, KOOPA_HEIGHT),
            anims: anims,
        }
    }
}

impl Actor<ActorType, ActorMessage> for Koopa {
    fn handle_message(&mut self, message: &ActorMessage) -> ActorMessage {
        use actions::ActorAction::*;

        if let ActorMessage::ActorAction { send_id, ref action, .. } = *message {
            match *action {
                Collision(actor_type, side) if actor_type == ActorType::Block &&
                                               side & CollisionSide::Bottom != 0 => {
                    if self.curr_state == KoopaState::Jumping {
                        self.curr_state = KoopaState::Walking;
                    }

                    self.grounded = true;
                    ActorMessage::None
                }
                Collision(actor_type, side) if actor_type == ActorType::Player &&
                                               side & 0b1101 != 0 => {
                    // Send damage message to original sender
                    ActorMessage::ActorAction {
                        send_id: self.id,
                        recv_id: send_id,
                        action: ActorAction::DamageActor(0),
                    }
                }
                _ => ActorMessage::None,
            }
        } else {
            ActorMessage::None
        }
    }

    fn collides_with(&mut self, other: &ActorData<ActorType>) -> Option<CollisionSide> {
        let key = (self.curr_state, self.direction);
        self.anims.collides_with(&key, &other.bounding_box)
    }

    fn update(&mut self, _context: &mut Context, _elapsed: f64) -> PositionChange {
        let max_y_speed = if self.curr_state == KoopaState::Jumping {
            KOOPA_Y_MAXSPEED
        } else {
            0.
        };

        let target_speed = Vector2D {
            x: 0.,
            y: max_y_speed,
        };

        self.curr_speed = (KOOPA_ACCELERATION * target_speed) +
                          ((1.0 - KOOPA_ACCELERATION) * self.curr_speed);

        let mut change = PositionChange::new().left(self.curr_speed.x as i32);
        if self.curr_state == KoopaState::Jumping {
            change = change.down(self.curr_speed.y as i32);
        }

        // If actor is no longer grounded, change it to jumping
        if !self.grounded && self.curr_state != KoopaState::Jumping {
            self.curr_state = KoopaState::Jumping;
        }

        // Reset grounded to check if there is a bottom collision again
        if self.grounded {
            self.grounded = false;
        }

        change
    }

    fn render(&mut self, context: &mut Context, viewport: &mut Viewport, _elapsed: f64) {
        let key = (self.curr_state, self.direction);
        self.anims.render(&key, &self.rect, viewport, &mut context.renderer, false);
    }

    fn data(&mut self) -> ActorData<ActorType> {
        ActorData {
            id: self.id,
            state: self.curr_state as u32,
            damage: 5,
            resolves_collisions: true,
            collision_filter: 0b1111,
            rect: self.rect.to_sdl().unwrap(),
            bounding_box: self.anims
                              .bbox(&(self.curr_state, self.direction))
                              .map(|bb| bb.clone()),
            actor_type: ActorType::Enemy,
        }
    }

    fn change_pos(&mut self, change: &PositionChange) {
        self.rect.apply_change(&change);
        self.anims.map_bbox_mut(|bbox| bbox.apply_change(&change));
    }
}
<commit_msg>Koopa goes into shell when stomped on<commit_after>use actions::{ActorAction, ActorMessage, ActorType};
use engine::{Actor, ActorData, Animation, AnimationManager, BoundingBox, Collision, CollisionSide,
             Context, Direction, PositionChange, Renderable, SpriteRectangle, Vector2D, Viewport};
use sdl2::render::Renderer;

const KOOPA_X_MAXSPEED: f64 = 10.0;
const KOOPA_Y_MAXSPEED: f64 = 15.0;
const KOOPA_ACCELERATION: f64 = 0.18;

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum KoopaState {
    Jumping,
    Walking,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum KoopaSize {
    Upright,
    Shell,
}

pub const KOOPA_WIDTH: u32 = 30;
pub const KOOPA_HEIGHT: u32 = 60;

pub struct Koopa {
    id: i32,
    curr_state: KoopaState,
    size: KoopaSize,
    direction: Direction,
    grounded: bool,
    curr_speed: Vector2D,
    rect: SpriteRectangle,
    anims: AnimationManager<(KoopaState, KoopaSize, Direction)>,
}

impl Koopa {
    pub fn new(id: i32, position: (i32, i32), renderer: &mut Renderer, fps: f64) -> Koopa {
        use engine::sprite::AnimationData;
        use engine::sprite::Direction::*;
        use self::KoopaSize::*;
        use self::KoopaState::*;

        let mut anims = AnimationManager::new(fps);

        let banim = Animation::new(AnimationData {
                                       width: 16,
                                       height: 29,
                                       sprites_in_row: 4,
                                       path: "./assets/koopa.png",
                                   },
                                   renderer);
        let sanim = Animation::new(AnimationData {
                                       width: 16,
                                       height: 16,
                                       sprites_in_row: 4,
                                       path: "./assets/shell.png",
                                   },
                                   renderer);

        let bbox = BoundingBox::Rectangle(SpriteRectangle::new(position.0,
                                                               position.1,
                                                               KOOPA_WIDTH,
                                                               KOOPA_HEIGHT));
        let cbbox = BoundingBox::Rectangle(SpriteRectangle::new(position.0,
                                                                position.1,
                                                                KOOPA_WIDTH,
                                                                KOOPA_HEIGHT / 2));

        anims.add((Jumping, Upright, Left), banim.range(0, 1), bbox.clone());
        anims.add((Jumping, Upright, Right), banim.range(3, 4), bbox.clone());
        anims.add((Walking, Upright, Left), banim.range(0, 2), bbox.clone());
        anims.add((Walking, Upright, Right), banim.range(2, 4), bbox.clone());

        anims.add((Jumping, Shell, Left), sanim.range(0, 1), cbbox.clone());
        anims.add((Jumping, Shell, Right), sanim.range(4, 5), cbbox.clone());
        anims.add((Walking, Shell, Left), sanim.range(0, 1), cbbox.clone());
        anims.add((Walking, Shell, Right), sanim.range(4, 5), cbbox.clone());

        Koopa {
            id: id,
            curr_state: KoopaState::Walking,
            size: KoopaSize::Upright,
            direction: Direction::Left,
            grounded: false,
            curr_speed: Vector2D { x: 0., y: 0. },
            rect: SpriteRectangle::new(position.0, position.1, KOOPA_WIDTH, KOOPA_HEIGHT),
            anims: anims,
        }
    }
}

impl Actor<ActorType, ActorMessage> for Koopa {
    fn handle_message(&mut self, message: &ActorMessage) -> ActorMessage {
        use actions::ActorAction::*;

        if let ActorMessage::ActorAction { send_id, ref action, .. } = *message {
            match *action {
                Collision(actor_type, side) if actor_type == ActorType::Block &&
                                               side & CollisionSide::Bottom != 0 => {
                    if self.curr_state == KoopaState::Jumping {
                        self.curr_state = KoopaState::Walking;
                    }

                    self.grounded = true;
                    ActorMessage::None
                }
                Collision(actor_type, side) if actor_type == ActorType::Player &&
                                               side & CollisionSide::Top != 0 => {
                    // Turn to shell if upright
                    if self.size != KoopaSize::Shell {
                        let amount: i32 = self.rect.h as i32 / 2;
                        let half_change = PositionChange::new().shrink_height_bot(amount);
                        self.rect.apply_change(&half_change);
                        self.size = KoopaSize::Shell;
                    }

                    ActorMessage::None
                }
                Collision(actor_type, side) if actor_type == ActorType::Player &&
                                               side & 0b1101 != 0 => {
                    // Send damage message to original sender
                    ActorMessage::ActorAction {
                        send_id: self.id,
                        recv_id: send_id,
                        action: ActorAction::DamageActor(0),
                    }
                }
                _ => ActorMessage::None,
            }
        } else {
            ActorMessage::None
        }
    }

    fn collides_with(&mut self, other: &ActorData<ActorType>) -> Option<CollisionSide> {
        let key = (self.curr_state, self.size, self.direction);
        self.anims.collides_with(&key, &other.bounding_box)
    }

    fn update(&mut self, _context: &mut Context, _elapsed: f64) -> PositionChange {
        let max_y_speed = if self.curr_state == KoopaState::Jumping {
            KOOPA_Y_MAXSPEED
        } else {
            0.
        };

        let target_speed = Vector2D {
            x: 0.,
            y: max_y_speed,
        };

        self.curr_speed = (KOOPA_ACCELERATION * target_speed) +
                          ((1.0 - KOOPA_ACCELERATION) * self.curr_speed);

        let mut change = PositionChange::new().left(self.curr_speed.x as i32);
        if self.curr_state == KoopaState::Jumping {
            change = change.down(self.curr_speed.y as i32);
        }

        // If actor is no longer grounded, change it to jumping
        if !self.grounded && self.curr_state != KoopaState::Jumping {
            self.curr_state = KoopaState::Jumping;
        }

        // Reset grounded to check if there is a bottom collision again
        if self.grounded {
            self.grounded = false;
        }

        change
    }

    fn render(&mut self, context: &mut Context, viewport: &mut Viewport, _elapsed: f64) {
        let key = (self.curr_state, self.size, self.direction);
        self.anims.render(&key, &self.rect, viewport, &mut context.renderer, false);
    }

    fn data(&mut self) -> ActorData<ActorType> {
        ActorData {
            id: self.id,
            state: self.curr_state as u32,
            damage: 5,
            resolves_collisions: true,
            collision_filter: 0b1111,
            rect: self.rect.to_sdl().unwrap(),
            bounding_box: self.anims
                              .bbox(&(self.curr_state, self.size, self.direction))
                              .map(|bb| bb.clone()),
            actor_type: ActorType::Enemy,
        }
    }

    fn change_pos(&mut self, change: &PositionChange) {
        self.rect.apply_change(&change);
        self.anims.map_bbox_mut(|bbox| bbox.apply_change(&change));
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use super::super::Port;
use spin::Mutex;
use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { Mode8086 = 0x01
             , Init     = 0x11
             , EndIRQ   = 0x20
             , ReadIRR  = 0x0a
             , ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See here for more info:
/// https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = 0 + OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }

struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port
  , /// The port that sends and recieves data from the PIC
    data_port: Port
}

impl PIC {

    const fn leader() -> PIC {
        unsafe {
            PIC { offset: OFFSET
                , command_port: Port::new(0x20)
                , data_port: Port::new(0x21)
                }
        }
    }

    const fn follower() -> PIC {
        unsafe {
            PIC { offset: OFFSET + 8
                , command_port: Port::new(0xA0)
                , data_port: Port::new(0xA1)
                }
        }
    }

    #[inline]
    fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    #[inline]
    fn send_command(&self, command: Command) {
        unsafe {
            self.command_port
                .out8(command as u8)
        }
    }

    #[inline]
    fn send_data(&self, data: u8) {
        unsafe {
            self.data_port
                .out8(data)
        }
    }

    #[inline]
    fn initialize(&self) {
        self.send_command(Command::Init)
    }

    #[inline]
    fn read_isr(&self) -> u8 {
        self.send_command(Command::ReadISR);
        unsafe { self.data_port.in8() }
    }

    #[inline]
    fn read_irr(&self) -> u8 {
        self.send_command(Command::ReadIRR);
        unsafe { self.data_port.in8() }
    }

}

trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    #[allow(unused_must_use)]
    fn end_interrupt(&self, irq: IRQ) {
        self.send_command(Command::EndIRQ)
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct BothPICs (PIC, PIC);

impl BothPICs {
    const fn new() -> Self {
        BothPICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    pub unsafe fn initialize(&mut self) {
        let wait_port = Port::new(0x80);
        let wait = || { wait_port.out8(0); };
        // helper macro to avoid writing repetitive code
        macro_rules! send {
            (pic0 => $data:expr) => {
                self.0.send_data($data)
                wait();
            };
            (pic1 => $data:expr) => {
                self.1.send_data($data)
                wait();
            };
        }

        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = (self.0.data_port.in8(), self.1.data_port.in8());

        // Send both PICs the 'initialize' command.
        self.0.initialize(); wait();
        self.1.initialize(); wait();

        // Each PIC then expects us to send it the following:
        // 1. the PIC's new vector offset
        send!(pic0 => self.0.offset);
        send!(pic1 => self.1.offset);
        // 2. number to configure PIC cascading
        send!(pic0 => 0x04);
        send!(pic1 => 0x02);
        // 3. command for 8086 mode
        send!(pic0 => Command::Mode8086 as u8);
        send!(pic1 => Command::Mode8086 as u8);
        // 4. finally, the mask we saved earlier
        send!(pic0 => saved_mask1);
        send!(pic1 => saved_mask2);
    }
}

impl IRQHandler for BothPICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<BothPICs>
    = Mutex::new(BothPICs::new());

/// Initialize the system's Programmable Interrupt Controller
pub unsafe fn initialize() {
    PICS.lock()
        .initialize();
    println!("{:<38}{:>40}", " . . Initializing PICs", "[ OKAY ]")

}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}
<commit_msg>[x86_all] Underscore out unused variables in pics<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use super::super::Port;
use spin::Mutex;
use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { Mode8086 = 0x01
             , Init     = 0x11
             , EndIRQ   = 0x20
             , ReadIRR  = 0x0a
             , ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See here for more info:
/// https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = 0 + OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }

struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port
  , /// The port that sends and recieves data from the PIC
    data_port: Port
}

impl PIC {

    const fn leader() -> PIC {
        unsafe {
            PIC { offset: OFFSET
                , command_port: Port::new(0x20)
                , data_port: Port::new(0x21)
                }
        }
    }

    const fn follower() -> PIC {
        unsafe {
            PIC { offset: OFFSET + 8
                , command_port: Port::new(0xA0)
                , data_port: Port::new(0xA1)
                }
        }
    }

    #[inline]
    fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    #[inline]
    fn send_command(&self, command: Command) {
        unsafe {
            self.command_port
                .out8(command as u8)
        }
    }

    #[inline]
    fn send_data(&self, data: u8) {
        unsafe {
            self.data_port
                .out8(data)
        }
    }

    #[inline]
    fn initialize(&self) {
        self.send_command(Command::Init)
    }

    #[inline]
    fn read_isr(&self) -> u8 {
        self.send_command(Command::ReadISR);
        unsafe { self.data_port.in8() }
    }

    #[inline]
    fn read_irr(&self) -> u8 {
        self.send_command(Command::ReadIRR);
        unsafe { self.data_port.in8() }
    }

}

trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    #[allow(unused_must_use)]
    fn end_interrupt(&self, _: IRQ) {
        self.send_command(Command::EndIRQ)
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct BothPICs (PIC, PIC);

impl BothPICs {
    const fn new() -> Self {
        BothPICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    pub unsafe fn initialize(&mut self) {
        let wait_port = Port::new(0x80);
        let wait = || { wait_port.out8(0); };
        // helper macro to avoid writing repetitive code
        macro_rules! send {
            (pic0 => $data:expr) => {
                self.0.send_data($data)
                wait();
            };
            (pic1 => $data:expr) => {
                self.1.send_data($data)
                wait();
            };
        }

        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = (self.0.data_port.in8(), self.1.data_port.in8());

        // Send both PICs the 'initialize' command.
        self.0.initialize(); wait();
        self.1.initialize(); wait();

        // Each PIC then expects us to send it the following:
        // 1. the PIC's new vector offset
        send!(pic0 => self.0.offset);
        send!(pic1 => self.1.offset);
        // 2. number to configure PIC cascading
        send!(pic0 => 0x04);
        send!(pic1 => 0x02);
        // 3. command for 8086 mode
        send!(pic0 => Command::Mode8086 as u8);
        send!(pic1 => Command::Mode8086 as u8);
        // 4. finally, the mask we saved earlier
        send!(pic0 => saved_mask1);
        send!(pic1 => saved_mask2);
    }
}

impl IRQHandler for BothPICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<BothPICs>
    = Mutex::new(BothPICs::new());

/// Initialize the system's Programmable Interrupt Controller
pub unsafe fn initialize() {
    PICS.lock()
        .initialize();
    println!("{:<38}{:>40}", " . . Initializing PICs", "[ OKAY ]")

}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}
<|endoftext|>