<commit_before>use std::rc::Rc;

use Message;
use MiliSec;
use state::State;
use TimerEvent;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: u32,
    pub renew_timeout: Option<u32>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<String>
}

impl Conditions {
    fn new(timeout: u32) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn on_message(&mut self, message: Rc<Message>, state: &mut State) {
        if self.ignore_message(&message) {
            println!("ignoring");
            return;
        }

        if state.is_open() {
            state.add_message(message);
            if self.is_closing(state) {
                state.close()
            }
        } else if self.is_opening(&message) {
            state.add_message(message);
            state.open();
        }
    }

    fn ignore_message(&self, message: &Message) -> bool {
        !self.patterns.contains(message.get("uuid").unwrap()) && self.patterns.len() > 0
    }

    fn is_opening(&self, message: &Message) -> bool {
        self.first_opens.map_or(true, |first| {
            if first {
                self.patterns.first().unwrap() == message.get("uuid").unwrap()
            } else {
                true
            }
        })
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |closes| {
            if closes {
                self.patterns.last().map_or(false, |pattern| {
                    pattern == state.messages().last().unwrap().get("uuid").unwrap()
                })
            } else {
                false
            }
        })
    }

    fn is_closing(&self, state: &State) -> bool {
        println!("checking close");
        self.is_max_size_reached(state) || self.is_closing_message(state)
    }

    pub fn on_timer(&mut self, event: &TimerEvent, state: &mut State) {
        state.on_timer(event);
        if self.is_any_timer_expired(state) {
            println!("closing state");
            state.close()
        }
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: u32) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: u32) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<String>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}
<commit_msg>refactor in Conditions<commit_after>use std::rc::Rc;

use Message;
use MiliSec;
use state::State;
use TimerEvent;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: u32,
    pub renew_timeout: Option<u32>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<String>
}

impl Conditions {
    fn new(timeout: u32) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn on_message(&mut self, message: Rc<Message>, state: &mut State) {
        if self.ignore_message(&message) {
            println!("ignoring");
            return;
        }

        if state.is_open() {
            state.add_message(message);
            if self.is_closing(state) {
                state.close()
            }
        } else if self.is_opening(&message) {
            state.add_message(message);
            state.open();
        }
    }

    fn ignore_message(&self, message: &Message) -> bool {
        !self.patterns.contains(message.get("uuid").unwrap()) && self.patterns.len() > 0
    }

    fn is_opening(&self, message: &Message) -> bool {
        self.first_opens.map_or(true, |first_message_opens_the_context| {
            if first_message_opens_the_context {
                self.patterns.first().unwrap() == message.get("uuid").unwrap()
            } else {
                true
            }
        })
    }

    fn is_closing(&self, state: &State) -> bool {
        println!("checking close");
        self.is_max_size_reached(state) || self.is_closing_message(state)
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |last_message_closes_the_context| {
            if last_message_closes_the_context {
                self.patterns.last().unwrap() == state.messages().last().unwrap().get("uuid").unwrap()
            } else {
                false
            }
        })
    }

    pub fn on_timer(&mut self, event: &TimerEvent, state: &mut State) {
        state.on_timer(event);
        if self.is_any_timer_expired(state) {
            println!("closing state");
            state.close()
        }
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: u32) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: u32) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<String>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}
<|endoftext|>


<commit_before>#![crate_id = "crypto#0.2.0"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT"]

extern crate num;

#[cfg(test)]
extern crate test;
#[cfg(test)]
extern crate serialize;

pub mod base58;
pub mod hash;
<commit_msg>Set crate output type to `lib` to let the compiler choosing the best one.<commit_after>#![crate_id = "crypto#0.2.0"]
#![crate_type = "lib"]
#![license = "MIT"]

extern crate num;

#[cfg(test)]
extern crate test;
#[cfg(test)]
extern crate serialize;

pub mod base58;
pub mod hash;
<|endoftext|>


<commit_before>use std::error::Error;

pub trait DbChannel {
    fn query(&self, &str) -> Result<(), String>;
}
<commit_msg>refactor(channel) implement DbChannel for MySQl and Postgres<commit_after>use std::error::Error;
use mysql::Pool;
use postgres::Connection;

pub trait DbChannel {
    fn query(&self, &str) -> Result<(), String>;
}

impl DbChannel for Pool {
    fn query(&self, query: &str) -> Result<(), String> {
        match self.prep_exec(query, ()) {
            Ok(_) => Ok(()),
            Err(err) => Err(err.description().to_string())
        }
    }
}

impl DbChannel for Connection {
    fn query(&self, query: &str) -> Result<(), String> {
        match self.execute(query, &[]) {
            Ok(_) => Ok(()),
            Err(err) => Err(err.description().to_string())
        }
    }
}<|endoftext|>


<commit_before>//  Copyright 2015 Nathanael Merrill
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

use playlist;

use rustty::{
    Terminal,
    Event,
    HasSize,
    CellAccessor,
    Cell,
    Attr,
    Color,
};
use rustty::ui::{
    Painter,
    Dialog,
    Widget,
    Alignable,
    HorizontalAlign,
    VerticalAlign
};

fn create_info_dlg(length: usize) -> Dialog {
    let mut optiondlg = Dialog::new(length as usize, 4);

    let inc_label = "space --> play/pause";
    let q_label   = "x     --> exit program";
    let n_label   = "n --> next song";
    let pp_label  = "p --> prev song";

    let inc_pos = optiondlg.window().halign_line(inc_label, HorizontalAlign::Left, 1);
    let q_pos = optiondlg.window().halign_line(q_label, HorizontalAlign::Left, 1);
    let n_pos = optiondlg.window().halign_line(n_label, HorizontalAlign::Middle, 1);
    let pp_pos = optiondlg.window().halign_line(pp_label, HorizontalAlign::Middle, 1);

    optiondlg.window_mut().printline(inc_pos, 1, inc_label);
    optiondlg.window_mut().printline(q_pos, 2, q_label);
    optiondlg.window_mut().printline(n_pos, 1, n_label);
    optiondlg.window_mut().printline(pp_pos, 2, pp_label);
    optiondlg.window_mut().draw_box();
    optiondlg
}

pub enum UIResult {
    PlayPause,
    Next,
    Previous,
    Exit,
    Error,
    NA,
}

pub struct UI {
    term: Terminal,
    optiondlg: Dialog,
    canvas: Widget,
    list_canvas: Widget,
    length: usize,
    height: usize,
    time: (i32, i32),
}

impl UI {
    pub fn new(playlist: &playlist::Playlist) -> UI {
        // Create our terminal, dialog window and main canvasa
        let term = Terminal::new().expect("Failed to make Rustty terminal");
        let length = term.cols();
        let height = term.rows();

        // aligns everything
        let mut optiondlg = create_info_dlg(length);
        let mut canvas = Widget::new(length as usize, 2);
        let mut list_canvas = Widget::new(length as usize,playlist.songs.len());
        optiondlg
            .window_mut()
            .align(&term, HorizontalAlign::Middle, VerticalAlign::Bottom, 0);
        canvas.align(&term, HorizontalAlign::Middle, VerticalAlign::Bottom, 4);
        list_canvas.align(&term, HorizontalAlign::Middle, VerticalAlign::Top, 0);

        UI {term: term,
            optiondlg: optiondlg,
            canvas: canvas,
            list_canvas: list_canvas,
            length: length,
            height: height,
            time: (-1,-1),
        }
    }

    fn length_checker(&mut self) {
        let last_pos = (self.length, self.height);
        self.length = self.term.cols();
        self.height =  self.term.rows();
        match last_pos == (self.term.cols(), self.term.rows()){
            true => {},
            false => {
                self.term.clear(); //TODO Handle if this errors
                self.optiondlg = create_info_dlg(self.length);
                self.canvas = Widget::new(self.length as usize, 2);
                self.optiondlg
                    .window_mut()
                    .align(&self.term,
                           HorizontalAlign::Middle,
                           VerticalAlign::Bottom, 0);
                self.canvas.align(&self.term,
                                  HorizontalAlign::Middle,
                                  VerticalAlign::Bottom, 6);
                self.list_canvas.align(&self.term, HorizontalAlign::Left,
                                       VerticalAlign::Top, 0);
            },
        }

    }

    pub fn manage_ui(&mut self, playlist: &playlist::Playlist,
                     time: i32, totaltime: i32) -> UIResult {
        //TODO: The rest of this function won't run if there is input
        //this is not really ideal
        while let Some(Event::Key(ch)) = self.term.get_event(0).unwrap() {
            match ch {
                ' ' => return UIResult::PlayPause,
                'p' => return UIResult::Previous,
                'n' => return UIResult::Next,
                'x' => return UIResult::Exit,
                _  => return UIResult::NA,
            }
        }

        if self.time != (time, totaltime) {
            self.time = (time, totaltime);

            let curr_song = playlist.get_curr_song().unwrap_or("");
            let length_i32 = self.length as i32;
            let tnum = time.to_string().len() + curr_song.len() + totaltime.to_string().len();
            let mut num = tnum as i32;
            num = length_i32 - num - 8;
            num = num / 2;
            let append = vec![' '; num as usize].into_iter().collect::<String>();
            let append2 = match length_i32.wrapping_rem(2) {
                0 => append.clone(),
                1 => append.clone() + " ",
                _ => unreachable!(),
            };
            let display = format!("--{}{}--{}--{}{}--", time, append,
                                  curr_song, append2, totaltime);

            let v: Vec<char> = display.chars().collect();
            let (cols, rows) = self.canvas.size();
            let (cols, rows) = (cols as isize, rows as isize);
            let num_x;
            let num_not;

            if totaltime == 0 { //TODO this is bad. fix it
                num_x = 0;
            }
            else {
                num_x = (time as f32 / totaltime as f32
                         * length_i32 as f32).round() as i32;
            }
            num_not = (length_i32 - num_x);

            let mut va = vec!['x'; num_x as usize];
            let ev = vec!['-'; num_not as usize];
            for x in ev {
                va.push(x);
            }
            //v.append(&mut va); unstable
            for i in 0..cols*rows {
                let y = i as isize / cols;
                let x = i as isize % cols;
                let fep ='*';
                let mut cell = self.canvas.get_mut(x as usize, y as usize).unwrap();
                match y {
                    0 => cell.set_ch(*v.get(x as usize).unwrap_or_else(|| &fep)),
                    1 => cell.set_ch(*va.get(x as usize).unwrap_or_else(|| &fep)),
                    _ => cell.set_ch(' '),
                };
            }

            self.length_checker();
            self.second_panel(playlist, curr_song);
            self.canvas.draw_into(&mut self.term);
            self.list_canvas.draw_into(&mut self.term);
            self.optiondlg.window().draw_into(&mut self.term);
            self.term.swap_buffers().expect("swap buffers error");
        }
        return UIResult::NA;
    }

