<commit_before>#![feature(core)]
#![feature(convert)]
#![feature(std_misc)]

use std::ops::Add;
use std::fs::File;
use std::io::{self, Lines, BufReader, BufRead};
use std::iter::{Iterator, Enumerate};
use std::error::{FromError, Error};
use std::convert::AsRef;
use std::path::Path;
use std::fmt::{self, Display, Formatter};

pub trait Limited: Add<u8, Output=Self> + PartialOrd + Copy {
    fn min_value() -> Self;
    fn max_value() -> Self;
}

pub mod interval;
pub mod schedule;
pub mod crontab;

pub struct CrontabFile<T: crontab::ToCrontabEntry> {
    lines: Enumerate<Lines<BufReader<File>>>,
    _marker: std::marker::PhantomData<T>
}

impl<T: crontab::ToCrontabEntry> CrontabFile<T> {
    pub fn new<P: AsRef<Path>>(path: P) -> io::Result<CrontabFile<T>> {
        File::open(path).map(CrontabFile::from_file)
    }

    pub fn from_file(file: File) -> CrontabFile<T> {
        CrontabFile {
            lines: BufReader::new(file).lines().enumerate(),
            _marker: std::marker::PhantomData
        }
    }
}

#[derive(Debug)]
pub enum CrontabFileErrorKind {
    Io(io::Error),
    Parse(crontab::CrontabEntryParseError)
}

#[derive(Debug)]
pub struct CrontabFileError {
    pub lineno: usize,
    pub line: String,
    pub kind: CrontabFileErrorKind
}

impl FromError<io::Error> for CrontabFileError {
    fn from_error(err: io::Error) -> CrontabFileError {
        CrontabFileError {
            lineno: 0,
            line: "".to_string(),
            kind: CrontabFileErrorKind::Io(err)
        }
    }
}

impl FromError<crontab::CrontabEntryParseError> for CrontabFileError {
    fn from_error(err: crontab::CrontabEntryParseError) -> CrontabFileError {
        CrontabFileError {
            lineno: 0,
            line: "".to_string(),
            kind: CrontabFileErrorKind::Parse(err)
        }
    }
}

impl Error for CrontabFileError {
    fn description(&self) -> &str {
        &"error parsing crontab"[..]
    }

    fn cause(&self) -> Option<&Error> {
        // match self.kind {
        //      CrontabFileErrorKind::Parse(ref e) => Some(e as &Error),
        //      CrontabFileErrorKind::Io(ref e) => Some(e as &Error)
        // }
        None
    }
}

impl Display for CrontabFileError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "error parsing crontab at line {} ({:?}): {:?}", self.lineno, self.line, self.kind)
    }
}

impl<T: crontab::ToCrontabEntry> Iterator for CrontabFile<T> {
    type Item = Result<crontab::CrontabEntry, CrontabFileError>;
    fn next(&mut self) -> Option<Result<crontab::CrontabEntry, CrontabFileError>> {
        loop {
            match self.lines.next() {
                Some((lineno, Ok(line))) => {
                    if line.len() == 0 || line.starts_with("#") || line.chars().all(|c| c == ' ' || c == '\t') {
                        continue;
                    }

                    return Some(match line.parse::<crontab::EnvVarEntry>() {
                        Ok(envvar) => Ok(crontab::CrontabEntry::EnvVar(envvar)),
                        _ => line.parse::<T>().map_err(|e| {
                            let mut err: CrontabFileError = FromError::from_error(e);
                            err.lineno = lineno + 1;
                            err.line = line.to_string();
                            err
                        }).map(crontab::ToCrontabEntry::to_crontab_entry)
                    });
                },
                Some((lineno, Err(e))) => {
                    let mut err: CrontabFileError = FromError::from_error(e);
                    err.lineno = lineno + 1;
                    return Some(Err(err));
                },
                None => return None
            }
        }
    }
}

<commit_msg>better error message<commit_after>#![feature(core)]
#![feature(convert)]
#![feature(std_misc)]

use std::ops::Add;
use std::fs::File;
use std::io::{self, Lines, BufReader, BufRead};
use std::iter::{Iterator, Enumerate};
use std::error::{FromError, Error};
use std::convert::AsRef;
use std::path::Path;
use std::fmt::{self, Display, Formatter};

pub trait Limited: Add<u8, Output=Self> + PartialOrd + Copy {
    fn min_value() -> Self;
    fn max_value() -> Self;
}

pub mod interval;
pub mod schedule;
pub mod crontab;

pub struct CrontabFile<T: crontab::ToCrontabEntry> {
    lines: Enumerate<Lines<BufReader<File>>>,
    _marker: std::marker::PhantomData<T>
}

impl<T: crontab::ToCrontabEntry> CrontabFile<T> {
    pub fn new<P: AsRef<Path>>(path: P) -> io::Result<CrontabFile<T>> {
        File::open(path).map(CrontabFile::from_file)
    }

    pub fn from_file(file: File) -> CrontabFile<T> {
        CrontabFile {
            lines: BufReader::new(file).lines().enumerate(),
            _marker: std::marker::PhantomData
        }
    }
}

#[derive(Debug)]
pub enum CrontabFileErrorKind {
    Io(io::Error),
    Parse(crontab::CrontabEntryParseError)
}

impl Display for CrontabFileErrorKind {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            CrontabFileErrorKind::Io(ref e) => e.fmt(f),
            CrontabFileErrorKind::Parse(ref e) => e.fmt(f)
        }
    }
}

#[derive(Debug)]
pub struct CrontabFileError {
    pub lineno: usize,
    pub line: String,
    pub kind: CrontabFileErrorKind
}

impl FromError<io::Error> for CrontabFileError {
    fn from_error(err: io::Error) -> CrontabFileError {
        CrontabFileError {
            lineno: 0,
            line: "".to_string(),
            kind: CrontabFileErrorKind::Io(err)
        }
    }
}

impl FromError<crontab::CrontabEntryParseError> for CrontabFileError {
    fn from_error(err: crontab::CrontabEntryParseError) -> CrontabFileError {
        CrontabFileError {
            lineno: 0,
            line: "".to_string(),
            kind: CrontabFileErrorKind::Parse(err)
        }
    }
}

impl Error for CrontabFileError {
    fn description(&self) -> &str {
        &"error parsing crontab"[..]
    }

    fn cause(&self) -> Option<&Error> {
        // match self.kind {
        //      CrontabFileErrorKind::Parse(ref e) => Some(e as &Error),
        //      CrontabFileErrorKind::Io(ref e) => Some(e as &Error)
        // }
        None
    }
}

impl Display for CrontabFileError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "error parsing crontab at line {} ({:?}): {}", self.lineno, self.line, self.kind)
    }
}

impl<T: crontab::ToCrontabEntry> Iterator for CrontabFile<T> {
    type Item = Result<crontab::CrontabEntry, CrontabFileError>;
    fn next(&mut self) -> Option<Result<crontab::CrontabEntry, CrontabFileError>> {
        loop {
            match self.lines.next() {
                Some((lineno, Ok(line))) => {
                    if line.len() == 0 || line.starts_with("#") || line.chars().all(|c| c == ' ' || c == '\t') {
                        continue;
                    }

                    return Some(match line.parse::<crontab::EnvVarEntry>() {
                        Ok(envvar) => Ok(crontab::CrontabEntry::EnvVar(envvar)),
                        _ => line.parse::<T>().map_err(|e| {
                            let mut err: CrontabFileError = FromError::from_error(e);
                            err.lineno = lineno + 1;
                            err.line = line.to_string();
                            err
                        }).map(crontab::ToCrontabEntry::to_crontab_entry)
                    });
                },
                Some((lineno, Err(e))) => {
                    let mut err: CrontabFileError = FromError::from_error(e);
                    err.lineno = lineno + 1;
                    return Some(Err(err));
                },
                None => return None
            }
        }
    }
}

<|endoftext|>


<commit_before>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#![feature(coerce_unsized)]

#![cfg_attr(feature="clippy", allow(collapsible_if))]
#![cfg_attr(feature="clippy", allow(extend_from_slice))]
#![cfg_attr(feature="clippy", allow(float_cmp))]
#![cfg_attr(feature="clippy", allow(inline_always))]

extern crate libc;
extern crate iup_sys;
extern crate kernel32;
extern crate winapi;
extern crate smallvec;

#[cfg(windows)]
fn get_thread_id() -> isize {
    use kernel32::GetCurrentThreadId;
    unsafe { GetCurrentThreadId() as isize }
}

macro_rules! impl_control_traits {
    ($control:ident) => {
        unsafe impl Control for ::$control {
            fn handle(&self) -> *mut Ihandle {
                assert!(!self.0.get().is_null(), "attempted to use destroyed control");
                ::check_thread();
                self.0.get()
            }
        }

        unsafe impl UnwrapHandle for ::$control {
            fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self> {
                assert!(!self.0.get().is_null(), "attempted to use destroyed control");
                self.0.try_unwrap().map_err(|handle_rc| ::$control(handle_rc))
            }
        }
    };
}

#[macro_use]
mod callbacks;
#[macro_use]
mod containers;

mod control_prelude;

mod alarm_builder;
mod attributes;
mod button;
mod canvas;
mod frame;
mod label;
mod line_graph;
mod list;
mod menu;
mod radio;
mod tabs;
mod text;
mod toggle;
mod dialog;
mod file_dlg;
mod handle_rc;
mod extra_refs;

pub use dialog::{Dialog, ShowCallbackToken, ShowState};
pub use file_dlg::{FileDlg, FileDialogType, FileExtFilter};
pub use alarm_builder::{AlarmResult, AlarmBuilder};
pub use button::Button;
pub use canvas::{Canvas};
pub use frame::Frame;
pub use label::Label;
pub use list::{List, ListActionArgs};
pub use radio::Radio;
pub use tabs::{Tabs, TabInfo};
pub use text::{Text, CaretArgs};
pub use toggle::{Toggle, ToggleState};
pub use menu::{Menu, MenuSubitem, Item, Separator, Submenu};
pub use containers::{Container, NonDialogContainer, Fill, Hbox, Vbox, NumDiv, GridBox};
pub use callbacks::{CallbackAction, Event, ButtonArgs, CanvasActionArgs};

// With this layout, you can glob import this module's contents but selectively import the
// above types if you want.
pub mod common_attrs_cbs {
    pub use attributes::{
        ActiveAttribute,
        CanFocusAttribute,
        Cursor,
        CursorAttribute,
        Expand,
        ExpandAttribute,
        MinMaxSizeAttribute,
        OrientationAttribute,
        ScrollbarAttribute,
        TipAttribute,
        TitleAttribute,
        VisibleAttribute,
        VisibleColumnsLinesAttribute,
    };
    pub use callbacks::{
        MenuCommonCallbacks,
        GetKillFocusCallbacks,
        EnterLeaveWindowCallbacks,
        ButtonCallback,
        ValueChangedCallback,
        MotionArgs,
        WheelArgs,
        CanvasCallbacks,
        ResizeCallback,
    };
}

use std::ptr;
use std::sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
use libc::{c_char, c_int};
use iup_sys::*;