    fn second_panel(&mut self, playlist: &playlist::Playlist, curr_song: &str) {
        let cell = Cell::with_style(Color::Black, Color::Red, Attr::Default);
        let cellother = Cell::with_style(Color::Default,
                                         Color::Default,
                                         Attr::Default);
        let (_, rows) = self.list_canvas.size();

        for i in 0..rows {
            let song = playlist.songs.get(i).expect("get song failed");
            self.list_canvas
                .printline_with_cell(0, i as usize, song,
                                     match curr_song == song {
                                         true => cell,
                                         false => cellother,
                                     });
        }
    }
}
<commit_msg>Make times in UI printed in minutes and seconds.<commit_after>//  Copyright 2015 Nathanael Merrill
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

use playlist;

use rustty::{
    Terminal,
    Event,
    HasSize,
    CellAccessor,
    Cell,
    Attr,
    Color,
};
use rustty::ui::{
    Painter,
    Dialog,
    Widget,
    Alignable,
    HorizontalAlign,
    VerticalAlign
};

fn create_info_dlg(length: usize) -> Dialog {
    let mut optiondlg = Dialog::new(length as usize, 4);

    let inc_label = "space --> play/pause";
    let q_label   = "x     --> exit program";
    let n_label   = "n --> next song";
    let pp_label  = "p --> prev song";

    let inc_pos = optiondlg.window().halign_line(inc_label, HorizontalAlign::Left, 1);
    let q_pos = optiondlg.window().halign_line(q_label, HorizontalAlign::Left, 1);
    let n_pos = optiondlg.window().halign_line(n_label, HorizontalAlign::Middle, 1);
    let pp_pos = optiondlg.window().halign_line(pp_label, HorizontalAlign::Middle, 1);

    optiondlg.window_mut().printline(inc_pos, 1, inc_label);
    optiondlg.window_mut().printline(q_pos, 2, q_label);
    optiondlg.window_mut().printline(n_pos, 1, n_label);
    optiondlg.window_mut().printline(pp_pos, 2, pp_label);
    optiondlg.window_mut().draw_box();
    optiondlg
}

pub enum UIResult {
    PlayPause,
    Next,
    Previous,
    Exit,
    Error,
    NA,
}

pub struct UI {
    term: Terminal,
    optiondlg: Dialog,
    canvas: Widget,
    list_canvas: Widget,
    length: usize,
    height: usize,
    time: (i32, i32),
}

impl UI {
    pub fn new(playlist: &playlist::Playlist) -> UI {
        // Create our terminal, dialog window and main canvasa
        let term = Terminal::new().expect("Failed to make Rustty terminal");
        let length = term.cols();
        let height = term.rows();

        // aligns everything
        let mut optiondlg = create_info_dlg(length);
        let mut canvas = Widget::new(length as usize, 2);
        let mut list_canvas = Widget::new(length as usize,playlist.songs.len());
        optiondlg
            .window_mut()
            .align(&term, HorizontalAlign::Middle, VerticalAlign::Bottom, 0);
        canvas.align(&term, HorizontalAlign::Middle, VerticalAlign::Bottom, 4);
        list_canvas.align(&term, HorizontalAlign::Middle, VerticalAlign::Top, 0);

        UI {term: term,
            optiondlg: optiondlg,
            canvas: canvas,
            list_canvas: list_canvas,
            length: length,
            height: height,
            time: (-1,-1),
        }
    }

    fn length_checker(&mut self) {
        let last_pos = (self.length, self.height);
        self.length = self.term.cols();
        self.height =  self.term.rows();
        match last_pos == (self.term.cols(), self.term.rows()){
            true => {},
            false => {
                self.term.clear(); //TODO Handle if this errors
                self.optiondlg = create_info_dlg(self.length);
                self.canvas = Widget::new(self.length as usize, 2);
                self.optiondlg
                    .window_mut()
                    .align(&self.term,
                           HorizontalAlign::Middle,
                           VerticalAlign::Bottom, 0);
                self.canvas.align(&self.term,
                                  HorizontalAlign::Middle,
                                  VerticalAlign::Bottom, 6);
                self.list_canvas.align(&self.term, HorizontalAlign::Left,
                                       VerticalAlign::Top, 0);
            },
        }

    }

    pub fn manage_ui(&mut self, playlist: &playlist::Playlist,
                     time: i32, totaltime: i32) -> UIResult {
        //TODO: The rest of this function won't run if there is input
        //this is not really ideal
        while let Some(Event::Key(ch)) = self.term.get_event(0).unwrap() {
            match ch {
                ' ' => return UIResult::PlayPause,
                'p' => return UIResult::Previous,
                'n' => return UIResult::Next,
                'x' => return UIResult::Exit,
                _  => return UIResult::NA,
            }
        }

        if self.time != (time, totaltime) {
            self.time = (time, totaltime);

            if totaltime/60 > 99 {
                panic!("RFSMP does not support songs longer than 100 minutes");
            }

            let curr_song = playlist.get_curr_song().unwrap_or("");
            let length_i32 = self.length as i32;
            let tnum = curr_song.len() + ((totaltime/60).to_string().len()+3)*2;
            let mut num = tnum as i32;
            num = length_i32 - num - 8;
            num = num / 2;
            let append = vec![' '; num as usize].into_iter().collect::<String>();
            let append2 = match length_i32.wrapping_rem(2) {
                0 => append.clone(),
                1 => append.clone() + " ",
                _ => unreachable!(),
            };
            let display = format!("--{:0>7$}:{:0>2}{}--{}--{}{:0>7$}:{:0>2}--",
                                  time/60, time%60, append, curr_song, append2,
                                  totaltime/60, totaltime%60,
                                  (totaltime/60).to_string().len());

            let v: Vec<char> = display.chars().collect();
            let (cols, rows) = self.canvas.size();
            let (cols, rows) = (cols as isize, rows as isize);
            let num_x;
            let num_not;

            if totaltime == 0 { //TODO this is bad. fix it
                num_x = 0;
            }
            else {
                num_x = (time as f32 / totaltime as f32
                         * length_i32 as f32).round() as i32;
            }
            num_not = (length_i32 - num_x);

            let mut va = vec!['x'; num_x as usize];
            let ev = vec!['-'; num_not as usize];
            for x in ev {
                va.push(x);
            }
            //v.append(&mut va); unstable
            for i in 0..cols*rows {
                let y = i as isize / cols;
                let x = i as isize % cols;
                let fep ='*';
                let mut cell = self.canvas.get_mut(x as usize, y as usize).unwrap();
                match y {
                    0 => cell.set_ch(*v.get(x as usize).unwrap_or_else(|| &fep)),
                    1 => cell.set_ch(*va.get(x as usize).unwrap_or_else(|| &fep)),
                    _ => cell.set_ch(' '),
                };
            }

            self.length_checker();
            self.second_panel(playlist, curr_song);
            self.canvas.draw_into(&mut self.term);
            self.list_canvas.draw_into(&mut self.term);
            self.optiondlg.window().draw_into(&mut self.term);
            self.term.swap_buffers().expect("swap buffers error");
        }
        return UIResult::NA;
    }

    fn second_panel(&mut self, playlist: &playlist::Playlist, curr_song: &str) {
        let cell = Cell::with_style(Color::Black, Color::Red, Attr::Default);
        let cellother = Cell::with_style(Color::Default,
                                         Color::Default,
                                         Attr::Default);
        let (_, rows) = self.list_canvas.size();

        for i in 0..rows {
            let song = playlist.songs.get(i).expect("get song failed");
            self.list_canvas
                .printline_with_cell(0, i as usize, song,
                                     match curr_song == song {
                                         true => cell,
                                         false => cellother,
                                     });
        }
    }
}
<|endoftext|>


<commit_before>pub mod search;

use std::thread;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use basetypes::*;
use uci::{UciEngine, UciEngineFactory, EngineReply, OptionName, OptionDescription};
use position::Position;
use chess_move::*;
use tt::TranspositionTable;
use rand;
use rand::distributions::{Sample, Range};

const VERSION: &'static str = "0.1";

/// Implements `UciEngine` trait.
pub struct Engine {
    position: Position,
    pondering_is_allowed: bool,
    multi_pv: usize,
    replies: Vec<EngineReply>,
    is_thinking: bool,
    infinite: bool,
    ponder: bool,
    best_move: String,
    move_stack: Vec<Move>,
    tt: Arc<TranspositionTable>,
    commands: Sender<search::Command>,
    reports: Receiver<search::Progress>,
    results: Receiver<search::Done>,
    searcher: thread::JoinHandle<()>,
}

impl Engine {
    /// Creates a new instance.
    ///
    /// `tt_size_mb` is the preferred size of the transposition
    /// table in Mbytes.
    pub fn new(tt_size_mb: usize) -> Engine {
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let (results_tx, results_rx) = channel();
        let mut tt = TranspositionTable::new();
        tt.resize(tt_size_mb);
        let tt = Arc::new(tt);
        Engine {
            position: Position::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 \
                                          1")
                          .ok()
                          .unwrap(),
            pondering_is_allowed: false,
            multi_pv: 1,
            is_thinking: false,
            replies: vec![],
            infinite: false,
            ponder: false,
            best_move: "0000".to_string(),
            move_stack: Vec::new(),
            tt: tt.clone(),
            commands: commands_tx,
            reports: reports_rx,
            results: results_rx,
            searcher: thread::spawn(move || {
                search::run(&tt, commands_rx, reports_tx, results_tx);
            }),
        }
    }
}

impl UciEngine for Engine {
    fn set_option(&mut self, name: &str, value: &str) {
        match name {
            // We do not support re-sizing of the transposition table
            // once the engine had started, so we do nothing.
            "Hash" => (),

            // Tells the engine that it will be allowed to ponder.
            // This option is needed because the engine might change
            // its time management algorithm when pondering is
            // allowed.
            "Ponder" => {
                self.pondering_is_allowed = value == "true";
            }

            // Tells the engine to output multiple best lines.
            // the default value is `1`.)
            "MultiPV" => {
                self.multi_pv = value.parse::<usize>().ok().unwrap_or(1);
            }

            // An invalid option.
            _ => {
                self.replies.push(EngineReply::Info(vec![("string".to_string(),
                                                          format!("Invalid option \"{}\"", name))]));
            }
        }
    }

    fn new_game(&mut self) {
        // Clearing the transposition table would not change anything,
        // so we do nothing.
    }

    fn position(&mut self, fen: &str, moves: &mut Iterator<Item = &str>) {
        if !self.is_thinking {
            if let Ok(p) = Position::from_history(fen, moves) {
                self.position = p;
            }
        }
    }

    #[allow(unused_variables)]
    fn go(&mut self,
          searchmoves: Option<Vec<String>>,
          ponder: bool,
          wtime: Option<u64>,
          btime: Option<u64>,
          winc: Option<u64>,
          binc: Option<u64>,
          movestogo: Option<u64>,
          depth: Option<u64>,
          nodes: Option<u64>,
          mate: Option<u64>,
          movetime: Option<u64>,
          infinite: bool) {
        if self.is_thinking {
            return;
        }

        // Get some legal move
        let s = &mut self.move_stack;
        let p = &mut self.position;
        p.generate_moves(s);
        let mut rng = rand::thread_rng();
        let mut between = Range::new(0, 10);
        let mut best_score = -20000;
        while let Some(m) = s.pop() {
            if p.do_move(m) {
                let score = -p.evaluate_quiescence(-20000, 20000).0 + between.sample(&mut rng);
                if score >= best_score {
                    best_score = score;
                    // self.replies.push(EngineReply::Info(vec![("info".to_string(),
                    //                                           format!("{} -> {}",
                    //                                                   m.notation(),
                    //                                                   score))]));
                    self.best_move = m.notation();
                }
                p.undo_move();
            }
        }

        // Start a new search
        self.commands
            .send(search::Command::Search(search::Parameters {
                id: 0,
                position: p.clone(),
                depth: 5,
                lower_bound: -20000,
                upper_bound: 20000,
            }))
            .unwrap();
        self.ponder = ponder;
        self.infinite = infinite;
        self.is_thinking = true;
    }

    fn ponder_hit(&mut self) {
        if self.is_thinking && self.ponder {
            self.ponder = false;
        }
    }

    fn stop(&mut self) {
        if self.is_thinking {
            self.commands.send(search::Command::Stop).unwrap();
            self.ponder = false;
            self.infinite = false;
        }
    }

    fn is_thinking(&self) -> bool {
        self.is_thinking
    }

    fn get_reply(&mut self) -> Option<EngineReply> {
        if !self.ponder {
            if let Ok(_) = self.results.try_recv() {
                self.try_to_get_best_move_from_tt();
                self.replies.push(EngineReply::BestMove {
                    best_move: self.best_move.clone(),
                    ponder_move: None,
                });
                self.best_move = "0000".to_string();
                self.is_thinking = false;
            }
        }
        self.replies.pop()
    }
}

impl Engine {
    fn try_to_get_best_move_from_tt(&mut self) {
        if let Some(entry) = self.tt.probe(self.position.hash()) {
            let m = entry.move16();
            if m != 0 {
                let move_type = ((m & 0b1100000000000000) >> 14) as MoveType;
                let orig_square = ((m & 0b0011111100000000) >> 8) as Square;
                let dest_square = ((m & 0b0000000011111100) >> 2) as Square;
                let promoted_piece = match m & 0b11 {
                    0 => "q",
                    1 => "r",
                    2 => "b",
                    3 => "n",
                    _ => panic!("invalid promoted piece code"),
                };
                self.best_move = format!("{}{}{}",
                                         notation(orig_square),
                                         notation(dest_square),
                                         if move_type == MOVE_PROMOTION {
                                             promoted_piece
                                         } else {
                                             ""
                                         })
            }
        }
    }
}

/// Implements `UciEngineFactory` trait.
pub struct EngineFactory;

impl UciEngineFactory<Engine> for EngineFactory {
    fn name(&self) -> String {
        format!("Alcibiades {}", VERSION)
    }

    fn author(&self) -> String {
        "Evgeni Pandurski".to_string()
    }

    fn options(&self) -> Vec<(OptionName, OptionDescription)> {
        vec![
            // TODO: Calculate a sane limit for the hash size.
            ("Hash".to_string(), OptionDescription::Spin { min: 1, max: 2048, default: 16 }),
            ("Ponder".to_string(), OptionDescription::Check { default: false }),
            ("MultiPV".to_string(), OptionDescription::Spin { min: 1, max: 32, default: 1 }),
        ]
    }

    fn create(&self, hash_size_mb: Option<usize>) -> Engine {
        Engine::new(hash_size_mb.unwrap_or(16))
    }
}
<commit_msg>refactoring<commit_after>pub mod search;

use std::thread;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use basetypes::*;
use uci::{UciEngine, UciEngineFactory, EngineReply, OptionName, OptionDescription};
use position::Position;
use chess_move::*;
use tt::TranspositionTable;
use rand;
use rand::distributions::{Sample, Range};

const VERSION: &'static str = "0.1";

/// Implements `UciEngine` trait.
pub struct Engine {
    position: Position,
    pondering_is_allowed: bool,
    multi_pv: usize,
    is_thinking: bool,
    is_pondering: bool,
    replies: Vec<EngineReply>,
    infinite: bool,
    best_move: String,
    move_stack: Vec<Move>,
    tt: Arc<TranspositionTable>,
    commands: Sender<search::Command>,
    reports: Receiver<search::Progress>,
    results: Receiver<search::Done>,
    searcher: thread::JoinHandle<()>,
}

impl Engine {
    /// Creates a new instance.
    ///
    /// `tt_size_mb` is the preferred size of the transposition
    /// table in Mbytes.
    pub fn new(tt_size_mb: usize) -> Engine {
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let (results_tx, results_rx) = channel();
        let mut tt = TranspositionTable::new();
        tt.resize(tt_size_mb);
        let tt = Arc::new(tt);
        Engine {
            position: Position::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 \
                                          1")
                          .ok()
                          .unwrap(),
            pondering_is_allowed: false,
            multi_pv: 1,
            is_thinking: false,
            is_pondering: false,
            replies: vec![],
            infinite: false,
            best_move: "0000".to_string(),
            move_stack: Vec::new(),
            tt: tt.clone(),
            commands: commands_tx,
            reports: reports_rx,
            results: results_rx,
            searcher: thread::spawn(move || {
                search::run(&tt, commands_rx, reports_tx, results_tx);
            }),
        }
    }
}

impl UciEngine for Engine {
    fn set_option(&mut self, name: &str, value: &str) {
        match name {
            // We do not support re-sizing of the transposition table
            // once the engine had started, so we do nothing.
            "Hash" => (),

            // Tells the engine that it will be allowed to ponder.
            // This option is needed because the engine might change
            // its time management algorithm when pondering is
            // allowed.
            "Ponder" => {
                self.pondering_is_allowed = value == "true";
            }

            // Tells the engine to output multiple best lines.
            // the default value is `1`.)
            "MultiPV" => {
                self.multi_pv = value.parse::<usize>().ok().unwrap_or(1);
            }

            // An invalid option.
            _ => {
                self.replies.push(EngineReply::Info(vec![("string".to_string(),
                                                          format!("Invalid option \"{}\"", name))]));
            }
        }
    }

    fn new_game(&mut self) {
        // Clearing the transposition table would not change anything,
        // so we do nothing.
    }

    fn position(&mut self, fen: &str, moves: &mut Iterator<Item = &str>) {
        if !self.is_thinking {
            if let Ok(p) = Position::from_history(fen, moves) {
                self.position = p;
            }
        }
    }

    #[allow(unused_variables)]
    fn go(&mut self,
          searchmoves: Option<Vec<String>>,
          ponder: bool,
          wtime: Option<u64>,
          btime: Option<u64>,
          winc: Option<u64>,
          binc: Option<u64>,
          movestogo: Option<u64>,
          depth: Option<u64>,
          nodes: Option<u64>,
          mate: Option<u64>,
          movetime: Option<u64>,
          infinite: bool) {
        if self.is_thinking {
            return;
        }

        // Get some legal move
        let s = &mut self.move_stack;
        let p = &mut self.position;
        p.generate_moves(s);
        let mut rng = rand::thread_rng();
        let mut between = Range::new(0, 10);
        let mut best_score = -20000;
        while let Some(m) = s.pop() {
            if p.do_move(m) {
                let score = -p.evaluate_quiescence(-20000, 20000).0 + between.sample(&mut rng);
                if score >= best_score {
                    best_score = score;
                    // self.replies.push(EngineReply::Info(vec![("info".to_string(),
                    //                                           format!("{} -> {}",
                    //                                                   m.notation(),
                    //                                                   score))]));
                    self.best_move = m.notation();
                }
                p.undo_move();
            }
        }

        // Start a new search
        self.commands
            .send(search::Command::Search(search::Parameters {
                id: 0,
                position: p.clone(),
                depth: 5,
                lower_bound: -20000,
                upper_bound: 20000,
            }))
            .unwrap();
        self.is_thinking = true;
        self.is_pondering = ponder;
        self.infinite = infinite;
    }

    fn ponder_hit(&mut self) {
        if self.is_thinking && self.is_pondering {
            self.is_pondering = false;
        }
    }

    fn stop(&mut self) {
        if self.is_thinking {
            self.commands.send(search::Command::Stop).unwrap();
            self.is_pondering = false;  // TODO: search the TT here instead.
        }
    }

    fn is_thinking(&self) -> bool {
        self.is_thinking
    }

    fn get_reply(&mut self) -> Option<EngineReply> {
        if !self.is_pondering {
            if let Ok(_) = self.results.try_recv() {
                self.try_to_get_best_move_from_tt();
                self.replies.push(EngineReply::BestMove {
                    best_move: self.best_move.clone(),
                    ponder_move: None,
                });
                self.best_move = "0000".to_string();
                self.is_thinking = false;
            }
        }
        self.replies.pop()
    }
}