// returns false if a panic is pending, but cannot be propagated because the main loop level is too high
fn propagate_panic() -> bool {
    if callbacks::is_panic_pending() && main_loop_level() > 0 {
        exit_loop();
        return false;
    }
    if let Some(payload) = callbacks::take_panic_payload() {
        // TODO: once a new nightly is released, use this
        //::std::panic::propagate(payload);
        panic!(payload.downcast_ref::<String>().unwrap_or(&String::new()).clone());
    }
    true
}

/// Executes the user interaction until `exit_loop` is called or the last visible dialog is hidden.
///
/// If you cascade many calls to `main_loop`, there must be a `exit_loop` call for each cascade
/// level, as hiding all dialogs will close only one level. Call `main_loop_level` to obtain the
/// current level.
///
/// If `main_loop` is called without any visible dialogs and no active timers, the application will
/// hang, and it will not be possible to close the main loop. The process will have to be
/// interrupted by the system.
///
/// When the last visible dialog is hidden, the `exit_loop` function is automatically called,
/// causing the `main_loop` to return. To avoid that, call `set_lock_loop(true)` before hiding the
/// last dialog.
pub fn main_loop() {
    unsafe {
        iup_open();

        // Callbacks can be called before main_loop() ever is. If they have been and have
        // panicked, we need to panic without calling IupMainLoop(). (IupMainLoopLevel() will
        // be 0 in a callback if it is running before IupMainLoop() has been called.)
        if !propagate_panic() { return; }
        IupMainLoop();
        propagate_panic();
    }
}

/// Returns the current cascade level of `main_loop`.
///
/// When no calls were done, return value is 0. Each time `main_loop` is called, the level
/// increases by one, and each time `main_loop` returns, the level decreases by one. You can use
/// this function to check if `main_loop` was already called and avoid calling it again.
///
/// A call to `Popup::popup` will increase the level by one.
pub fn main_loop_level() -> i32 {
    unsafe {
        IupMainLoopLevel()
    }
}

pub fn exit_loop() {
    unsafe {
        IupExitLoop();
    }
}

/// If this setting is set to false and the last visible dialog is closed, the `exit_loop`
/// function is called.
///
/// To avoid `exit_loop` being called, call `set_lock_loop(true)` before hiding the last dialog.
///
/// The default is false.
pub fn lock_loop() -> bool {
    unsafe {
        attributes::get_str_attribute_slice(ptr::null_mut(), "LOCKLOOP\0") == "YES"
    }
}

/// See `lock_loop`
pub fn set_lock_loop(lock: bool) {
    attributes::set_str_attribute(ptr::null_mut(), "LOCKLOOP\0", if lock { "YES\0" } else { "NO\0" });
}

fn iup_open() {
    check_thread();
    unsafe {
        if IupOpen(ptr::null_mut(), ptr::null_mut()) == IUP_OPENED {
            return;
        }
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE\0", "YES\0");
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE_FILE\0", "YES\0");
    }
}

static THREAD_ID: AtomicIsize = ATOMIC_ISIZE_INIT;

fn check_thread() {
    let thread_id = get_thread_id();
    let prev = THREAD_ID.compare_and_swap(0, thread_id, Ordering::SeqCst);
    assert!(prev == 0 || prev == thread_id, "IUP/Clear Coat functions must be called from a single thread");
}

// Part of the contract of implementing this trait is that no invalid handle
// is returned. Either the handle will stay valid for the life of the object or
// the method will panic.
pub unsafe trait Control {
    fn handle(&self) -> *mut Ihandle;

    /// Warning: Since children are stored as a linked list, detaching a control is O(n) where
    /// n is the number of siblings before this control.
    fn detach(&self) {
        unsafe { IupDetach(self.handle()); }
    }

    fn reparent(&self, new_parent: &Container, ref_child: Option<&Control>) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupReparent(self.handle(), new_parent.handle(), ref_child) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn get_dialog(&self) -> Option<Dialog> {
        unsafe {
            let handle = IupGetDialog(self.handle());
            if handle == ptr::null_mut() {
                None
            } else {
                Some(Dialog::from_handle(handle))
            }
        }
    }

    /// Marks the control to be redrawn on a future main loop iteration.
    fn update(&self) {
        unsafe {
            IupUpdate(self.handle());
        }
    }

    /// Immediately redraws the control and, if `include_children` is `true`, its children as well
    /// (they will be redrawn before this method returns). Usually, it's better to use `update`
    /// because it will batch redraws together, avoiding unnecessary work.
    fn redraw(&self, include_children: bool) {
        unsafe {
            IupRedraw(self.handle(), if include_children { 1 } else { 0 });
        }
    }
}

// If this wrapper has the only reference, it gives up shared ownership of the *mut Ihandle.
pub unsafe trait UnwrapHandle : Sized {
    fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self>;
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ScreenPosition { // This is the name IUP uses: SCREENPOSITION attribute
    Absolute(i32),
    Left,
    Right,
    Top,
    Bottom,
    Center,
    MousePos,
    CenterParent,
    Current,
}

impl ScreenPosition {
    #[allow(dead_code)]
    fn from_int_x(i: c_int) -> ScreenPosition {
       match i {
           IUP_LEFT => ScreenPosition::Left,
           IUP_RIGHT => ScreenPosition::Right,
           IUP_CENTER => ScreenPosition::Center,
           IUP_MOUSEPOS => ScreenPosition::MousePos,
           IUP_CENTERPARENT => ScreenPosition::CenterParent,
           IUP_CURRENT => ScreenPosition::Current,
           _ => ScreenPosition::Absolute(i),
       }
    }

    #[allow(dead_code)]
    fn from_int_y(i: c_int) -> ScreenPosition {
       match i {
           IUP_TOP => ScreenPosition::Top,
           IUP_BOTTOM => ScreenPosition::Bottom,
           _ => Self::from_int_x(i),
       }
    }