impl Engine {
    fn try_to_get_best_move_from_tt(&mut self) {
        if let Some(entry) = self.tt.probe(self.position.hash()) {
            let m = entry.move16();
            if m != 0 {
                let move_type = ((m & 0b1100000000000000) >> 14) as MoveType;
                let orig_square = ((m & 0b0011111100000000) >> 8) as Square;
                let dest_square = ((m & 0b0000000011111100) >> 2) as Square;
                let promoted_piece = match m & 0b11 {
                    0 => "q",
                    1 => "r",
                    2 => "b",
                    3 => "n",
                    _ => panic!("invalid promoted piece code"),
                };
                self.best_move = format!("{}{}{}",
                                         notation(orig_square),
                                         notation(dest_square),
                                         if move_type == MOVE_PROMOTION {
                                             promoted_piece
                                         } else {
                                             ""
                                         })
            }
        }
    }
}

/// Implements `UciEngineFactory` trait.
pub struct EngineFactory;

impl UciEngineFactory<Engine> for EngineFactory {
    fn name(&self) -> String {
        format!("Alcibiades {}", VERSION)
    }

    fn author(&self) -> String {
        "Evgeni Pandurski".to_string()
    }

    fn options(&self) -> Vec<(OptionName, OptionDescription)> {
        vec![
            // TODO: Calculate a sane limit for the hash size.
            ("Hash".to_string(), OptionDescription::Spin { min: 1, max: 2048, default: 16 }),
            ("Ponder".to_string(), OptionDescription::Check { default: false }),
            ("MultiPV".to_string(), OptionDescription::Spin { min: 1, max: 32, default: 1 }),
        ]
    }

    fn create(&self, hash_size_mb: Option<usize>) -> Engine {
        Engine::new(hash_size_mb.unwrap_or(16))
    }
}
<|endoftext|>


<commit_before>use interpreter::Interpreter;
use std::io::process::Command;

pub struct Executable<'f, 'i> {
    file: &'f Path,
    interpreter: Option<&'i Interpreter>,
}

impl<'f, 'i> Executable<'f, 'i> {
    pub fn new(file: &'f Path, interpreter: Option<&'i Interpreter>)
        -> Executable<'f, 'i>
    {
        Executable {
            file: file,
            interpreter: interpreter,
        }
    }

    pub fn bench(&self, iters: u64) -> u64 {
        let file = self.file;
        let mut command = match self.interpreter {
            None => Command::new(format!("./{}", file.display())),
            Some(interpreter) => Command::new(interpreter.command()),

        };

        let iters = iters.to_str();
        let output = match self.interpreter {
            None => command.arg(iters).output(),
            Some(interpreter) => {
                let flags = interpreter.flags();

                command.args(flags).arg(file).arg(iters).output()
            },
        };

        match output {
            Err(_) => fail!("couldn't find {}", command),
            Ok(output) => if output.status.success() {
                match StrBuf::from_utf8(output.output) {
                    Err(_) => fail!("malformed output"),
                    Ok(string) => match from_str(string.as_slice().trim()) {
                        None => fail!("malformed output"),
                        Some(integer) => integer,
                    },
                }
            } else {
                fail!("{} failed at runtime", file.display())
            },
        }
    }

    pub fn test(&self) -> Option<StrBuf> {
        let file = self.file;
        let mut command = match self.interpreter {
            None => Command::new(format!("./{}", file.display())),
            Some(interpreter) => Command::new(interpreter.command()),

        };

        let output = match self.interpreter {
            None => command.output(),
            Some(interpreter) => {
                command.args(interpreter.flags()).arg(file).output()
            },
        };

        match output {
            Err(_) => {
                println!("Couldn't find the interpreter");

                None
            },
            Ok(output) => if output.status.success() {
                match StrBuf::from_utf8(output.output) {
                    Err(_) => {
                        println!("Bad output");

                        None
                    },
                    Ok(string) => Some(string),
                }
            } else {
                println!("Runtime failure");

                println!("{}", StrBuf::from_utf8(output.error));

                None
            },
        }
    }
}
<commit_msg>eulermark: unwrap runtime failure message<commit_after>use interpreter::Interpreter;
use std::io::process::Command;

pub struct Executable<'f, 'i> {
    file: &'f Path,
    interpreter: Option<&'i Interpreter>,
}

impl<'f, 'i> Executable<'f, 'i> {
    pub fn new(file: &'f Path, interpreter: Option<&'i Interpreter>)
        -> Executable<'f, 'i>
    {
        Executable {
            file: file,
            interpreter: interpreter,
        }
    }

    pub fn bench(&self, iters: u64) -> u64 {
        let file = self.file;
        let mut command = match self.interpreter {
            None => Command::new(format!("./{}", file.display())),
            Some(interpreter) => Command::new(interpreter.command()),

        };

        let iters = iters.to_str();
        let output = match self.interpreter {
            None => command.arg(iters).output(),
            Some(interpreter) => {
                let flags = interpreter.flags();

                command.args(flags).arg(file).arg(iters).output()
            },
        };

        match output {
            Err(_) => fail!("couldn't find {}", command),
            Ok(output) => if output.status.success() {
                match StrBuf::from_utf8(output.output) {
                    Err(_) => fail!("malformed output"),
                    Ok(string) => match from_str(string.as_slice().trim()) {
                        None => fail!("malformed output"),
                        Some(integer) => integer,
                    },
                }
            } else {
                fail!("{} failed at runtime", file.display())
            },
        }
    }

    pub fn test(&self) -> Option<StrBuf> {
        let file = self.file;
        let mut command = match self.interpreter {
            None => Command::new(format!("./{}", file.display())),
            Some(interpreter) => Command::new(interpreter.command()),

        };

        let output = match self.interpreter {
            None => command.output(),
            Some(interpreter) => {
                command.args(interpreter.flags()).arg(file).output()
            },
        };

        match output {
            Err(_) => {
                println!("Couldn't find the interpreter");

                None
            },
            Ok(output) => if output.status.success() {
                match StrBuf::from_utf8(output.output) {
                    Err(_) => {
                        println!("Bad output");

                        None
                    },
                    Ok(string) => Some(string),
                }
            } else {
                println!("Runtime failure");

                println!("{}", StrBuf::from_utf8(output.error).unwrap());

                None
            },
        }
    }
}
<|endoftext|>


<commit_before>//! Manage SBD messages stored on the fileystem.
//!
//! Messages are stored in a directory hierarchy under a single root directory. Message storage and
//! retrieval are managed by a `Storage` object, which is configured for a single root directory.

use std::fs;
use std::path::{Path, PathBuf};
use std::result;

use glob::{glob, Paths, PatternError};

use super::{Message, Result};

const SBD_EXTENSION: &'static str = ".sbd";

/// A structure for managing storing and retriving SBD messages on a filesystem.
pub struct Storage {
    root: PathBuf,
}

/// An interator over the messages in a `Storage`.
pub struct StorageIterator {
    paths: Option<Paths>,
}

/// The object yielded by a `StorageIterator`.
pub struct StorageEntry {
    pub message: Message,
    pub path_buf: PathBuf,
}

impl Iterator for StorageIterator {
    type Item = StorageEntry;

    fn next(&mut self) -> Option<Self::Item> {
        let mut paths = match self.paths {
            Some(ref mut paths) => paths,
            None => return None,
        };
        loop {
            let glob_result = match paths.next() {
                Some(result) => result,
                None => return None,
            };
            let path_buf = match glob_result {
                Ok(path_buf) => path_buf,
                Err(_) => continue,
            };
            match Message::from_path(&path_buf) {
                Ok(message) => return Some(StorageEntry {
                    message: message,
                    path_buf: path_buf,
                }),
                Err(_) => continue,
            };
        }
    }
}

impl StorageIterator {
    fn new(storage: &Storage) -> StorageIterator {
        let paths = match storage.glob() {
            Ok(paths) => Some(paths),
            Err(_) => None,
        };
        StorageIterator {
            paths: paths,
        }
    }
}

impl<'a> IntoIterator for &'a Storage {
    type Item = StorageEntry;
    type IntoIter = StorageIterator;

    fn into_iter(self) -> Self::IntoIter {
        StorageIterator::new(self)
    }
}

impl Storage {
    /// Creates a new storage manager for a given root directory.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use sbd::filesystem::Storage;
    /// let storage = Storage::new("/var/iridium");
    /// ```
    pub fn new<P: AsRef<Path>>(root: P) -> Storage {
        Storage {
            root: root.as_ref().to_path_buf(),
        }
    }

    /// Stores a message on the filesystem.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use sbd::filesystem::Storage;
    /// use sbd::Message;
    /// let message: Message = Default::default();
    /// let storage = Storage::new("/var/iridium");
    /// storage.store(&message);
    /// ```
    pub fn store(&self, message: &Message) -> Result<PathBuf> {
        let mut path_buf = self.root.clone();
        path_buf.push(message.imei());
        path_buf.push(message.time_of_session().format("%y").to_string());
        path_buf.push(message.time_of_session().format("%m").to_string());
        try!(fs::create_dir_all(&path_buf));
        path_buf.push(message.time_of_session().format(&format!("%y%m%d_%H%M%S{}", SBD_EXTENSION)).to_string());
        let mut file = try!(fs::File::create(&path_buf));
        try!(message.write_to(&mut file));
        Ok(path_buf)
    }

    fn glob(&self) -> result::Result<Paths, PatternError> {
        let mut path_buf = self.root.clone();
        path_buf.push("**");
        path_buf.push(format!("*{}", SBD_EXTENSION));
        glob(&path_buf.to_str().unwrap())
    }
}

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

    use tempdir::TempDir;

    use super::super::Message;

    #[test]
    fn new_storage() {
        Storage::new(TempDir::new("").unwrap().path());
    }

    #[test]
    fn store_message() {
        let storage = Storage::new(TempDir::new("").unwrap().path());
        let message: Message = Default::default();
        let pathbuf = storage.store(&message).unwrap();
        Message::from_path(pathbuf).unwrap();
    }

    #[test]
    fn iterate_over_messages() {
        let storage = Storage::new(TempDir::new("").unwrap().path());
        let message: Message = Default::default();
        storage.store(&message).unwrap();
        let messages = storage.into_iter().collect::<Vec<StorageEntry>>();
        assert_eq!(1, messages.len());
    }
}
<commit_msg>Use full year for file storage<commit_after>//! Manage SBD messages stored on the fileystem.
//!
//! Messages are stored in a directory hierarchy under a single root directory. Message storage and
//! retrieval are managed by a `Storage` object, which is configured for a single root directory.

use std::fs;
use std::path::{Path, PathBuf};
use std::result;

use glob::{glob, Paths, PatternError};

use super::{Message, Result};

const SBD_EXTENSION: &'static str = ".sbd";

/// A structure for managing storing and retriving SBD messages on a filesystem.
pub struct Storage {
    root: PathBuf,
}

/// An interator over the messages in a `Storage`.
pub struct StorageIterator {
    paths: Option<Paths>,
}

/// The object yielded by a `StorageIterator`.
pub struct StorageEntry {
    pub message: Message,
    pub path_buf: PathBuf,
}

impl Iterator for StorageIterator {
    type Item = StorageEntry;

    fn next(&mut self) -> Option<Self::Item> {
        let mut paths = match self.paths {
            Some(ref mut paths) => paths,
            None => return None,
        };
        loop {
            let glob_result = match paths.next() {
                Some(result) => result,
                None => return None,
            };
            let path_buf = match glob_result {
                Ok(path_buf) => path_buf,
                Err(_) => continue,
            };
            match Message::from_path(&path_buf) {
                Ok(message) => return Some(StorageEntry {
                    message: message,
                    path_buf: path_buf,
                }),
                Err(_) => continue,
            };
        }
    }
}

impl StorageIterator {
    fn new(storage: &Storage) -> StorageIterator {
        let paths = match storage.glob() {
            Ok(paths) => Some(paths),
            Err(_) => None,
        };
        StorageIterator {
            paths: paths,
        }
    }
}

impl<'a> IntoIterator for &'a Storage {
    type Item = StorageEntry;
    type IntoIter = StorageIterator;

    fn into_iter(self) -> Self::IntoIter {
        StorageIterator::new(self)
    }
}

impl Storage {
    /// Creates a new storage manager for a given root directory.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use sbd::filesystem::Storage;
    /// let storage = Storage::new("/var/iridium");
    /// ```
    pub fn new<P: AsRef<Path>>(root: P) -> Storage {
        Storage {
            root: root.as_ref().to_path_buf(),
        }
    }

    /// Stores a message on the filesystem.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use sbd::filesystem::Storage;
    /// use sbd::Message;
    /// let message: Message = Default::default();
    /// let storage = Storage::new("/var/iridium");
    /// storage.store(&message);
    /// ```
    pub fn store(&self, message: &Message) -> Result<PathBuf> {
        let mut path_buf = self.root.clone();
        path_buf.push(message.imei());
        path_buf.push(message.time_of_session().format("%Y").to_string());
        path_buf.push(message.time_of_session().format("%m").to_string());
        try!(fs::create_dir_all(&path_buf));
        path_buf.push(message.time_of_session().format(&format!("%y%m%d_%H%M%S{}", SBD_EXTENSION)).to_string());
        let mut file = try!(fs::File::create(&path_buf));
        try!(message.write_to(&mut file));
        Ok(path_buf)
    }

    fn glob(&self) -> result::Result<Paths, PatternError> {
        let mut path_buf = self.root.clone();
        path_buf.push("**");
        path_buf.push(format!("*{}", SBD_EXTENSION));
        glob(&path_buf.to_str().unwrap())
    }
}

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

    use tempdir::TempDir;

    use super::super::Message;

    #[test]
    fn new_storage() {
        Storage::new(TempDir::new("").unwrap().path());
    }

    #[test]
    fn store_message() {
        let storage = Storage::new(TempDir::new("").unwrap().path());
        let message: Message = Default::default();
        let pathbuf = storage.store(&message).unwrap();
        Message::from_path(pathbuf).unwrap();
    }

    #[test]
    fn iterate_over_messages() {
        let storage = Storage::new(TempDir::new("").unwrap().path());
        let message: Message = Default::default();
        storage.store(&message).unwrap();
        let messages = storage.into_iter().collect::<Vec<StorageEntry>>();
        assert_eq!(1, messages.len());
    }
}
<|endoftext|>


<commit_before>/// Represents the players in a Tic-tac-toe game.
#[deriving(Clone, Show)]
pub enum Mark {
  X, O
}

impl Mark {
  /// Returns the opposite mark.
  pub fn opposite(self) -> Mark {
    match self {
      X => O,
      O => X
    }
  }
}

/// Represents a line of the Tic-tac-toe board. A line consists of three cells.
struct PlayLine {
  cells: [Option<Mark>, ..3]
}

impl PlayLine {
  /// Determines if this line counts as a win. Returns the winner wrapped in an
  /// Option, with None meaning that this line is not a winning one.
  pub fn is_win(&self) -> Option<Mark> {
    let (xs, os) = self.cells.iter().fold((0, 0), |(xs, os), &place| {
      match place {
        Some(X) => (xs + 1, os),
        Some(O) => (xs, os + 1),
        None    => (xs, os)
      }
    });
    if xs == 3 {
      Some(X)
    } else if os == 3 {
      Some(O)
    } else {
      None
    }
  }
}

/// Stores the board data associated with a game of Tic-tac-toe.
pub struct PlayField {
  cells: [Option<Mark>, ..9]
}

impl PlayField {
  pub fn new() -> PlayField {
    PlayField {
      cells: [None, ..9]
    }
  }

  /// Returns the number of occupied cells.
  pub fn occupied_count(&self) -> int {
    self.cells.iter().fold(0, |s, mark| if mark.is_some() { s + 1 } else { s })
  }

  /// Returns an iterator over the `PlayLine`s in this field.
  pub fn lines<'a>(&'a self) -> Lines<'a> {
    Lines::from_field(self)
  }

  fn horizontal_line(&self, row: uint) -> Option<PlayLine> {
    PlayField::map_xy(0, row).map(|ix| PlayLine {
      // there's probably a trick to do this with a slice
      cells: [self.cells[ix], self.cells[ix + 1], self.cells[ix + 2]]
    })
  }

  fn vertical_line(&self, col: uint) -> Option<PlayLine> {
    PlayField::map_xy(col, 0).map(|ix| PlayLine {
      cells: [self.cells[ix], self.cells[ix + 3], self.cells[ix + 6]]
    })
  }

  fn ltr_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[0], self.cells[4], self.cells[8]]
    }
  }

  fn rtl_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[2], self.cells[4], self.cells[6]]
    }
  }

  pub fn map_xy(x: uint, y: uint) -> Option<uint> {
    if y < 3 && y < 3 {
      Some(y * 3 + x)
    } else {
      None
    }
  }

  pub fn get_cell_xy(&self, x: uint, y: uint) -> Option<Option<Mark>> {
    PlayField::map_xy(x, y).map(|ix| self.cells[ix])
  }

  pub fn get_mut_cell_xy<'a>(&'a mut self, x: uint, y: uint) -> Option<&'a mut Option<Mark>> {
    match PlayField::map_xy(x, y) {
      Some(ix) => Some(&mut self.cells[ix]),
      None     => None
    }
  }
}

/// Represents an on-screen area where a Tic-tac-toe board can be interacted
/// with.
pub struct FieldArea {
  pub x: int,
  pub y: int,
  pub w: int,
  pub h: int
}

impl FieldArea {
  pub fn from_rect(rect: &::sdl2::rect::Rect) -> FieldArea {
    FieldArea {
      x: rect.x as int, y: rect.y as int,
      w: rect.w as int, h: rect.h as int
    }
  }

  /// Returns the width of an individual cell.
  pub fn cell_width(&self) -> int {
    self.w / 3
  }

  /// Returns the height of an individual cell.
  pub fn cell_height(&self) -> int {
    self.h / 3
  }

  /// Computes the row at a given on-screen Y-coordinate.
  pub fn unproject_row(&self, y: int) -> Option<int> {
    if y >= self.y {
      match (y - self.y) / self.cell_height() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the column at a given on-screen X-coordinate.
  pub fn unproject_col(&self, x: int) -> Option<int> {
    if x >= self.x {
      match (x - self.x) / self.cell_width() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the given row and column given on-screen X and Y coordinates.
  pub fn unproject(&self, x: int, y: int) -> Option<(int, int)> {
    let row = match self.unproject_row(y) {
      Some(row) => row,
      None      => return None
    };
    let col = match self.unproject_col(x) {
      Some(col) => col,
      None      => return None
    };
    Some((row, col))
  }

  /// Computes the on-screen X and Y coordinates for a given row and column.
  pub fn project(&self, row: int, col: int) -> ::sdl2::rect::Point {
    let x = (self.x + col * self.cell_width()) as i32;
    let y = (self.y + row * self.cell_height()) as i32;
    ::sdl2::rect::Point::new(x, y)
  }
}

enum LinesState {
  Row(uint),
  Column(uint),
  LtrDiagonal,
  RtlDiagonal,
  Finished
}

struct Lines<'a> {
  field: &'a PlayField,
  state: LinesState
}

impl<'a> Lines<'a> {
  fn from_field<'a>(f: &'a PlayField) -> Lines<'a> {
    Lines {
      field: f,
      state: Row(0)
    }
  }
}

impl<'a> Iterator<PlayLine> for Lines<'a> {
  fn next(&mut self) -> Option<PlayLine> {
    match self.state {
      Row(place) => {
        self.state = if place + 1 < 3 {
          Row(place + 1)
        } else {
          Column(0)
        };
        self.field.horizontal_line(place)
      },
      Column(place) => {
        self.state = if place + 1 < 3 {
          Column(place + 1)
        } else {
          LtrDiagonal
        };
        self.field.vertical_line(place)
      },
      LtrDiagonal => {
        self.state = RtlDiagonal;
        Some(self.field.ltr_diagonal_line())
      },
      RtlDiagonal => {
        self.state = Finished;
        Some(self.field.rtl_diagonal_line())
      },
      Finished => None
    }
  }
}
<commit_msg>Use integer suffix to comply with latest version of rust<commit_after>/// Represents the players in a Tic-tac-toe game.
#[deriving(Clone, Show)]
pub enum Mark {
  X, O
}

impl Mark {
  /// Returns the opposite mark.
  pub fn opposite(self) -> Mark {
    match self {
      X => O,
      O => X
    }
  }
}

/// Represents a line of the Tic-tac-toe board. A line consists of three cells.
struct PlayLine {
  cells: [Option<Mark>, ..3]
}

impl PlayLine {
  /// Determines if this line counts as a win. Returns the winner wrapped in an
  /// Option, with None meaning that this line is not a winning one.
  pub fn is_win(&self) -> Option<Mark> {
    let (xs, os) = self.cells.iter().fold((0i, 0i), |(xs, os), &place| {
      match place {
        Some(X) => (xs + 1, os),
        Some(O) => (xs, os + 1),
        None    => (xs, os)
      }
    });
    if xs == 3 {
      Some(X)
    } else if os == 3 {
      Some(O)
    } else {
      None
    }
  }
}

/// Stores the board data associated with a game of Tic-tac-toe.
pub struct PlayField {
  cells: [Option<Mark>, ..9]
}

impl PlayField {
  pub fn new() -> PlayField {
    PlayField {
      cells: [None, ..9]
    }
  }