    #[cfg_attr(feature="clippy", allow(match_same_arms))]
    fn to_int(self) -> c_int {
        match self {
            ScreenPosition::Absolute(i) => i,
            ScreenPosition::Left => IUP_LEFT,
            ScreenPosition::Right => IUP_RIGHT,
            ScreenPosition::Top => IUP_TOP,
            ScreenPosition::Bottom => IUP_BOTTOM,
            ScreenPosition::Center => IUP_CENTER,
            ScreenPosition::MousePos => IUP_MOUSEPOS,
            ScreenPosition::CenterParent => IUP_CENTERPARENT,
            ScreenPosition::Current => IUP_CURRENT,
        }
    }
}

pub trait Popup : Control {
    fn popup(&self, x: ScreenPosition, y: ScreenPosition) -> Result<(), ()> {
        unsafe {
            if IupPopup(self.handle(), x.to_int(), y.to_int()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }
}

#[derive(Copy,Clone)]
pub enum MouseButton {
    Button1,
    Button2,
    Button3,
    Button4,
    Button5,
}

impl MouseButton {
    fn from_int(i: c_int) -> MouseButton {
        match i {
            IUP_BUTTON1 => MouseButton::Button1,
            IUP_BUTTON2 => MouseButton::Button2,
            IUP_BUTTON3 => MouseButton::Button3,
            IUP_BUTTON4 => MouseButton::Button4,
            IUP_BUTTON5 => MouseButton::Button5,
            _ => panic!("unknown mouse button"),
        }
    }

    #[allow(dead_code)]
    fn to_int(self) -> c_int {
        match self {
            MouseButton::Button1 => IUP_BUTTON1,
            MouseButton::Button2 => IUP_BUTTON2,
            MouseButton::Button3 => IUP_BUTTON3,
            MouseButton::Button4 => IUP_BUTTON4,
            MouseButton::Button5 => IUP_BUTTON5,
        }
    }
}

#[derive(Clone)]
pub struct KeyboardMouseStatus {
    shift_pressed: bool,
    control_pressed: bool,
    alt_pressed: bool,
    sys_pressed: bool,
    button1_pressed: bool,
    button2_pressed: bool,
    button3_pressed: bool,
    button4_pressed: bool,
    button5_pressed: bool,
}

impl KeyboardMouseStatus {
    unsafe fn from_cstr(s: *const c_char) -> KeyboardMouseStatus {
        KeyboardMouseStatus {
            shift_pressed: iup_isshift(s),
            control_pressed: iup_iscontrol(s),
            alt_pressed: iup_isalt(s),
            sys_pressed: iup_issys(s),
            button1_pressed: iup_isbutton1(s),
            button2_pressed: iup_isbutton2(s),
            button3_pressed: iup_isbutton3(s),
            button4_pressed: iup_isbutton4(s),
            button5_pressed: iup_isbutton5(s),
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum VAlignment {
    Top,
    Center,
    Bottom,
}

impl VAlignment {
    fn from_str(s: &[u8]) -> Self {
        match s {
            b"ATOP" => VAlignment::Top,
            b"ACENTER" => VAlignment::Center,
            b"ABOTTOM" => VAlignment::Bottom,
            _ => panic!("unknown VAlignment"),
        }
    }

    fn to_str(self) -> &'static str {
        match self {
            VAlignment::Top => "ATOP\0",
            VAlignment::Center => "ACENTER\0",
            VAlignment::Bottom => "ABOTTOM\0",
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HAlignment {
    Left,
    Center,
    Right,
}

impl HAlignment {
    fn from_str(s: &[u8]) -> Self {
        match s {
            b"ALEFT" => HAlignment::Left,
            b"ACENTER" => HAlignment::Center,
            b"ARIGHT" => HAlignment::Right,
            _ => panic!("unknown HAlignment"),
        }
    }

    fn to_str(self) -> &'static str {
        match self {
            HAlignment::Left => "ALEFT\0",
            HAlignment::Center => "ACENTER\0",
            HAlignment::Right => "ARIGHT\0",
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Orientation {
    Horizontal,
    Vertical,
}

impl Orientation {
    fn from_str(s: &[u8]) -> Self {
        match s {
            b"HORIZONTAL" => Orientation::Horizontal,
            b"VERTICAL" => Orientation::Vertical,
            _ => panic!("unknown Orientation"),
        }
    }

    fn to_str(self) -> &'static str {
        match self {
            Orientation::Horizontal => "HORIZONTAL\0",
            Orientation::Vertical => "VERTICAL\0",
        }
    }
}
<commit_msg>Fix compile error caused by a breaking change to the compiler<commit_after>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#![feature(coerce_unsized)]

#![cfg_attr(feature="clippy", allow(collapsible_if))]
#![cfg_attr(feature="clippy", allow(extend_from_slice))]
#![cfg_attr(feature="clippy", allow(float_cmp))]
#![cfg_attr(feature="clippy", allow(inline_always))]

extern crate libc;
extern crate iup_sys;
extern crate kernel32;
extern crate winapi;
extern crate smallvec;

#[cfg(windows)]
fn get_thread_id() -> isize {
    use kernel32::GetCurrentThreadId;
    unsafe { GetCurrentThreadId() as isize }
}

macro_rules! impl_control_traits {
    ($control:path) => {
        unsafe impl Control for $control {
            fn handle(&self) -> *mut Ihandle {
                assert!(!self.0.get().is_null(), "attempted to use destroyed control");
                ::check_thread();
                self.0.get()
            }
        }

        unsafe impl UnwrapHandle for $control {
            fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self> {
                assert!(!self.0.get().is_null(), "attempted to use destroyed control");
                self.0.try_unwrap().map_err(|handle_rc| $control(handle_rc))
            }
        }
    };
}

#[macro_use]
mod callbacks;
#[macro_use]
mod containers;

mod control_prelude;

mod alarm_builder;
mod attributes;
mod button;
mod canvas;
mod frame;
mod label;
mod line_graph;
mod list;
mod menu;
mod radio;
mod tabs;
mod text;
mod toggle;
mod dialog;
mod file_dlg;
mod handle_rc;
mod extra_refs;

pub use dialog::{Dialog, ShowCallbackToken, ShowState};
pub use file_dlg::{FileDlg, FileDialogType, FileExtFilter};
pub use alarm_builder::{AlarmResult, AlarmBuilder};
pub use button::Button;
pub use canvas::{Canvas};
pub use frame::Frame;
pub use label::Label;
pub use list::{List, ListActionArgs};
pub use radio::Radio;
pub use tabs::{Tabs, TabInfo};
pub use text::{Text, CaretArgs};
pub use toggle::{Toggle, ToggleState};
pub use menu::{Menu, MenuSubitem, Item, Separator, Submenu};
pub use containers::{Container, NonDialogContainer, Fill, Hbox, Vbox, NumDiv, GridBox};
pub use callbacks::{CallbackAction, Event, ButtonArgs, CanvasActionArgs};

// With this layout, you can glob import this module's contents but selectively import the
// above types if you want.
pub mod common_attrs_cbs {
    pub use attributes::{
        ActiveAttribute,
        CanFocusAttribute,
        Cursor,
        CursorAttribute,
        Expand,
        ExpandAttribute,
        MinMaxSizeAttribute,
        OrientationAttribute,
        ScrollbarAttribute,
        TipAttribute,
        TitleAttribute,
        VisibleAttribute,
        VisibleColumnsLinesAttribute,
    };
    pub use callbacks::{
        MenuCommonCallbacks,
        GetKillFocusCallbacks,
        EnterLeaveWindowCallbacks,
        ButtonCallback,
        ValueChangedCallback,
        MotionArgs,
        WheelArgs,
        CanvasCallbacks,
        ResizeCallback,
    };
}

use std::ptr;
use std::sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
use libc::{c_char, c_int};
use iup_sys::*;

// returns false if a panic is pending, but cannot be propagated because the main loop level is too high
fn propagate_panic() -> bool {
    if callbacks::is_panic_pending() && main_loop_level() > 0 {
        exit_loop();
        return false;
    }
    if let Some(payload) = callbacks::take_panic_payload() {
        // TODO: once a new nightly is released, use this
        //::std::panic::propagate(payload);
        panic!(payload.downcast_ref::<String>().unwrap_or(&String::new()).clone());
    }
    true
}

/// Executes the user interaction until `exit_loop` is called or the last visible dialog is hidden.
///
/// If you cascade many calls to `main_loop`, there must be a `exit_loop` call for each cascade
/// level, as hiding all dialogs will close only one level. Call `main_loop_level` to obtain the
/// current level.
///
/// If `main_loop` is called without any visible dialogs and no active timers, the application will
/// hang, and it will not be possible to close the main loop. The process will have to be
/// interrupted by the system.
///
/// When the last visible dialog is hidden, the `exit_loop` function is automatically called,
/// causing the `main_loop` to return. To avoid that, call `set_lock_loop(true)` before hiding the
/// last dialog.
pub fn main_loop() {
    unsafe {
        iup_open();

        // Callbacks can be called before main_loop() ever is. If they have been and have
        // panicked, we need to panic without calling IupMainLoop(). (IupMainLoopLevel() will
        // be 0 in a callback if it is running before IupMainLoop() has been called.)
        if !propagate_panic() { return; }
        IupMainLoop();
        propagate_panic();
    }
}

/// Returns the current cascade level of `main_loop`.
///
/// When no calls were done, return value is 0. Each time `main_loop` is called, the level
/// increases by one, and each time `main_loop` returns, the level decreases by one. You can use
/// this function to check if `main_loop` was already called and avoid calling it again.
///
/// A call to `Popup::popup` will increase the level by one.
pub fn main_loop_level() -> i32 {
    unsafe {
        IupMainLoopLevel()
    }
}

pub fn exit_loop() {
    unsafe {
        IupExitLoop();
    }
}

/// If this setting is set to false and the last visible dialog is closed, the `exit_loop`
/// function is called.
///
/// To avoid `exit_loop` being called, call `set_lock_loop(true)` before hiding the last dialog.
///
/// The default is false.
pub fn lock_loop() -> bool {
    unsafe {
        attributes::get_str_attribute_slice(ptr::null_mut(), "LOCKLOOP\0") == "YES"
    }
}

/// See `lock_loop`
pub fn set_lock_loop(lock: bool) {
    attributes::set_str_attribute(ptr::null_mut(), "LOCKLOOP\0", if lock { "YES\0" } else { "NO\0" });
}

fn iup_open() {
    check_thread();
    unsafe {
        if IupOpen(ptr::null_mut(), ptr::null_mut()) == IUP_OPENED {
            return;
        }
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE\0", "YES\0");
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE_FILE\0", "YES\0");
    }
}

static THREAD_ID: AtomicIsize = ATOMIC_ISIZE_INIT;

fn check_thread() {
    let thread_id = get_thread_id();
    let prev = THREAD_ID.compare_and_swap(0, thread_id, Ordering::SeqCst);
    assert!(prev == 0 || prev == thread_id, "IUP/Clear Coat functions must be called from a single thread");
}

// Part of the contract of implementing this trait is that no invalid handle
// is returned. Either the handle will stay valid for the life of the object or
// the method will panic.
pub unsafe trait Control {
    fn handle(&self) -> *mut Ihandle;

    /// Warning: Since children are stored as a linked list, detaching a control is O(n) where
    /// n is the number of siblings before this control.
    fn detach(&self) {
        unsafe { IupDetach(self.handle()); }
    }

    fn reparent(&self, new_parent: &Container, ref_child: Option<&Control>) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupReparent(self.handle(), new_parent.handle(), ref_child) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn get_dialog(&self) -> Option<Dialog> {
        unsafe {
            let handle = IupGetDialog(self.handle());
            if handle == ptr::null_mut() {
                None
            } else {
                Some(Dialog::from_handle(handle))
            }
        }
    }

    /// Marks the control to be redrawn on a future main loop iteration.
    fn update(&self) {
        unsafe {
            IupUpdate(self.handle());
        }
    }

    /// Immediately redraws the control and, if `include_children` is `true`, its children as well
    /// (they will be redrawn before this method returns). Usually, it's better to use `update`
    /// because it will batch redraws together, avoiding unnecessary work.
    fn redraw(&self, include_children: bool) {
        unsafe {
            IupRedraw(self.handle(), if include_children { 1 } else { 0 });
        }
    }
}

// If this wrapper has the only reference, it gives up shared ownership of the *mut Ihandle.
pub unsafe trait UnwrapHandle : Sized {
    fn try_unwrap_handle(self) -> Result<*mut Ihandle, Self>;
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ScreenPosition { // This is the name IUP uses: SCREENPOSITION attribute
    Absolute(i32),
    Left,
    Right,
    Top,
    Bottom,
    Center,
    MousePos,
    CenterParent,
    Current,
}

impl ScreenPosition {
    #[allow(dead_code)]
    fn from_int_x(i: c_int) -> ScreenPosition {
       match i {
           IUP_LEFT => ScreenPosition::Left,
           IUP_RIGHT => ScreenPosition::Right,
           IUP_CENTER => ScreenPosition::Center,
           IUP_MOUSEPOS => ScreenPosition::MousePos,
           IUP_CENTERPARENT => ScreenPosition::CenterParent,
           IUP_CURRENT => ScreenPosition::Current,
           _ => ScreenPosition::Absolute(i),
       }
    }

    #[allow(dead_code)]
    fn from_int_y(i: c_int) -> ScreenPosition {
       match i {
           IUP_TOP => ScreenPosition::Top,
           IUP_BOTTOM => ScreenPosition::Bottom,
           _ => Self::from_int_x(i),
       }
    }

    #[cfg_attr(feature="clippy", allow(match_same_arms))]
    fn to_int(self) -> c_int {
        match self {
            ScreenPosition::Absolute(i) => i,
            ScreenPosition::Left => IUP_LEFT,
            ScreenPosition::Right => IUP_RIGHT,
            ScreenPosition::Top => IUP_TOP,
            ScreenPosition::Bottom => IUP_BOTTOM,
            ScreenPosition::Center => IUP_CENTER,
            ScreenPosition::MousePos => IUP_MOUSEPOS,
            ScreenPosition::CenterParent => IUP_CENTERPARENT,
            ScreenPosition::Current => IUP_CURRENT,
        }
    }
}

pub trait Popup : Control {
    fn popup(&self, x: ScreenPosition, y: ScreenPosition) -> Result<(), ()> {
        unsafe {
            if IupPopup(self.handle(), x.to_int(), y.to_int()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }
}

#[derive(Copy,Clone)]
pub enum MouseButton {
    Button1,
    Button2,
    Button3,
    Button4,
    Button5,
}

impl MouseButton {
    fn from_int(i: c_int) -> MouseButton {
        match i {
            IUP_BUTTON1 => MouseButton::Button1,
            IUP_BUTTON2 => MouseButton::Button2,
            IUP_BUTTON3 => MouseButton::Button3,
            IUP_BUTTON4 => MouseButton::Button4,
            IUP_BUTTON5 => MouseButton::Button5,
            _ => panic!("unknown mouse button"),
        }
    }

    #[allow(dead_code)]
    fn to_int(self) -> c_int {
        match self {
            MouseButton::Button1 => IUP_BUTTON1,
            MouseButton::Button2 => IUP_BUTTON2,
            MouseButton::Button3 => IUP_BUTTON3,
            MouseButton::Button4 => IUP_BUTTON4,
            MouseButton::Button5 => IUP_BUTTON5,
        }
    }
}

#[derive(Clone)]
pub struct KeyboardMouseStatus {
    shift_pressed: bool,
    control_pressed: bool,
    alt_pressed: bool,
    sys_pressed: bool,
    button1_pressed: bool,
    button2_pressed: bool,
    button3_pressed: bool,
    button4_pressed: bool,
    button5_pressed: bool,
}

impl KeyboardMouseStatus {
    unsafe fn from_cstr(s: *const c_char) -> KeyboardMouseStatus {
        KeyboardMouseStatus {
            shift_pressed: iup_isshift(s),
            control_pressed: iup_iscontrol(s),
            alt_pressed: iup_isalt(s),
            sys_pressed: iup_issys(s),
            button1_pressed: iup_isbutton1(s),
            button2_pressed: iup_isbutton2(s),
            button3_pressed: iup_isbutton3(s),
            button4_pressed: iup_isbutton4(s),
            button5_pressed: iup_isbutton5(s),
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum VAlignment {
    Top,
    Center,
    Bottom,
}

impl VAlignment {
    fn from_str(s: &[u8]) -> Self {
        match s {
            b"ATOP" => VAlignment::Top,
            b"ACENTER" => VAlignment::Center,
            b"ABOTTOM" => VAlignment::Bottom,
            _ => panic!("unknown VAlignment"),
        }
    }

    fn to_str(self) -> &'static str {
        match self {
            VAlignment::Top => "ATOP\0",
            VAlignment::Center => "ACENTER\0",
            VAlignment::Bottom => "ABOTTOM\0",
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HAlignment {
    Left,
    Center,
    Right,
}

impl HAlignment {
    fn from_str(s: &[u8]) -> Self {
        match s {
            b"ALEFT" => HAlignment::Left,
            b"ACENTER" => HAlignment::Center,
            b"ARIGHT" => HAlignment::Right,
            _ => panic!("unknown HAlignment"),
        }
    }

    fn to_str(self) -> &'static str {
        match self {
            HAlignment::Left => "ALEFT\0",
            HAlignment::Center => "ACENTER\0",
            HAlignment::Right => "ARIGHT\0",
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Orientation {
    Horizontal,
    Vertical,
}

impl Orientation {
    fn from_str(s: &[u8]) -> Self {
        match s {
            b"HORIZONTAL" => Orientation::Horizontal,
            b"VERTICAL" => Orientation::Vertical,
            _ => panic!("unknown Orientation"),
        }
    }

    fn to_str(self) -> &'static str {
        match self {
            Orientation::Horizontal => "HORIZONTAL\0",
            Orientation::Vertical => "VERTICAL\0",
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![feature(core)]

//! A GLFW window back-end for the Piston game engine.

extern crate glfw;
extern crate gl;
extern crate window;
extern crate shader_version;
extern crate input;
#[macro_use]
extern crate quack;

use std::sync::mpsc::Receiver;

// External crates.
use std::collections::RingBuf;
use glfw::Context;
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
    Motion,
};
use window::{
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    CaptureCursor, DrawSize, Title,
    ExitOnEsc
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlfwWindow {
    /// The window.
    pub window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    pub glfw: glfw::Glfw,
    event_queue: RingBuf<input::Input>,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
}

impl GlfwWindow {
    /// Create a new game window from an existing GLFW window.
    pub fn from_pieces(mut win: glfw::Window, glfw: glfw::Glfw,
                       events: Receiver<(f64, glfw::WindowEvent)>,
                       exit_on_esc: bool) -> GlfwWindow {
        win.set_all_polling(true);
        win.make_current();
        let title = "<unknown window title, created from_pieces>";
        GlfwWindow {
            window: win,
            events: events,
            glfw: glfw,
            exit_on_esc: exit_on_esc,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: title.to_string(),
        }
    }

    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlfwWindow {
        use glfw::Context;

        // Initialize GLFW.
        let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (major, minor) = opengl.get_major_minor();

        // Make sure we have the right GL version.
        glfw.window_hint(glfw::WindowHint::ContextVersion(major as u32, minor as u32));
        glfw.window_hint(glfw::WindowHint::OpenglForwardCompat(true));
        glfw.window_hint(glfw::WindowHint::OpenglProfile(glfw::OpenGlProfileHint::Core));
        glfw.window_hint(glfw::WindowHint::Samples(settings.samples as u32));

        // Create GLFW window.
        let (mut window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            &settings.title[], glfw::WindowMode::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlfwWindow {
            window: window,
            events: events,
            glfw: glfw,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _)
                if self.exit_on_esc => {
                    self.window.set_should_close(true);
                }
                glfw::WindowEvent::Char(ch) => {
                    self.event_queue.push_back(Input::Text(ch.to_string()));
                }
                glfw::WindowEvent::Key(key, _, glfw::Action::Press, _) => {
                    self.event_queue.push_back(
                        Input::Press(Button::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::WindowEvent::Key(key, _, glfw::Action::Release, _) => {
                    self.event_queue.push_back(
                        Input::Release(Button::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::WindowEvent::MouseButton(button, glfw::Action::Press, _) => {
                    self.event_queue.push_back(
                        Input::Press(Button::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::WindowEvent::MouseButton(button, glfw::Action::Release, _) => {
                    self.event_queue.push_back(
                        Input::Release(Button::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::WindowEvent::CursorPos(x, y) => {
                    self.event_queue.push_back(Input::Move(Motion::MouseCursor(x, y)));
                    match self.last_mouse_pos {
                        Some((lx, ly)) => {
                            self.event_queue.push_back(
                                Input::Move(Motion::MouseRelative(x - lx, y - ly))
                            )
                        }
                        None => {}
                    };
                    self.last_mouse_pos = Some((x, y));
                }
                glfw::WindowEvent::Scroll(x, y) => {
                    self.event_queue.push_back(Input::Move(Motion::MouseScroll(x, y)));
                }
                glfw::WindowEvent::Size(w, h) => {
                    self.event_queue.push_back(Input::Resize(w as u32, h as u32));
                }
                glfw::WindowEvent::Focus(focus) => {
                    self.event_queue.push_back(Input::Focus(focus));
                }
                _ => {}
            }
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front()
        } else {
            None
        }
    }

    fn capture_cursor(&mut self, enabled: bool) {
        if enabled {
            self.window.set_cursor_mode(glfw::CursorMode::Disabled)
        } else {
            self.window.set_cursor_mode(glfw::CursorMode::Normal);
            self.last_mouse_pos = None;
        }
    }
}

quack! {
obj: GlfwWindow[]
get:
    fn () -> Size [] {
        let (w, h) = obj.window.get_size();
        Size([w as u32, h as u32])
    }
    fn () -> ShouldClose [] {
        ShouldClose(obj.window.should_close())
    }
    fn () -> DrawSize [] {
        let (w, h) = obj.window.get_framebuffer_size();
        DrawSize([w as u32, h as u32])
    }
    fn () -> Title [] { Title(obj.title.clone()) }
    fn () -> ExitOnEsc [] { ExitOnEsc(obj.exit_on_esc) }
set:
    fn (val: CaptureCursor) [] { obj.capture_cursor(val.0) }
    fn (val: ShouldClose) [] { obj.window.set_should_close(val.0) }
    fn (val: Title) [] { obj.window.set_title(&val.0[]) }
    fn (val: ExitOnEsc) [] { obj.exit_on_esc = val.0 }
action:
    fn (__: PollEvent) -> Option<Input> [] { obj.poll_event() }
    fn (__: SwapBuffers) -> () [] { obj.window.swap_buffers() }
}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    use input::keyboard::Key;

    match keycode {
        glfw::Key::Num0 => Key::D0,
        glfw::Key::Num1 => Key::D1,
        glfw::Key::Num2 => Key::D2,
        glfw::Key::Num3 => Key::D3,
        glfw::Key::Num4 => Key::D4,
        glfw::Key::Num5 => Key::D5,
        glfw::Key::Num6 => Key::D6,
        glfw::Key::Num7 => Key::D7,
        glfw::Key::Num8 => Key::D8,
        glfw::Key::Num9 => Key::D9,
        glfw::Key::A => Key::A,
        glfw::Key::B => Key::B,
        glfw::Key::C => Key::C,
        glfw::Key::D => Key::D,
        glfw::Key::E => Key::E,
        glfw::Key::F => Key::F,
        glfw::Key::G => Key::G,
        glfw::Key::H => Key::H,
        glfw::Key::I => Key::I,
        glfw::Key::J => Key::J,
        glfw::Key::K => Key::K,
        glfw::Key::L => Key::L,
        glfw::Key::M => Key::M,
        glfw::Key::N => Key::N,
        glfw::Key::O => Key::O,
        glfw::Key::P => Key::P,
        glfw::Key::Q => Key::Q,
        glfw::Key::R => Key::R,
        glfw::Key::S => Key::S,
        glfw::Key::T => Key::T,
        glfw::Key::U => Key::U,
        glfw::Key::V => Key::V,
        glfw::Key::W => Key::W,
        glfw::Key::X => Key::X,
        glfw::Key::Y => Key::Y,
        glfw::Key::Z => Key::Z,
        glfw::Key::Apostrophe => Key::Unknown,
        glfw::Key::Backslash => Key::Backslash,
        glfw::Key::Backspace => Key::Backspace,
        glfw::Key::CapsLock => Key::CapsLock,
        glfw::Key::Delete => Key::Delete,
        glfw::Key::Comma => Key::Comma,
        glfw::Key::Down => Key::Down,
        glfw::Key::End => Key::End,
        glfw::Key::Enter => Key::Return,
        glfw::Key::Equal => Key::Equals,
        glfw::Key::Escape => Key::Escape,
        glfw::Key::F1 => Key::F1,
        glfw::Key::F2 => Key::F2,
        glfw::Key::F3 => Key::F3,
        glfw::Key::F4 => Key::F4,
        glfw::Key::F5 => Key::F5,
        glfw::Key::F6 => Key::F6,
        glfw::Key::F7 => Key::F7,
        glfw::Key::F8 => Key::F8,
        glfw::Key::F9 => Key::F9,
        glfw::Key::F10 => Key::F10,
        glfw::Key::F11 => Key::F11,
        glfw::Key::F12 => Key::F12,
        glfw::Key::F13 => Key::F13,
        glfw::Key::F14 => Key::F14,
        glfw::Key::F15 => Key::F15,
        glfw::Key::F16 => Key::F16,
        glfw::Key::F17 => Key::F17,
        glfw::Key::F18 => Key::F18,
        glfw::Key::F19 => Key::F19,
        glfw::Key::F20 => Key::F20,
        glfw::Key::F21 => Key::F21,
        glfw::Key::F22 => Key::F22,
        glfw::Key::F23 => Key::F23,
        glfw::Key::F24 => Key::F24,
        // Possibly next code.
        glfw::Key::F25 => Key::Unknown,
        glfw::Key::Kp0 => Key::NumPad0,
        glfw::Key::Kp1 => Key::NumPad1,
        glfw::Key::Kp2 => Key::NumPad2,
        glfw::Key::Kp3 => Key::NumPad3,
        glfw::Key::Kp4 => Key::NumPad4,
        glfw::Key::Kp5 => Key::NumPad5,
        glfw::Key::Kp6 => Key::NumPad6,
        glfw::Key::Kp7 => Key::NumPad7,
        glfw::Key::Kp8 => Key::NumPad8,
        glfw::Key::Kp9 => Key::NumPad9,
        glfw::Key::KpDecimal => Key::NumPadDecimal,
        glfw::Key::KpDivide => Key::NumPadDivide,
        glfw::Key::KpMultiply => Key::NumPadMultiply,
        glfw::Key::KpSubtract => Key::NumPadMinus,
        glfw::Key::KpAdd => Key::NumPadPlus,
        glfw::Key::KpEnter => Key::NumPadEnter,
        glfw::Key::KpEqual => Key::NumPadEquals,
        glfw::Key::LeftShift => Key::LShift,
        glfw::Key::LeftControl => Key::LCtrl,
        glfw::Key::LeftAlt => Key::LAlt,
        glfw::Key::LeftSuper => Key::LGui,
        glfw::Key::RightShift => Key::RShift,
        glfw::Key::RightControl => Key::RCtrl,
        glfw::Key::RightAlt => Key::RAlt,
        glfw::Key::RightSuper => Key::RGui,
        // Map to backslash?
        glfw::Key::GraveAccent => Key::Unknown,
        glfw::Key::Home => Key::Home,
        glfw::Key::Insert => Key::Insert,
        glfw::Key::Left => Key::Left,
        glfw::Key::LeftBracket => Key::LeftBracket,
        glfw::Key::Menu => Key::Menu,
        glfw::Key::Minus => Key::Minus,
        glfw::Key::NumLock => Key::NumLockClear,
        glfw::Key::PageDown => Key::PageDown,
        glfw::Key::PageUp => Key::PageUp,
        glfw::Key::Pause => Key::Pause,
        glfw::Key::Period => Key::Period,
        glfw::Key::PrintScreen => Key::PrintScreen,
        glfw::Key::Right => Key::Right,
        glfw::Key::RightBracket => Key::RightBracket,
        glfw::Key::ScrollLock => Key::ScrollLock,
        glfw::Key::Semicolon => Key::Semicolon,
        glfw::Key::Slash => Key::Slash,
        glfw::Key::Space => Key::Space,
        glfw::Key::Tab => Key::Tab,
        glfw::Key::Up => Key::Up,
        glfw::Key::World1 => Key::Unknown,
        glfw::Key::World2 => Key::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> MouseButton {
    match mouse_button {
        glfw::MouseButton::Button1 => MouseButton::Left,
        glfw::MouseButton::Button2 => MouseButton::Right,
        glfw::MouseButton::Button3 => MouseButton::Middle,
        glfw::MouseButton::Button4 => MouseButton::X1,
        glfw::MouseButton::Button5 => MouseButton::X2,
        glfw::MouseButton::Button6 => MouseButton::Button6,
        glfw::MouseButton::Button7 => MouseButton::Button7,
        glfw::MouseButton::Button8 => MouseButton::Button8,
    }
}
<commit_msg>Fix old opengl context init.<commit_after>#![deny(missing_docs)]
#![feature(core)]

//! A GLFW window back-end for the Piston game engine.

extern crate glfw;
extern crate gl;
extern crate window;
extern crate shader_version;
extern crate input;
#[macro_use]
extern crate quack;

use std::sync::mpsc::Receiver;

// External crates.
use std::collections::RingBuf;
use glfw::Context;
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
    Motion,
};
use window::{
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    CaptureCursor, DrawSize, Title,
    ExitOnEsc
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlfwWindow {
    /// The window.
    pub window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    pub glfw: glfw::Glfw,
    event_queue: RingBuf<input::Input>,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
}

impl GlfwWindow {
    /// Create a new game window from an existing GLFW window.
    pub fn from_pieces(mut win: glfw::Window, glfw: glfw::Glfw,
                       events: Receiver<(f64, glfw::WindowEvent)>,
                       exit_on_esc: bool) -> GlfwWindow {
        win.set_all_polling(true);
        win.make_current();
        let title = "<unknown window title, created from_pieces>";
        GlfwWindow {
            window: win,
            events: events,
            glfw: glfw,
            exit_on_esc: exit_on_esc,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: title.to_string(),
        }
    }

    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlfwWindow {
        use glfw::Context;

        // Initialize GLFW.
        let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (major, minor) = opengl.get_major_minor();

        // Make sure we have the right GL version.
        glfw.window_hint(glfw::WindowHint::ContextVersion(major as u32, minor as u32));
        if opengl >= OpenGL::_3_0 {
            glfw.window_hint(glfw::WindowHint::OpenglForwardCompat(true));
        }
        if opengl >= OpenGL::_3_2 {
            glfw.window_hint(glfw::WindowHint::OpenglProfile(glfw::OpenGlProfileHint::Core));
        }
        glfw.window_hint(glfw::WindowHint::Samples(settings.samples as u32));

        // Create GLFW window.
        let (mut window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            &settings.title[], glfw::WindowMode::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlfwWindow {
            window: window,
            events: events,
            glfw: glfw,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _)
                if self.exit_on_esc => {
                    self.window.set_should_close(true);
                }
                glfw::WindowEvent::Char(ch) => {
                    self.event_queue.push_back(Input::Text(ch.to_string()));
                }
                glfw::WindowEvent::Key(key, _, glfw::Action::Press, _) => {
                    self.event_queue.push_back(
                        Input::Press(Button::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::WindowEvent::Key(key, _, glfw::Action::Release, _) => {
                    self.event_queue.push_back(
                        Input::Release(Button::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::WindowEvent::MouseButton(button, glfw::Action::Press, _) => {
                    self.event_queue.push_back(
                        Input::Press(Button::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::WindowEvent::MouseButton(button, glfw::Action::Release, _) => {
                    self.event_queue.push_back(
                        Input::Release(Button::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::WindowEvent::CursorPos(x, y) => {
                    self.event_queue.push_back(Input::Move(Motion::MouseCursor(x, y)));
                    match self.last_mouse_pos {
                        Some((lx, ly)) => {
                            self.event_queue.push_back(
                                Input::Move(Motion::MouseRelative(x - lx, y - ly))
                            )
                        }
                        None => {}
                    };
                    self.last_mouse_pos = Some((x, y));
                }
                glfw::WindowEvent::Scroll(x, y) => {
                    self.event_queue.push_back(Input::Move(Motion::MouseScroll(x, y)));
                }
                glfw::WindowEvent::Size(w, h) => {
                    self.event_queue.push_back(Input::Resize(w as u32, h as u32));
                }
                glfw::WindowEvent::Focus(focus) => {
                    self.event_queue.push_back(Input::Focus(focus));
                }
                _ => {}
            }
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front()
        } else {
            None
        }
    }

    fn capture_cursor(&mut self, enabled: bool) {
        if enabled {
            self.window.set_cursor_mode(glfw::CursorMode::Disabled)
        } else {
            self.window.set_cursor_mode(glfw::CursorMode::Normal);
            self.last_mouse_pos = None;
        }
    }
}

quack! {
obj: GlfwWindow[]
get:
    fn () -> Size [] {
        let (w, h) = obj.window.get_size();
        Size([w as u32, h as u32])
    }
    fn () -> ShouldClose [] {
        ShouldClose(obj.window.should_close())
    }
    fn () -> DrawSize [] {
        let (w, h) = obj.window.get_framebuffer_size();
        DrawSize([w as u32, h as u32])
    }
    fn () -> Title [] { Title(obj.title.clone()) }
    fn () -> ExitOnEsc [] { ExitOnEsc(obj.exit_on_esc) }
set:
    fn (val: CaptureCursor) [] { obj.capture_cursor(val.0) }
    fn (val: ShouldClose) [] { obj.window.set_should_close(val.0) }
    fn (val: Title) [] { obj.window.set_title(&val.0[]) }
    fn (val: ExitOnEsc) [] { obj.exit_on_esc = val.0 }
action:
    fn (__: PollEvent) -> Option<Input> [] { obj.poll_event() }
    fn (__: SwapBuffers) -> () [] { obj.window.swap_buffers() }
}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    use input::keyboard::Key;

    match keycode {
        glfw::Key::Num0 => Key::D0,
        glfw::Key::Num1 => Key::D1,
        glfw::Key::Num2 => Key::D2,
        glfw::Key::Num3 => Key::D3,
        glfw::Key::Num4 => Key::D4,
        glfw::Key::Num5 => Key::D5,
        glfw::Key::Num6 => Key::D6,
        glfw::Key::Num7 => Key::D7,
        glfw::Key::Num8 => Key::D8,
        glfw::Key::Num9 => Key::D9,
        glfw::Key::A => Key::A,
        glfw::Key::B => Key::B,
        glfw::Key::C => Key::C,
        glfw::Key::D => Key::D,
        glfw::Key::E => Key::E,
        glfw::Key::F => Key::F,
        glfw::Key::G => Key::G,
        glfw::Key::H => Key::H,
        glfw::Key::I => Key::I,
        glfw::Key::J => Key::J,
        glfw::Key::K => Key::K,
        glfw::Key::L => Key::L,
        glfw::Key::M => Key::M,
        glfw::Key::N => Key::N,
        glfw::Key::O => Key::O,
        glfw::Key::P => Key::P,
        glfw::Key::Q => Key::Q,
        glfw::Key::R => Key::R,
        glfw::Key::S => Key::S,
        glfw::Key::T => Key::T,
        glfw::Key::U => Key::U,
        glfw::Key::V => Key::V,
        glfw::Key::W => Key::W,
        glfw::Key::X => Key::X,
        glfw::Key::Y => Key::Y,
        glfw::Key::Z => Key::Z,
        glfw::Key::Apostrophe => Key::Unknown,
        glfw::Key::Backslash => Key::Backslash,
        glfw::Key::Backspace => Key::Backspace,
        glfw::Key::CapsLock => Key::CapsLock,
        glfw::Key::Delete => Key::Delete,
        glfw::Key::Comma => Key::Comma,
        glfw::Key::Down => Key::Down,
        glfw::Key::End => Key::End,
        glfw::Key::Enter => Key::Return,
        glfw::Key::Equal => Key::Equals,
        glfw::Key::Escape => Key::Escape,
        glfw::Key::F1 => Key::F1,
        glfw::Key::F2 => Key::F2,
        glfw::Key::F3 => Key::F3,
        glfw::Key::F4 => Key::F4,
        glfw::Key::F5 => Key::F5,
        glfw::Key::F6 => Key::F6,
        glfw::Key::F7 => Key::F7,
        glfw::Key::F8 => Key::F8,
        glfw::Key::F9 => Key::F9,
        glfw::Key::F10 => Key::F10,
        glfw::Key::F11 => Key::F11,
        glfw::Key::F12 => Key::F12,
        glfw::Key::F13 => Key::F13,
        glfw::Key::F14 => Key::F14,
        glfw::Key::F15 => Key::F15,
        glfw::Key::F16 => Key::F16,
        glfw::Key::F17 => Key::F17,
        glfw::Key::F18 => Key::F18,
        glfw::Key::F19 => Key::F19,
        glfw::Key::F20 => Key::F20,
        glfw::Key::F21 => Key::F21,
        glfw::Key::F22 => Key::F22,
        glfw::Key::F23 => Key::F23,
        glfw::Key::F24 => Key::F24,
        // Possibly next code.
        glfw::Key::F25 => Key::Unknown,
        glfw::Key::Kp0 => Key::NumPad0,
        glfw::Key::Kp1 => Key::NumPad1,
        glfw::Key::Kp2 => Key::NumPad2,
        glfw::Key::Kp3 => Key::NumPad3,
        glfw::Key::Kp4 => Key::NumPad4,
        glfw::Key::Kp5 => Key::NumPad5,
        glfw::Key::Kp6 => Key::NumPad6,
        glfw::Key::Kp7 => Key::NumPad7,
        glfw::Key::Kp8 => Key::NumPad8,
        glfw::Key::Kp9 => Key::NumPad9,
        glfw::Key::KpDecimal => Key::NumPadDecimal,
        glfw::Key::KpDivide => Key::NumPadDivide,
        glfw::Key::KpMultiply => Key::NumPadMultiply,
        glfw::Key::KpSubtract => Key::NumPadMinus,
        glfw::Key::KpAdd => Key::NumPadPlus,
        glfw::Key::KpEnter => Key::NumPadEnter,
        glfw::Key::KpEqual => Key::NumPadEquals,
        glfw::Key::LeftShift => Key::LShift,
        glfw::Key::LeftControl => Key::LCtrl,
        glfw::Key::LeftAlt => Key::LAlt,
        glfw::Key::LeftSuper => Key::LGui,
        glfw::Key::RightShift => Key::RShift,
        glfw::Key::RightControl => Key::RCtrl,
        glfw::Key::RightAlt => Key::RAlt,
        glfw::Key::RightSuper => Key::RGui,
        // Map to backslash?
        glfw::Key::GraveAccent => Key::Unknown,
        glfw::Key::Home => Key::Home,
        glfw::Key::Insert => Key::Insert,
        glfw::Key::Left => Key::Left,
        glfw::Key::LeftBracket => Key::LeftBracket,
        glfw::Key::Menu => Key::Menu,
        glfw::Key::Minus => Key::Minus,
        glfw::Key::NumLock => Key::NumLockClear,
        glfw::Key::PageDown => Key::PageDown,
        glfw::Key::PageUp => Key::PageUp,
        glfw::Key::Pause => Key::Pause,
        glfw::Key::Period => Key::Period,
        glfw::Key::PrintScreen => Key::PrintScreen,
        glfw::Key::Right => Key::Right,
        glfw::Key::RightBracket => Key::RightBracket,
        glfw::Key::ScrollLock => Key::ScrollLock,
        glfw::Key::Semicolon => Key::Semicolon,
        glfw::Key::Slash => Key::Slash,
        glfw::Key::Space => Key::Space,
        glfw::Key::Tab => Key::Tab,
        glfw::Key::Up => Key::Up,
        glfw::Key::World1 => Key::Unknown,
        glfw::Key::World2 => Key::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> MouseButton {
    match mouse_button {
        glfw::MouseButton::Button1 => MouseButton::Left,
        glfw::MouseButton::Button2 => MouseButton::Right,
        glfw::MouseButton::Button3 => MouseButton::Middle,
        glfw::MouseButton::Button4 => MouseButton::X1,
        glfw::MouseButton::Button5 => MouseButton::X2,
        glfw::MouseButton::Button6 => MouseButton::Button6,
        glfw::MouseButton::Button7 => MouseButton::Button7,
        glfw::MouseButton::Button8 => MouseButton::Button8,
    }
}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/7853871?s=128", html_favicon_url = "https://avatars0.githubusercontent.com/u/7853871?s=256", html_root_url = "http://ironframework.io/core/router")]
#![crate_id = "router"]
#![license = "MIT"]
#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]
#![feature(phase, globs)]

//! `Router` provides a fast router middleware for the Iron web framework.

extern crate http;
extern crate iron;
extern crate regex;
#[phase(plugin, link)] extern crate log;
#[phase(plugin)] extern crate regex_macros;

#[cfg(test)] extern crate test;

pub use router::Router;
pub use router::params::Params;

mod router;

<commit_msg>(fix) Changed to crate name<commit_after>#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/7853871?s=128", html_favicon_url = "https://avatars0.githubusercontent.com/u/7853871?s=256", html_root_url = "http://ironframework.io/core/router")]
#![crate_name = "router"]
#![license = "MIT"]
#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]
#![feature(phase, globs)]

//! `Router` provides a fast router middleware for the Iron web framework.

extern crate http;
extern crate iron;
extern crate regex;
#[phase(plugin, link)] extern crate log;
#[phase(plugin)] extern crate regex_macros;

#[cfg(test)] extern crate test;

pub use router::Router;
pub use router::params::Params;

mod router;

<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::mem;
use std::ops::{Index, IndexMut};

#[derive(Debug, Copy, Clone)]
pub struct _0;
#[derive(Debug, Copy, Clone)]
pub struct _1;

/// Single type-level bit, `_0` or `_1`.
pub trait Bit { }
impl Bit for _0 { }
impl Bit for _1 { }

/// Nonnegative type-level integer, e.g., `((_1,_0),_1) = 0b101 = 25`.
pub trait Nat {
    fn reify() -> u64;
}
impl Nat for _0 { fn reify() -> u64 { 0 } }
impl Nat for _1 { fn reify() -> u64 { 1 } }
impl<N: Nat> Nat for (N, _0) {
    fn reify() -> u64 { N::reify() << 1 }
}
impl<N: Nat> Nat for (N, _1) {
    fn reify() -> u64 { (N::reify() << 1) | 1 }
}

/// Trait making GenericArray work
pub trait ArrayLength<T> : Nat {
	/// Associated type representing the array type for the number
	type ArrayType;
}

/// Empty array - needed to end recursion
#[allow(dead_code)]
pub struct EmptyArray<T> {
	_marker: PhantomData<T>
}

/// Array with a single element - for _1
#[allow(dead_code)]
pub struct UnitArray<T> {
	data: T
}

impl<T> ArrayLength<T> for _0 {
	type ArrayType = EmptyArray<T>;
}
impl<T> ArrayLength<T> for _1 {
	type ArrayType = UnitArray<T>;
}

#[allow(dead_code)]
pub struct GenericArrayImplEven<T, U> {
	parent1: U,
	parent2: U,
	_marker: PhantomData<T>
}

#[allow(dead_code)]
pub struct GenericArrayImplOdd<T, U> {
	parent1: U,
	parent2: U,
	data: T
}

impl<T, N: ArrayLength<T>> ArrayLength<T> for (N, _0) {
	type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
}

impl<T, N: ArrayLength<T>> ArrayLength<T> for (N, _1) {
	type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
}

#[allow(dead_code)]
pub struct GenericArray<T, U: ArrayLength<T>> {
	data: U::ArrayType
}

impl<T, N> Index<usize> for GenericArray<T, N> where N: ArrayLength<T> {
	type Output = T;

	fn index(&self, i: usize) -> &T {
		assert!(i < N::reify() as usize);
		let p: *const T = self as *const GenericArray<T, N> as *const T;
		unsafe { &*p.offset(i as isize) }
	}
}

impl<T, N> IndexMut<usize> for GenericArray<T, N> where N: ArrayLength<T> {

	fn index_mut(&mut self, i: usize) -> &mut T {
		assert!(i < N::reify() as usize);
		let p: *mut T = self as *mut GenericArray<T, N> as *mut T;
		unsafe { &mut *p.offset(i as isize) }
	}
}

impl<T: Clone, N> GenericArray<T, N> where N: ArrayLength<T> {

	pub fn new() -> GenericArray<T, N> {
		unsafe { mem::zeroed() }
	}

	pub fn new_list(list: &[T]) -> GenericArray<T, N> {
		assert_eq!(list.len(), N::reify() as usize);
		let mut res = GenericArray::new();
		for i in 0..N::reify() as usize {
			res[i] = list[i].clone();
		}
		res
	}

}

#[cfg(test)]
mod test {
	use super::{_0, _1, GenericArray};

	type P97 = ((((((_1, _1), _0), _0), _0), _0), _1);

	#[test]
	fn test() {
		let mut list97 = [0; 97];
		for i in 0..97 {
			list97[i] = i as i32;
		}
	    let l : GenericArray<i32, P97> = GenericArray::new_list(&list97);
	    assert_eq!(l[0], 0);
	    assert_eq!(l[1], 1);
	    assert_eq!(l[32], 32);
	    assert_eq!(l[56], 56);
	}
}<commit_msg>Mark ArrayLength as an unsafe trait to prevent users from erroneously implementing it<commit_after>use std::marker::PhantomData;
use std::mem;
use std::ops::{Index, IndexMut};

#[derive(Debug, Copy, Clone)]
pub struct _0;
#[derive(Debug, Copy, Clone)]
pub struct _1;

/// Single type-level bit, `_0` or `_1`.
pub trait Bit { }
impl Bit for _0 { }
impl Bit for _1 { }

/// Nonnegative type-level integer, e.g., `((_1,_0),_1) = 0b101 = 25`.
pub trait Nat {
    fn reify() -> u64;
}
impl Nat for _0 { fn reify() -> u64 { 0 } }
impl Nat for _1 { fn reify() -> u64 { 1 } }
impl<N: Nat> Nat for (N, _0) {
    fn reify() -> u64 { N::reify() << 1 }
}
impl<N: Nat> Nat for (N, _1) {
    fn reify() -> u64 { (N::reify() << 1) | 1 }
}

/// Trait making GenericArray work
pub unsafe trait ArrayLength<T> : Nat {
	/// Associated type representing the array type for the number
	type ArrayType;
}

/// Empty array - needed to end recursion
#[allow(dead_code)]
pub struct EmptyArray<T> {
	_marker: PhantomData<T>
}

/// Array with a single element - for _1
#[allow(dead_code)]
pub struct UnitArray<T> {
	data: T
}

unsafe impl<T> ArrayLength<T> for _0 {
	type ArrayType = EmptyArray<T>;
}
unsafe impl<T> ArrayLength<T> for _1 {
	type ArrayType = UnitArray<T>;
}

#[allow(dead_code)]
pub struct GenericArrayImplEven<T, U> {
	parent1: U,
	parent2: U,
	_marker: PhantomData<T>
}

#[allow(dead_code)]
pub struct GenericArrayImplOdd<T, U> {
	parent1: U,
	parent2: U,
	data: T
}

unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for (N, _0) {
	type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
}

unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for (N, _1) {
	type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
}

#[allow(dead_code)]
pub struct GenericArray<T, U: ArrayLength<T>> {
	data: U::ArrayType
}

impl<T, N> Index<usize> for GenericArray<T, N> where N: ArrayLength<T> {
	type Output = T;

	fn index(&self, i: usize) -> &T {
		assert!(i < N::reify() as usize);
		let p: *const T = self as *const GenericArray<T, N> as *const T;
		unsafe { &*p.offset(i as isize) }
	}
}

impl<T, N> IndexMut<usize> for GenericArray<T, N> where N: ArrayLength<T> {

	fn index_mut(&mut self, i: usize) -> &mut T {
		assert!(i < N::reify() as usize);
		let p: *mut T = self as *mut GenericArray<T, N> as *mut T;
		unsafe { &mut *p.offset(i as isize) }
	}
}

impl<T: Clone, N> GenericArray<T, N> where N: ArrayLength<T> {

	pub fn new() -> GenericArray<T, N> {
		unsafe { mem::zeroed() }
	}

	pub fn new_list(list: &[T]) -> GenericArray<T, N> {
		assert_eq!(list.len(), N::reify() as usize);
		let mut res = GenericArray::new();
		for i in 0..N::reify() as usize {
			res[i] = list[i].clone();
		}
		res
	}

}

#[cfg(test)]
mod test {
	use super::{_0, _1, GenericArray};

	type P97 = ((((((_1, _1), _0), _0), _0), _0), _1);

	#[test]
	fn test() {
		let mut list97 = [0; 97];
		for i in 0..97 {
			list97[i] = i as i32;
		}
	    let l : GenericArray<i32, P97> = GenericArray::new_list(&list97);
	    assert_eq!(l[0], 0);
	    assert_eq!(l[1], 1);
	    assert_eq!(l[32], 32);
	    assert_eq!(l[56], 56);
	}
}
<|endoftext|>


<commit_before>extern crate libc;

mod ffi;

use ffi::*;
use libc::c_char;
use std::ffi::*;

/// Result of opening a file dialog
pub enum NFDResult {
    /// User pressed okay. `String` is the file path selected
    Okay(String),
    /// User pressed cancel
    Cancel,
    /// Program error. `String` is the error description
    Error(String),
}

enum DialogType {
    SingleFile,
    SaveFile
}

/// Open single file dialog
#[inline(always)]
pub fn open_file_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SingleFile)
}

/// Open save dialog
#[inline(always)]
pub fn open_save_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SaveFile)
}

fn open_dialog(filter_list: Option<&str>, default_path: Option<&str>, dialog_type: &DialogType) -> NFDResult {
    let result: nfdresult_t;
    let result_cstring;

    let filter_list_cstring;
    let filter_list_ptr = match filter_list {
        Some(fl_str) => {
            filter_list_cstring = CString::new(fl_str).unwrap();
            filter_list_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let default_path_cstring;
    let default_path_ptr = match default_path {
        Some(dp_str) => {
            default_path_cstring = CString::new(dp_str).unwrap();
            default_path_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let out_path = CString::new("").unwrap().into_raw() as *mut *mut c_char;

    unsafe {
        result = match dialog_type {
            &DialogType::SingleFile => {
                NFD_OpenDialog(filter_list_ptr, default_path_ptr, out_path)
            },

            &DialogType::SaveFile => {
                NFD_SaveDialog(filter_list_ptr, default_path_ptr, out_path)
            },
        };

        result_cstring = match result {
            nfdresult_t::NFD_OKAY => CString::from_raw(*out_path),
            nfdresult_t::NFD_ERROR => CStr::from_ptr(NFD_GetError()).to_owned(),
            _ => CString::new("").unwrap()
        }
    }

    let result_string = result_cstring.to_str().unwrap().to_string();

    match result {
        nfdresult_t::NFD_OKAY => NFDResult::Okay(result_string),
        nfdresult_t::NFD_CANCEL => NFDResult::Cancel,
        nfdresult_t::NFD_ERROR => NFDResult::Error(result_string)
    }
}
<commit_msg>Improve memory usage Avoid unnecessary allocation of an empty string. Fix a memory leak resulting from not calling CString::from_raw in case of NFD_CANCEL or NFD_ERROR.<commit_after>extern crate libc;

mod ffi;

use ffi::*;
use libc::c_char;
use std::ffi::*;

/// Result of opening a file dialog
pub enum NFDResult {
    /// User pressed okay. `String` is the file path selected
    Okay(String),
    /// User pressed cancel
    Cancel,
    /// Program error. `String` is the error description
    Error(String),
}

enum DialogType {
    SingleFile,
    SaveFile
}

/// Open single file dialog
#[inline(always)]
pub fn open_file_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SingleFile)
}

/// Open save dialog
#[inline(always)]
pub fn open_save_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SaveFile)
}

fn open_dialog(filter_list: Option<&str>, default_path: Option<&str>, dialog_type: &DialogType) -> NFDResult {
    let result: nfdresult_t;
    let result_cstring;

    let filter_list_cstring;
    let filter_list_ptr = match filter_list {
        Some(fl_str) => {
            filter_list_cstring = CString::new(fl_str).unwrap();
            filter_list_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let default_path_cstring;
    let default_path_ptr = match default_path {
        Some(dp_str) => {
            default_path_cstring = CString::new(dp_str).unwrap();
            default_path_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let mut out_path: *mut c_char = std::ptr::null_mut();
    let ptr_out_path = &mut out_path as *mut *mut c_char;

    unsafe {
        result = match dialog_type {
            &DialogType::SingleFile => {
                NFD_OpenDialog(filter_list_ptr, default_path_ptr, ptr_out_path)
            },

            &DialogType::SaveFile => {
                NFD_SaveDialog(filter_list_ptr, default_path_ptr, ptr_out_path)
            },
        };

        result_cstring = match result {
            nfdresult_t::NFD_OKAY => CStr::from_ptr(out_path).to_owned(),
            nfdresult_t::NFD_ERROR => CStr::from_ptr(NFD_GetError()).to_owned(),
            _ => CString::new("").unwrap()
        }
    }

    let result_string = result_cstring.to_str().unwrap().to_string();

    match result {
        nfdresult_t::NFD_OKAY => NFDResult::Okay(result_string),
        nfdresult_t::NFD_CANCEL => NFDResult::Cancel,
        nfdresult_t::NFD_ERROR => NFDResult::Error(result_string)
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate chrono;
extern crate rustc_serialize;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;
mod builder;

use chrono::{DateTime, UTC};
use chrono::format::ParseError as ChronoParseError;
use std::collections::BTreeMap;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

#[derive(Clone, Debug, PartialEq)]
pub enum Plist {
	Array(Vec<Plist>),
	Dictionary(BTreeMap<String, Plist>),
	Boolean(bool),
	Data(Vec<u8>),
	Date(DateTime<UTC>),
	Real(f64),
	Integer(i64),
	String(String)
}

use rustc_serialize::base64::{STANDARD, ToBase64};
use rustc_serialize::json::Json as RustcJson;

impl Plist {
	pub fn from_events<T>(events: T) -> Result<Plist, ()>
		where T: IntoIterator<Item = ReadResult<PlistEvent>>
	{
		let iter = events.into_iter();
		let builder = builder::Builder::new(iter);

		match builder.build() {
			Ok(plist) => Ok(plist),
			Err(_) => Err(())
		}
	}

	pub fn into_events(self) -> Vec<PlistEvent> {
		let mut events = Vec::new();
		self.into_events_inner(&mut events);
		events
	}

	fn into_events_inner(self, events: &mut Vec<PlistEvent>) {
		match self {
			Plist::Array(array) => {
				events.push(PlistEvent::StartArray(Some(array.len() as u64)));
				for value in array.into_iter() {
					value.into_events_inner(events);
				}
				events.push(PlistEvent::EndArray);
			},
			Plist::Dictionary(dict) => {
				events.push(PlistEvent::StartDictionary(Some(dict.len() as u64)));
				for (key, value) in dict.into_iter() {
					events.push(PlistEvent::StringValue(key));
					value.into_events_inner(events);
				}
				events.push(PlistEvent::EndDictionary);
			},
			Plist::Boolean(value) => events.push(PlistEvent::BooleanValue(value)),
			Plist::Data(value) => events.push(PlistEvent::DataValue(value)),
			Plist::Date(value) => events.push(PlistEvent::DateValue(value)),
			Plist::Real(value) => events.push(PlistEvent::RealValue(value)),
			Plist::Integer(value) => events.push(PlistEvent::IntegerValue(value)),
			Plist::String(value) => events.push(PlistEvent::StringValue(value)),
		}
	}

	pub fn into_rustc_serialize_json(self) -> RustcJson {
		match self {
			Plist::Array(value) => RustcJson::Array(value.into_iter().map(|p| p.into_rustc_serialize_json()).collect()),
			Plist::Dictionary(value) => RustcJson::Object(value.into_iter().map(|(k, v)| (k, v.into_rustc_serialize_json())).collect()),
			Plist::Boolean(value) => RustcJson::Boolean(value),
			Plist::Data(value) => RustcJson::String(value.to_base64(STANDARD)),
			Plist::Date(value) => RustcJson::String(value.to_rfc3339()),
			Plist::Real(value) => RustcJson::F64(value),
			Plist::Integer(value) => RustcJson::I64(value),
			Plist::String(value) => RustcJson::String(value),
		}
	}
}

#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
	StartPlist,
	EndPlist,

	StartArray(Option<u64>),
	EndArray,

	StartDictionary(Option<u64>),
	EndDictionary,

	BooleanValue(bool),
	DataValue(Vec<u8>),
	DateValue(DateTime<UTC>),
	IntegerValue(i64),
	RealValue(f64),
	StringValue(String),
}

pub type ReadResult<T> = Result<T, ReadError>;

#[derive(Debug)]
pub enum ReadError {
	InvalidData,
	UnexpectedEof,
	UnsupportedType,
	Io(IoError)
}

impl From<IoError> for ReadError {
	fn from(io_error: IoError) -> ReadError {
		ReadError::Io(io_error)
	}
}

impl From<ChronoParseError> for ReadError {
	fn from(_: ChronoParseError) -> ReadError {
		ReadError::InvalidData
	}
}

pub enum EventReader<R: Read+Seek> {
	Xml(xml::EventReader<R>),
	Binary(binary::EventReader<R>)
}

impl<R: Read+Seek> EventReader<R> {
	pub fn new(mut reader: R) -> EventReader<R> {
		match EventReader::is_binary(&mut reader) {
			Ok(true) => EventReader::Binary(binary::EventReader::new(reader)),
			Ok(false) | Err(_) => EventReader::Xml(xml::EventReader::new(reader))
		}
	}

	fn is_binary(reader: &mut R) -> Result<bool, IoError> {
		try!(reader.seek(SeekFrom::Start(0)));
		let mut magic = [0; 8];
		try!(reader.read(&mut magic));
		try!(reader.seek(SeekFrom::Start(0)));

		Ok(if &magic == b"bplist00" {
			true
		} else {
			false
		})
	}
}

impl<R: Read+Seek> Iterator for EventReader<R> {
	type Item = ReadResult<PlistEvent>;

	fn next(&mut self) -> Option<ReadResult<PlistEvent>> {
		match *self {
			EventReader::Xml(ref mut parser) => parser.next(),
			EventReader::Binary(ref mut parser) => parser.next()
		}
	}
}<commit_msg>EventReader lazy initialization<commit_after>extern crate byteorder;
extern crate chrono;
extern crate rustc_serialize;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;
mod builder;

use chrono::{DateTime, UTC};
use chrono::format::ParseError as ChronoParseError;
use std::collections::BTreeMap;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

#[derive(Clone, Debug, PartialEq)]
pub enum Plist {
	Array(Vec<Plist>),
	Dictionary(BTreeMap<String, Plist>),
	Boolean(bool),
	Data(Vec<u8>),
	Date(DateTime<UTC>),
	Real(f64),
	Integer(i64),
	String(String)
}

use rustc_serialize::base64::{STANDARD, ToBase64};
use rustc_serialize::json::Json as RustcJson;

impl Plist {
	pub fn from_events<T>(events: T) -> Result<Plist, ()>
		where T: IntoIterator<Item = ReadResult<PlistEvent>>
	{
		let iter = events.into_iter();
		let builder = builder::Builder::new(iter);

		match builder.build() {
			Ok(plist) => Ok(plist),
			Err(_) => Err(())
		}
	}

	pub fn into_events(self) -> Vec<PlistEvent> {
		let mut events = Vec::new();
		self.into_events_inner(&mut events);
		events
	}

	fn into_events_inner(self, events: &mut Vec<PlistEvent>) {
		match self {
			Plist::Array(array) => {
				events.push(PlistEvent::StartArray(Some(array.len() as u64)));
				for value in array.into_iter() {
					value.into_events_inner(events);
				}
				events.push(PlistEvent::EndArray);
			},
			Plist::Dictionary(dict) => {
				events.push(PlistEvent::StartDictionary(Some(dict.len() as u64)));
				for (key, value) in dict.into_iter() {
					events.push(PlistEvent::StringValue(key));
					value.into_events_inner(events);
				}
				events.push(PlistEvent::EndDictionary);
			},
			Plist::Boolean(value) => events.push(PlistEvent::BooleanValue(value)),
			Plist::Data(value) => events.push(PlistEvent::DataValue(value)),
			Plist::Date(value) => events.push(PlistEvent::DateValue(value)),
			Plist::Real(value) => events.push(PlistEvent::RealValue(value)),
			Plist::Integer(value) => events.push(PlistEvent::IntegerValue(value)),
			Plist::String(value) => events.push(PlistEvent::StringValue(value)),
		}
	}

	pub fn into_rustc_serialize_json(self) -> RustcJson {
		match self {
			Plist::Array(value) => RustcJson::Array(value.into_iter().map(|p| p.into_rustc_serialize_json()).collect()),
			Plist::Dictionary(value) => RustcJson::Object(value.into_iter().map(|(k, v)| (k, v.into_rustc_serialize_json())).collect()),
			Plist::Boolean(value) => RustcJson::Boolean(value),
			Plist::Data(value) => RustcJson::String(value.to_base64(STANDARD)),
			Plist::Date(value) => RustcJson::String(value.to_rfc3339()),
			Plist::Real(value) => RustcJson::F64(value),
			Plist::Integer(value) => RustcJson::I64(value),
			Plist::String(value) => RustcJson::String(value),
		}
	}
}

#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
	StartPlist,
	EndPlist,

	StartArray(Option<u64>),
	EndArray,

	StartDictionary(Option<u64>),
	EndDictionary,

	BooleanValue(bool),
	DataValue(Vec<u8>),
	DateValue(DateTime<UTC>),
	IntegerValue(i64),
	RealValue(f64),
	StringValue(String),
}

pub type ReadResult<T> = Result<T, ReadError>;

#[derive(Debug)]
pub enum ReadError {
	InvalidData,
	UnexpectedEof,
	UnsupportedType,
	Io(IoError)
}

impl From<IoError> for ReadError {
	fn from(io_error: IoError) -> ReadError {
		ReadError::Io(io_error)
	}
}

impl From<ChronoParseError> for ReadError {
	fn from(_: ChronoParseError) -> ReadError {
		ReadError::InvalidData
	}
}

pub enum EventReader<R: Read+Seek> {
	Uninitialized(Option<R>),
	Xml(xml::EventReader<R>),
	Binary(binary::EventReader<R>)
}

impl<R: Read+Seek> EventReader<R> {
	pub fn new(reader: R) -> EventReader<R> {
		EventReader::Uninitialized(Some(reader))
	}

	fn is_binary(reader: &mut R) -> Result<bool, IoError> {
		try!(reader.seek(SeekFrom::Start(0)));
		let mut magic = [0; 8];
		try!(reader.read(&mut magic));
		try!(reader.seek(SeekFrom::Start(0)));

		Ok(if &magic == b"bplist00" {
			true
		} else {
			false
		})
	}
}

impl<R: Read+Seek> Iterator for EventReader<R> {
	type Item = ReadResult<PlistEvent>;

	fn next(&mut self) -> Option<ReadResult<PlistEvent>> {
		let mut reader = match *self {
			EventReader::Xml(ref mut parser) => return parser.next(),
			EventReader::Binary(ref mut parser) => return parser.next(),
			EventReader::Uninitialized(ref mut reader) => reader.take().unwrap()
		};

		let event_reader = match EventReader::is_binary(&mut reader) {
			Ok(true) => EventReader::Binary(binary::EventReader::new(reader)),
			Ok(false) => EventReader::Xml(xml::EventReader::new(reader)),
			Err(err) => {
				::std::mem::replace(self, EventReader::Uninitialized(Some(reader)));
				return Some(Err(ReadError::Io(err)))
			}
		};

		::std::mem::replace(self, event_reader);

		self.next()
	}
}<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate rand;
extern crate time;

#[derive(Debug)]
pub struct CohortResult<T: Clone> {
    duration: f64,
    result: T
}

impl<T: Clone> CohortResult<T> {
    pub fn new(duration: f64, result: &T) -> Self {
        CohortResult {
            duration: duration,
            result: result.clone()
        }
    }
}

#[derive(Debug)]
pub struct ExperimentResult<CurrentT: Clone, NewT: Clone> {
    current: CohortResult<CurrentT>,
    new: CohortResult<NewT>,
    name: &'static str
}

impl<CurrentT: Clone, NewT: Clone> ExperimentResult<CurrentT, NewT> {
    pub fn new(current: CohortResult<CurrentT>, new: CohortResult<NewT>, name: &'static str) -> Self {
        ExperimentResult {
            current: current,
            new: new,
            name: name
        }
    }
}

#[macro_export]
macro_rules! experiment {
    ($dexter_type:ident, $name:expr, current:$current:block new:$new:block) => {
        {
            use rand::{thread_rng, Rng};
            use time::{precise_time_ns};

            let mut rng = thread_rng();
            let mut did_one = false;
            let current_goes_first: bool = rng.gen();
            let mut current_val = None;
            let mut new_val = None;
            let mut current_duration = 0;
            let mut new_duration = 0;
            loop {
                if (current_goes_first || did_one) && !(current_goes_first && did_one) {
                    let start = precise_time_ns();
                    current_val = Some($current);
                    current_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
                if (!current_goes_first || did_one) && !(!current_goes_first && did_one) {
                    let start = precise_time_ns();
                    new_val = Some($new);
                    new_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
            }
            $dexter_type::publish(ExperimentResult::new(
                CohortResult::new(current_duration as f64 * 1e-9, &current_val.as_ref().unwrap()),
                CohortResult::new(new_duration as f64 * 1e-9, &new_val.as_ref().unwrap()),
                $name
            ));
            current_val.unwrap()
        }
    }
}

pub trait Dexter<CurrentT: Clone, NewT: Clone> {
    fn publish(_: ExperimentResult<CurrentT, NewT>) {}
}

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

    impl Dexter<String, String> for TestExperiment {
        fn publish(result: ExperimentResult<String, String>) {
            println!("{:?}", result);
        }
    }

    #[test]
    fn it_works() {
        let a = experiment!{
            TestExperiment,
            "experiment!",
            current: {
                println!("current went!");
                "current result".to_string()
            }
            new: {
                println!("new went!");
                "new result".to_string()
            }
        };
        println!("{}", a);
    }
}
<commit_msg>Added internal module to make additional dependencies unnecessary<commit_after>#![allow(dead_code)]
extern crate rand;
extern crate time;

#[derive(Debug)]
pub struct CohortResult<T: Clone> {
    duration: f64,
    result: T
}

impl<T: Clone> CohortResult<T> {
    pub fn new(duration: f64, result: &T) -> Self {
        CohortResult {
            duration: duration,
            result: result.clone()
        }
    }
}

#[derive(Debug)]
pub struct ExperimentResult<CurrentT: Clone, NewT: Clone> {
    current: CohortResult<CurrentT>,
    new: CohortResult<NewT>,
    name: &'static str
}

impl<CurrentT: Clone, NewT: Clone> ExperimentResult<CurrentT, NewT> {
    pub fn new(current: CohortResult<CurrentT>, new: CohortResult<NewT>, name: &'static str) -> Self {
        ExperimentResult {
            current: current,
            new: new,
            name: name
        }
    }
}

#[macro_export]
macro_rules! experiment {
    ($dexter_type:ident, $name:expr, current:$current:block new:$new:block) => {
        {
            use $crate::internal::rand::{thread_rng, Rng};
            use $crate::internal::time::{precise_time_ns};

            let mut rng = thread_rng();
            let mut did_one = false;
            let current_goes_first: bool = rng.gen();
            let mut current_val = None;
            let mut new_val = None;
            let mut current_duration = 0;
            let mut new_duration = 0;
            loop {
                if (current_goes_first || did_one) && !(current_goes_first && did_one) {
                    let start = precise_time_ns();
                    current_val = Some($current);
                    current_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
                if (!current_goes_first || did_one) && !(!current_goes_first && did_one) {
                    let start = precise_time_ns();
                    new_val = Some($new);
                    new_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
            }
            $dexter_type::publish(ExperimentResult::new(
                CohortResult::new(current_duration as f64 * 1e-9, &current_val.as_ref().unwrap()),
                CohortResult::new(new_duration as f64 * 1e-9, &new_val.as_ref().unwrap()),
                $name
            ));
            current_val.unwrap()
        }
    }
}

pub trait Dexter<CurrentT: Clone, NewT: Clone> {
    fn publish(_: ExperimentResult<CurrentT, NewT>) {}
}

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

    impl Dexter<String, String> for TestExperiment {
        fn publish(result: ExperimentResult<String, String>) {
            println!("{:?}", result);
        }
    }

    #[test]
    fn it_works() {
        let a = experiment!{
            TestExperiment,
            "experiment!",
            current: {
                println!("current went!");
                "current result".to_string()
            }
            new: {
                println!("new went!");
                "new result".to_string()
            }
        };
        println!("{}", a);
    }
}

#[doc(hidden)]
mod internal {
    pub use rand;
    pub use time;
}
<|endoftext|>


<commit_before>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, fn_traits, specialization, never_type)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]

extern crate rand;
extern crate nalgebra;
extern crate siphasher;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate crossbeam;
#[macro_use]
extern crate quickcheck;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  #[macro_use]
  pub mod list_of_types;
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

mod deterministic_random_id;
pub use deterministic_random_id::*;
#[macro_use]
mod api;
#[macro_use]
mod api_macros;
pub use api::*;
pub use implementation_support::list_of_types::{ColumnType, EventType, PredictorType};

#[macro_use]
pub mod stewards {
  pub mod inefficient_flat;
  pub mod memoized_flat;
  pub mod amortized;

  pub mod flat_to_inefficient_full;
  pub mod crossverified;
  pub mod simply_synchronized;
}

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod collision_detection;
}
<commit_msg>Add commented-out references to unfinished modules<commit_after>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, fn_traits, specialization, never_type)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]

extern crate rand;
extern crate nalgebra;
extern crate siphasher;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate crossbeam;
#[macro_use]
extern crate quickcheck;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  #[macro_use]
  pub mod list_of_types;
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;
#[macro_use]
mod api;
#[macro_use]
mod api_macros;
pub use api::*;
pub use implementation_support::list_of_types::{ColumnType, EventType, PredictorType};

#[macro_use]
pub mod stewards {
  pub mod inefficient_flat;
  pub mod memoized_flat;
  pub mod amortized;
  //pub mod optimized;

  pub mod flat_to_inefficient_full;
  pub mod crossverified;
  pub mod simply_synchronized;
}

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod collision_detection;
}
<|endoftext|>