  /// Returns the number of occupied cells.
  pub fn occupied_count(&self) -> int {
    self.cells.iter().fold(0, |s, mark| if mark.is_some() { s + 1 } else { s })
  }

  /// Returns an iterator over the `PlayLine`s in this field.
  pub fn lines<'a>(&'a self) -> Lines<'a> {
    Lines::from_field(self)
  }

  fn horizontal_line(&self, row: uint) -> Option<PlayLine> {
    PlayField::map_xy(0, row).map(|ix| PlayLine {
      // there's probably a trick to do this with a slice
      cells: [self.cells[ix], self.cells[ix + 1], self.cells[ix + 2]]
    })
  }

  fn vertical_line(&self, col: uint) -> Option<PlayLine> {
    PlayField::map_xy(col, 0).map(|ix| PlayLine {
      cells: [self.cells[ix], self.cells[ix + 3], self.cells[ix + 6]]
    })
  }

  fn ltr_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[0], self.cells[4], self.cells[8]]
    }
  }

  fn rtl_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[2], self.cells[4], self.cells[6]]
    }
  }

  pub fn map_xy(x: uint, y: uint) -> Option<uint> {
    if y < 3 && y < 3 {
      Some(y * 3 + x)
    } else {
      None
    }
  }

  pub fn get_cell_xy(&self, x: uint, y: uint) -> Option<Option<Mark>> {
    PlayField::map_xy(x, y).map(|ix| self.cells[ix])
  }

  pub fn get_mut_cell_xy<'a>(&'a mut self, x: uint, y: uint) -> Option<&'a mut Option<Mark>> {
    match PlayField::map_xy(x, y) {
      Some(ix) => Some(&mut self.cells[ix]),
      None     => None
    }
  }
}

/// Represents an on-screen area where a Tic-tac-toe board can be interacted
/// with.
pub struct FieldArea {
  pub x: int,
  pub y: int,
  pub w: int,
  pub h: int
}

impl FieldArea {
  pub fn from_rect(rect: &::sdl2::rect::Rect) -> FieldArea {
    FieldArea {
      x: rect.x as int, y: rect.y as int,
      w: rect.w as int, h: rect.h as int
    }
  }

  /// Returns the width of an individual cell.
  pub fn cell_width(&self) -> int {
    self.w / 3
  }

  /// Returns the height of an individual cell.
  pub fn cell_height(&self) -> int {
    self.h / 3
  }

  /// Computes the row at a given on-screen Y-coordinate.
  pub fn unproject_row(&self, y: int) -> Option<int> {
    if y >= self.y {
      match (y - self.y) / self.cell_height() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the column at a given on-screen X-coordinate.
  pub fn unproject_col(&self, x: int) -> Option<int> {
    if x >= self.x {
      match (x - self.x) / self.cell_width() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the given row and column given on-screen X and Y coordinates.
  pub fn unproject(&self, x: int, y: int) -> Option<(int, int)> {
    let row = match self.unproject_row(y) {
      Some(row) => row,
      None      => return None
    };
    let col = match self.unproject_col(x) {
      Some(col) => col,
      None      => return None
    };
    Some((row, col))
  }

  /// Computes the on-screen X and Y coordinates for a given row and column.
  pub fn project(&self, row: int, col: int) -> ::sdl2::rect::Point {
    let x = (self.x + col * self.cell_width()) as i32;
    let y = (self.y + row * self.cell_height()) as i32;
    ::sdl2::rect::Point::new(x, y)
  }
}

enum LinesState {
  Row(uint),
  Column(uint),
  LtrDiagonal,
  RtlDiagonal,
  Finished
}

struct Lines<'a> {
  field: &'a PlayField,
  state: LinesState
}

impl<'a> Lines<'a> {
  fn from_field<'a>(f: &'a PlayField) -> Lines<'a> {
    Lines {
      field: f,
      state: Row(0)
    }
  }
}

impl<'a> Iterator<PlayLine> for Lines<'a> {
  fn next(&mut self) -> Option<PlayLine> {
    match self.state {
      Row(place) => {
        self.state = if place + 1 < 3 {
          Row(place + 1)
        } else {
          Column(0)
        };
        self.field.horizontal_line(place)
      },
      Column(place) => {
        self.state = if place + 1 < 3 {
          Column(place + 1)
        } else {
          LtrDiagonal
        };
        self.field.vertical_line(place)
      },
      LtrDiagonal => {
        self.state = RtlDiagonal;
        Some(self.field.ltr_diagonal_line())
      },
      RtlDiagonal => {
        self.state = Finished;
        Some(self.field.rtl_diagonal_line())
      },
      Finished => None
    }
  }
}
<|endoftext|>


<commit_before>use game_map::{RoomId, GameMap};
use platform;
use command::{PrimaryCommand, CommandProcessor};

const PAUSE_MS: u64 = 3000;

#[derive(Debug, PartialEq, Copy, Clone)]
enum GameMode {
  AskName,
  Primary,
  Finished,
}

pub struct GameState<'a> {
  map: &'a mut GameMap<'a>,
  curr_mode: GameMode,
  player_name: String,
  curr_room: RoomId,
  show_desc: bool,
}

impl<'a> GameState<'a> {
  pub fn new(map: &'a mut GameMap<'a>) -> Self {
    Self {
      map: map,
      player_name: String::from(""),
      curr_mode: GameMode::AskName,
      curr_room: RoomId::Entrance,
      show_desc: true,
    }
  }

  pub fn is_finished(&self) -> bool {
    self.curr_mode == GameMode::Finished
  }

  pub fn tick_primary_mode(&mut self) {
    if self.show_desc {
      match self.curr_room {
        RoomId::Lift => {
          println!("You have entered the lift...");
          platform::sleep(PAUSE_MS);
          println!("It slowly descends...");
          platform::sleep(PAUSE_MS);
          self.curr_room = RoomId::RearVestibule;
          return;
        },
        RoomId::Exit => {
          println!("\nYou've done it!!");
          platform::sleep(PAUSE_MS);
          println!("That was the exit from the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nYou have succeeded, {}!", self.player_name);
          println!("\nYou managed to get out of the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nWell done!");
          platform::sleep(PAUSE_MS);
          self.curr_mode = GameMode::Finished;
          return;
        },
        _ => {
          platform::writeln_with_wrapping(
            self.map.room(self.curr_room).description
          );
        }
      }
      self.show_desc = false;
    }

    if let Some(cmd) = PrimaryCommand::get() {
      match cmd {
        PrimaryCommand::Go(dir) => {
          if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
            self.curr_room = room;
            self.show_desc = true;
          } else {
            println!("You can't go that way.");
          }
        },
        PrimaryCommand::Look => { self.show_desc = true; }
        PrimaryCommand::Quit => {
          if platform::is_browser() {
            println!("If you want to quit, close your browser.");
          } else {
            self.curr_mode = GameMode::Finished;
          }
        }
      }
    };
  }

  pub fn tick(&mut self) {
    match self.curr_mode {
      GameMode::AskName => {
        platform::show_prompt("What is your name, explorer? ");

        platform::read_input().map(|input| {
          if input.len() == 0 {
            println!("Pardon me?");
          } else {
            self.player_name = input;
            self.curr_mode = GameMode::Primary;
          }
        });
      },
      GameMode::Primary => { self.tick_primary_mode() },
      GameMode::Finished => {}
    }
  }
}
<commit_msg>Change pause time to 2.5s.<commit_after>use game_map::{RoomId, GameMap};
use platform;
use command::{PrimaryCommand, CommandProcessor};

const PAUSE_MS: u64 = 2500;

#[derive(Debug, PartialEq, Copy, Clone)]
enum GameMode {
  AskName,
  Primary,
  Finished,
}

pub struct GameState<'a> {
  map: &'a mut GameMap<'a>,
  curr_mode: GameMode,
  player_name: String,
  curr_room: RoomId,
  show_desc: bool,
}

impl<'a> GameState<'a> {
  pub fn new(map: &'a mut GameMap<'a>) -> Self {
    Self {
      map: map,
      player_name: String::from(""),
      curr_mode: GameMode::AskName,
      curr_room: RoomId::Entrance,
      show_desc: true,
    }
  }

  pub fn is_finished(&self) -> bool {
    self.curr_mode == GameMode::Finished
  }

  pub fn tick_primary_mode(&mut self) {
    if self.show_desc {
      match self.curr_room {
        RoomId::Lift => {
          println!("You have entered the lift...");
          platform::sleep(PAUSE_MS);
          println!("It slowly descends...");
          platform::sleep(PAUSE_MS);
          self.curr_room = RoomId::RearVestibule;
          return;
        },
        RoomId::Exit => {
          println!("\nYou've done it!!");
          platform::sleep(PAUSE_MS);
          println!("That was the exit from the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nYou have succeeded, {}!", self.player_name);
          println!("\nYou managed to get out of the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nWell done!");
          platform::sleep(PAUSE_MS);
          self.curr_mode = GameMode::Finished;
          return;
        },
        _ => {
          platform::writeln_with_wrapping(
            self.map.room(self.curr_room).description
          );
        }
      }
      self.show_desc = false;
    }

    if let Some(cmd) = PrimaryCommand::get() {
      match cmd {
        PrimaryCommand::Go(dir) => {
          if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
            self.curr_room = room;
            self.show_desc = true;
          } else {
            println!("You can't go that way.");
          }
        },
        PrimaryCommand::Look => { self.show_desc = true; }
        PrimaryCommand::Quit => {
          if platform::is_browser() {
            println!("If you want to quit, close your browser.");
          } else {
            self.curr_mode = GameMode::Finished;
          }
        }
      }
    };
  }

  pub fn tick(&mut self) {
    match self.curr_mode {
      GameMode::AskName => {
        platform::show_prompt("What is your name, explorer? ");

        platform::read_input().map(|input| {
          if input.len() == 0 {
            println!("Pardon me?");
          } else {
            self.player_name = input;
            self.curr_mode = GameMode::Primary;
          }
        });
      },
      GameMode::Primary => { self.tick_primary_mode() },
      GameMode::Finished => {}
    }
  }
}
<|endoftext|>


<commit_before>//! Wrapper for an OpenGL buffer object.

use std::cast;
use std::mem;
use std::ptr;
use std::vec;
use gl;
use gl::types::*;
use std::util::NonCopyable;
use gl_primitive::GLPrimitive;

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

struct GLHandle {
    priv handle: GLuint,
    priv nocpy:  NonCopyable
}

impl GLHandle {
    pub fn new(handle: GLuint) -> GLHandle {
        GLHandle {
            handle: handle,
            nocpy:  NonCopyable
        }
    }

    pub fn handle(&self) -> GLuint {
        self.handle
    }
}

impl Drop for GLHandle {
    fn drop(&mut self) {
        unsafe {
            verify!(gl::DeleteBuffers(1, &self.handle))
        }
    }
}

// FIXME: generalize this for any resource: GPUResource
/// A vector of elements that can be loaded to the GPU, on the RAM, or both.
pub struct GPUVector<T> {
    priv len:        uint,
    priv buf_type:   BufferType,
    priv alloc_type: AllocationType,
    priv handle:     Option<GLHandle>,
    priv data:       Option<~[T]>,
}

// FIXME: implement Clone

impl<T: GLPrimitive> GPUVector<T> {
    /// Creates a new `GpuVector` that is not yet uploaded to the GPU.
    pub fn new(data: ~[T], buf_type: BufferType, alloc_type: AllocationType) -> GPUVector<T> {
        GPUVector {
            len:        data.len(),
            buf_type:   buf_type,
            alloc_type: alloc_type,
            handle:     None,
            data:       Some(data)
        }
    }

    /// The length of this vector.
    pub fn len(&self) -> uint {
        self.len
    }

    /// Modifies this vector.
    ///
    /// This will do nothing if the vector os not available on RAM.
    pub fn write(&mut self, f: |&mut ~[T]| -> ()) {
        match self.data {
            None            => { }
            Some(ref mut d) => {
                f(d)
            }
        }

        if self.is_on_gpu() {
            self.reload_to_gpu();
        }
    }

    /// Immutably accesses the vector.
    pub fn read(&self, f: |&[T]| -> ()) {
        match self.data {
            None            => { }
            Some(ref d) => { f(*d) }
        }
    }

    /// Returns `true` if this vector is already uploaded to the GPU.
    pub fn is_on_gpu(&self) -> bool {
        self.handle.is_some()
    }

    /// Retuns `true` if this vector is available on RAM.
    ///
    /// Note that a GPUVector may be both on RAM and on the GPU.
    pub fn is_on_ram(&self) -> bool {
        self.data.is_some()
    }

    /// Loads the vector from the RAM to the GPU.
    ///
    /// If the vector is not available on RAM or already loaded to the GPU, nothing will happen.
    pub fn load_to_gpu(&mut self) {
        if !self.is_on_gpu() {
            self.handle = self.data.as_ref().map(|d| GLHandle::new(
                    upload_buffer(*d, self.buf_type, self.alloc_type)
                )
            );
        }
    }

    fn reload_to_gpu(&mut self) {
        if self.is_on_gpu() {
            let handle = self.handle.as_ref().map(|h| h.handle()).unwrap();

            self.data.as_ref().map(|d| {
                update_buffer(*d, handle, self.buf_type, self.alloc_type)
            });
        }
    }

    /// Binds this vector to gpu buffer and attribute.
    pub fn bind(&mut self, attribute: Option<GLuint>) {
        self.load_to_gpu();

        unsafe {
            let handle = self.handle.as_ref().map(|h| h.handle()).unwrap();
            verify!(gl::BindBuffer(self.buf_type.to_gl(), handle));
            attribute.map(|attr|
                verify!(gl::VertexAttribPointer(
                        attr,
                        GLPrimitive::size(None::<T>) as i32,
                        GLPrimitive::gl_type(None::<T>),
                        gl::FALSE as u8,
                        0,
                        ptr::null())));
        }
    }

    /// Unbind this vector to the corresponding gpu buffer.
    pub fn unbind(&mut self) {
        if self.is_on_gpu() {
            unsafe {
                verify!(gl::BindBuffer(self.buf_type.to_gl(), 0));
            }
        }
    }

    /// Loads the vector from the GPU to the RAM.
    ///
    /// If the vector is not available on the GPU or already loaded to the RAM, nothing will
    /// happen.
    pub fn load_to_ram(&mut self) {
        if !self.is_on_ram() && self.is_on_gpu() {
            let     handle = self.handle.as_ref().map(|h| h.handle()).unwrap();
            let mut data   = vec::with_capacity(self.len);

            unsafe { data.set_len(self.len) };
            download_buffer(handle, self.buf_type, data);
            self.data = Some(data);
        }
    }

    /// Unloads this resourse from the GPU.
    pub fn unload_from_gpu(&mut self) {
        self.handle.as_ref().map(|h| unsafe { verify!(gl::DeleteBuffers(1, &h.handle())) });
        self.handle = None;
    }

    /// Removes this resource from the RAM.
    ///
    /// This is useful to save memory for vectors required on the GPU only.
    pub fn unload_from_ram(&mut self) {
        self.data = None;
    }
}

/// Type of gpu buffer.
pub enum BufferType {
    /// An array buffer bindable to a gl::ARRAY_BUFFER.
    ArrayBuffer,
    /// An array buffer bindable to a gl::ELEMENT_ARRAY_BUFFER.
    ElementArrayBuffer
}

impl BufferType {
    fn to_gl(&self) -> GLuint {
        match *self {
            ArrayBuffer        => gl::ARRAY_BUFFER,
            ElementArrayBuffer => gl::ELEMENT_ARRAY_BUFFER
        }
    }
}

/// Allocation type of gpu buffers.
pub enum AllocationType {
    /// STATIC_DRAW allocation type.
    StaticDraw,
    /// DYNAMIC_DRAW allocation type.
    DynamicDraw,
    /// STREAM_DRAW allocation type.
    StreamDraw
}

impl AllocationType {
    fn to_gl(&self) -> GLuint {
        match *self {
            StaticDraw  => gl::STATIC_DRAW,
            DynamicDraw => gl::DYNAMIC_DRAW,
            StreamDraw  => gl::STREAM_DRAW
        }
    }
}

/// Allocates and uploads a buffer to the gpu.
pub fn upload_buffer<T: GLPrimitive>(buf:             &[T],
                                     buf_type:        BufferType,
                                     allocation_type: AllocationType)
                                     -> GLuint {
    // Upload values of vertices
    let mut buf_id: GLuint = 0;

    unsafe {
        verify!(gl::GenBuffers(1, &mut buf_id));
        update_buffer(buf, buf_id, buf_type, allocation_type);
    }

    buf_id
}

/// Downloads a buffer from the gpu.
///
///
pub fn download_buffer<T: GLPrimitive>(buf_id: GLuint, buf_type: BufferType, out: &mut [T]) {
    unsafe {
        verify!(gl::BindBuffer(buf_type.to_gl(), buf_id));
        verify!(gl::GetBufferSubData(
                buf_type.to_gl(),
                0,
                (out.len() * mem::size_of::<T>()) as GLsizeiptr,
                cast::transmute(&out[0])));
    }
}

/// Updates a buffer to the gpu.
pub fn update_buffer<T: GLPrimitive>(buf:             &[T],
                                     buf_id:          GLuint,
                                     buf_type:        BufferType,
                                     allocation_type: AllocationType) {
    unsafe {
        verify!(gl::BindBuffer(buf_type.to_gl(), buf_id));
        verify!(gl::BufferData(
                buf_type.to_gl(),
                (buf.len() * mem::size_of::<T>()) as GLsizeiptr,
                cast::transmute(&buf[0]),
                allocation_type.to_gl()));
    }
}
<commit_msg>Add a method to transform a GPUVector to a regular vector.<commit_after>//! Wrapper for an OpenGL buffer object.

use std::cast;
use std::mem;
use std::ptr;
use std::vec;
use gl;
use gl::types::*;
use std::util::NonCopyable;
use gl_primitive::GLPrimitive;

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

struct GLHandle {
    priv handle: GLuint,
    priv nocpy:  NonCopyable
}

impl GLHandle {
    pub fn new(handle: GLuint) -> GLHandle {
        GLHandle {
            handle: handle,
            nocpy:  NonCopyable
        }
    }

    pub fn handle(&self) -> GLuint {
        self.handle
    }
}

impl Drop for GLHandle {
    fn drop(&mut self) {
        unsafe {
            verify!(gl::DeleteBuffers(1, &self.handle))
        }
    }
}

// FIXME: generalize this for any resource: GPUResource
/// A vector of elements that can be loaded to the GPU, on the RAM, or both.
pub struct GPUVector<T> {
    priv len:        uint,
    priv buf_type:   BufferType,
    priv alloc_type: AllocationType,
    priv handle:     Option<GLHandle>,
    priv data:       Option<~[T]>,
}

// FIXME: implement Clone

impl<T: GLPrimitive> GPUVector<T> {
    /// Creates a new `GpuVector` that is not yet uploaded to the GPU.
    pub fn new(data: ~[T], buf_type: BufferType, alloc_type: AllocationType) -> GPUVector<T> {
        GPUVector {
            len:        data.len(),
            buf_type:   buf_type,
            alloc_type: alloc_type,
            handle:     None,
            data:       Some(data)
        }
    }

    /// The length of this vector.
    pub fn len(&self) -> uint {
        self.len
    }

    /// Modifies this vector.
    ///
    /// This will do nothing if the vector os not available on RAM.
    pub fn write(&mut self, f: |&mut ~[T]| -> ()) {
        match self.data {
            None            => { }
            Some(ref mut d) => {
                f(d)
            }
        }

        if self.is_on_gpu() {
            self.reload_to_gpu();
        }
    }

    /// Immutably accesses the vector.
    pub fn read(&self, f: |&[T]| -> ()) {
        match self.data {
            None            => { }
            Some(ref d) => { f(*d) }
        }
    }

    /// Returns `true` if this vector is already uploaded to the GPU.
    pub fn is_on_gpu(&self) -> bool {
        self.handle.is_some()
    }

    /// Retuns `true` if this vector is available on RAM.
    ///
    /// Note that a GPUVector may be both on RAM and on the GPU.
    pub fn is_on_ram(&self) -> bool {
        self.data.is_some()
    }

    /// Loads the vector from the RAM to the GPU.
    ///
    /// If the vector is not available on RAM or already loaded to the GPU, nothing will happen.
    pub fn load_to_gpu(&mut self) {
        if !self.is_on_gpu() {
            self.handle = self.data.as_ref().map(|d| GLHandle::new(
                    upload_buffer(*d, self.buf_type, self.alloc_type)
                )
            );
        }
    }

    fn reload_to_gpu(&mut self) {
        if self.is_on_gpu() {
            let handle = self.handle.as_ref().map(|h| h.handle()).unwrap();

            self.data.as_ref().map(|d| {
                update_buffer(*d, handle, self.buf_type, self.alloc_type)
            });
        }
    }

    /// Binds this vector to gpu buffer and attribute.
    pub fn bind(&mut self, attribute: Option<GLuint>) {
        self.load_to_gpu();

        unsafe {
            let handle = self.handle.as_ref().map(|h| h.handle()).unwrap();
            verify!(gl::BindBuffer(self.buf_type.to_gl(), handle));
            attribute.map(|attr|
                verify!(gl::VertexAttribPointer(
                        attr,
                        GLPrimitive::size(None::<T>) as i32,
                        GLPrimitive::gl_type(None::<T>),
                        gl::FALSE as u8,
                        0,
                        ptr::null())));
        }
    }

    /// Unbind this vector to the corresponding gpu buffer.
    pub fn unbind(&mut self) {
        if self.is_on_gpu() {
            unsafe {
                verify!(gl::BindBuffer(self.buf_type.to_gl(), 0));
            }
        }
    }

    /// Loads the vector from the GPU to the RAM.
    ///
    /// If the vector is not available on the GPU or already loaded to the RAM, nothing will
    /// happen.
    pub fn load_to_ram(&mut self) {
        if !self.is_on_ram() && self.is_on_gpu() {
            let     handle = self.handle.as_ref().map(|h| h.handle()).unwrap();
            let mut data   = vec::with_capacity(self.len);

            unsafe { data.set_len(self.len) };
            download_buffer(handle, self.buf_type, data);
            self.data = Some(data);
        }
    }

    /// Unloads this resourse from the GPU.
    pub fn unload_from_gpu(&mut self) {
        self.handle.as_ref().map(|h| unsafe { verify!(gl::DeleteBuffers(1, &h.handle())) });
        self.handle = None;
    }

    /// Removes this resource from the RAM.
    ///
    /// This is useful to save memory for vectors required on the GPU only.
    pub fn unload_from_ram(&mut self) {
        self.data = None;
    }
}

impl<T: Clone + GLPrimitive> GPUVector<T> {
    /// Returns this vector as an owned vector if it is available on RAM.
    ///
    /// If it has been uploaded to the GPU, and unloaded from the RAM, call `load_to_ram` first to
    /// make the data accessible.
    pub fn to_owned(&self) -> Option<~[T]> {
        self.data.as_ref().map(|d| d.clone())
    }
}

/// Type of gpu buffer.
pub enum BufferType {
    /// An array buffer bindable to a gl::ARRAY_BUFFER.
    ArrayBuffer,
    /// An array buffer bindable to a gl::ELEMENT_ARRAY_BUFFER.
    ElementArrayBuffer
}

impl BufferType {
    fn to_gl(&self) -> GLuint {
        match *self {
            ArrayBuffer        => gl::ARRAY_BUFFER,
            ElementArrayBuffer => gl::ELEMENT_ARRAY_BUFFER
        }
    }
}

/// Allocation type of gpu buffers.
pub enum AllocationType {
    /// STATIC_DRAW allocation type.
    StaticDraw,
    /// DYNAMIC_DRAW allocation type.
    DynamicDraw,
    /// STREAM_DRAW allocation type.
    StreamDraw
}

impl AllocationType {
    fn to_gl(&self) -> GLuint {
        match *self {
            StaticDraw  => gl::STATIC_DRAW,
            DynamicDraw => gl::DYNAMIC_DRAW,
            StreamDraw  => gl::STREAM_DRAW
        }
    }
}

/// Allocates and uploads a buffer to the gpu.
pub fn upload_buffer<T: GLPrimitive>(buf:             &[T],
                                     buf_type:        BufferType,
                                     allocation_type: AllocationType)
                                     -> GLuint {
    // Upload values of vertices
    let mut buf_id: GLuint = 0;

    unsafe {
        verify!(gl::GenBuffers(1, &mut buf_id));
        update_buffer(buf, buf_id, buf_type, allocation_type);
    }

    buf_id
}

/// Downloads a buffer from the gpu.
///
///
pub fn download_buffer<T: GLPrimitive>(buf_id: GLuint, buf_type: BufferType, out: &mut [T]) {
    unsafe {
        verify!(gl::BindBuffer(buf_type.to_gl(), buf_id));
        verify!(gl::GetBufferSubData(
                buf_type.to_gl(),
                0,
                (out.len() * mem::size_of::<T>()) as GLsizeiptr,
                cast::transmute(&out[0])));
    }
}

/// Updates a buffer to the gpu.
pub fn update_buffer<T: GLPrimitive>(buf:             &[T],
                                     buf_id:          GLuint,
                                     buf_type:        BufferType,
                                     allocation_type: AllocationType) {
    unsafe {
        verify!(gl::BindBuffer(buf_type.to_gl(), buf_id));
        verify!(gl::BufferData(
                buf_type.to_gl(),
                (buf.len() * mem::size_of::<T>()) as GLsizeiptr,
                cast::transmute(&buf[0]),
                allocation_type.to_gl()));
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use super::utils::{parse_uuid, parse_direction, parse_axis, lock_tree_dbus};

use dbus::tree::MethodErr;

use super::super::layout::{Layout, commands as layout_cmd};

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        match tree.active_id() {
            Some(id) => Ok(id.to_string()),
            None => Ok("".to_string())
        }
    }

    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                let mut tree = try!(lock_tree_dbus());
                tree.toggle_float()
                    .and(Ok(true))
                    .map_err(|err| {
                        MethodErr::failed(&format!("{:?}", err))
                    })
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_active(target_uuid, direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SplitContainer(container_id: String, split_axis: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let axis = try!(parse_axis("split_direction", split_axis.as_str()));
        // TODO Tree commands need to have these defined on the Tree,
        // for now this is _ok_, but we are swallowing an potential Tree lock error here.
        match axis {
            Layout::Horizontal => layout_cmd::split_horizontal(),
            Layout::Vertical => layout_cmd::split_vertical()
        }
        Ok(true)
    }

    fn ToggleCardinalTiling(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.toggle_cardinal_tiling(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SwitchWorkspace(w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        tree.switch_to_workspace(w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn CloseView(view_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("view_id", &view_id))
            .or_else(|| tree.active_id())
            .ok_or(MethodErr::failed(&"No active container")));
        tree.remove_view_by_id(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Focus(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));

        tree.focus(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FocusDir(direction: String) -> success: DBusResult<bool> {
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_focus(direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SendToWorkspace(container_id: String, w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.send_to_workspace(uuid, w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Debug() -> success: DBusResult<String> {
        Ok(format!("{}", layout_cmd::tree_as_json()))
    }
}
<commit_msg>Added ContainerInActiveWorkspace D-Bus cmd<commit_after>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use super::utils::{parse_uuid, parse_direction, parse_axis, lock_tree_dbus};

use dbus::tree::MethodErr;

use super::super::layout::{Layout, commands as layout_cmd};

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        match tree.active_id() {
            Some(id) => Ok(id.to_string()),
            None => Ok("".to_string())
        }
    }

    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                let mut tree = try!(lock_tree_dbus());
                tree.toggle_float()
                    .and(Ok(true))
                    .map_err(|err| {
                        MethodErr::failed(&format!("{:?}", err))
                    })
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_active(target_uuid, direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SplitContainer(container_id: String, split_axis: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let axis = try!(parse_axis("split_direction", split_axis.as_str()));
        // TODO Tree commands need to have these defined on the Tree,
        // for now this is _ok_, but we are swallowing an potential Tree lock error here.
        match axis {
            Layout::Horizontal => layout_cmd::split_horizontal(),
            Layout::Vertical => layout_cmd::split_vertical()
        }
        Ok(true)
    }

    fn ToggleCardinalTiling(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.toggle_cardinal_tiling(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SwitchWorkspace(w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        tree.switch_to_workspace(w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn CloseView(view_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("view_id", &view_id))
            .or_else(|| tree.active_id())
            .ok_or(MethodErr::failed(&"No active container")));
        tree.remove_view_by_id(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Focus(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));

        tree.focus(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FocusDir(direction: String) -> success: DBusResult<bool> {
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_focus(direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SendToWorkspace(container_id: String, w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.send_to_workspace(uuid, w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Debug() -> success: DBusResult<String> {
        Ok(format!("{}", layout_cmd::tree_as_json()))
    }

    fn ContainerInActiveWorkspace(container_id: String) -> success: DBusResult<bool> {
        let tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.container_in_active_workspace(uuid)
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix Outgoing derive missing lifetimes when branching for emitting code<commit_after><|endoftext|>