<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)]

extern crate libc;
extern crate iup_sys;
extern crate kernel32;

#[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() != ptr::null_mut(), "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() != ptr::null_mut(), "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 attributes;
mod button;
mod dialog;
mod handle_rc;

pub use dialog::{Dialog};
pub use button::Button;
pub use containers::{Container, Fill, Hbox, Vbox};
pub use callbacks::{CallbackAction, Event};

// 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::{CommonAttributes, TitleAttribute};
    pub use callbacks::{MenuCommonCallbacks, NonMenuCommonCallbacks, ButtonCallback};
}

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

pub fn main_loop() {
    unsafe {
        iup_open();
        IupMainLoop();
    }
}

fn iup_open() {
    check_thread();
    unsafe { IupOpen(ptr::null_mut(), ptr::null_mut()); }
}

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;

    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))
            }
        }
    }
}

// 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),
       }
    }

    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),
        }
    }
}
<commit_msg>Turn on IUP's UTF-8 support<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)]

extern crate libc;
extern crate iup_sys;
extern crate kernel32;

#[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() != ptr::null_mut(), "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() != ptr::null_mut(), "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 attributes;
mod button;
mod dialog;
mod handle_rc;

pub use dialog::{Dialog};
pub use button::Button;
pub use containers::{Container, Fill, Hbox, Vbox};
pub use callbacks::{CallbackAction, Event};

// 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::{CommonAttributes, TitleAttribute};
    pub use callbacks::{MenuCommonCallbacks, NonMenuCommonCallbacks, ButtonCallback};
}

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

pub fn main_loop() {
    unsafe {
        iup_open();
        IupMainLoop();
    }
}

fn iup_open() {
    check_thread();
    unsafe {
        IupOpen(ptr::null_mut(), ptr::null_mut());
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE", "YES");
        attributes::set_str_attribute(ptr::null_mut(), "UTF8MODE_FILE", "YES");
    }
}

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;

    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))
            }
        }
    }
}

// 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),
       }
    }

    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),
        }
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

pub mod requests;

#[cfg(test)]
mod test {
    use super::requests;
    use hyper::status::StatusCode;

    #[test]
    fn test_get() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_post() {
        const URL: &'static str = "http://httpbin.org/post";
        let res = requests::post(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_put() {
        const URL: &'static str = "http://httpbin.org/put";
        let res = requests::put(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_head() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::head(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_detele() {
        const URL: &'static str = "http://httpbin.org/delete";
        let res = requests::delete(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }
}
<commit_msg>Fix type in test name<commit_after>extern crate hyper;

pub mod requests;

#[cfg(test)]
mod test {
    use super::requests;
    use hyper::status::StatusCode;

    #[test]
    fn test_get() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_post() {
        const URL: &'static str = "http://httpbin.org/post";
        let res = requests::post(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_put() {
        const URL: &'static str = "http://httpbin.org/put";
        let res = requests::put(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_head() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::head(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_delete() {
        const URL: &'static str = "http://httpbin.org/delete";
        let res = requests::delete(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! The Elision term rewriting library.
//!
//! Elision is a custom term rewriter intended for use in analyzing
//! and computing the behavior of compiled software.  Elision is
//! Turing complete.

// Tell the documentation system about some icons and require
// documentation.  Enable core.
#![doc(html_logo_url = "https://raw.githubusercontent.com/relision/things/master/graphics/relision.png",
	html_favicon_url = "https://raw.githubusercontent.com/relision/things/master/graphics/favicon.ico",
	html_root_url = "https://github.com/relision")]
#![warn(missing_docs)]

extern crate num;

/* Load platform specific definitions. */

mod win32;
mod linux;
mod macos;
mod terms;

#[cfg(target_os = "linux")]
use linux::os_spec;
#[cfg(target_os = "win32")]
use win32::os_spec;
#[cfg(target_os = "macos")]
use macos::os_spec;
#[cfg(not(any(target_os = "macos",
              target_os = "win32",
              target_os = "linux")))]
use linux::os_spec;

use std::path::Path;

/// Get the name of the platform on which this was built.
pub fn get_platform() -> &'static str {
	os_spec::tos()
}

/// Get the configuration folder.  This creates it if it does not exist.
pub fn get_config_dir() -> String {
	let location = os_spec::get_config_dir();
    //Introduce a scope so `location` can be reused.
    {
        let path = Path::new(&location);
        match std::fs::create_dir_all(&path) {
		    Ok(_) => {},
		    Err(error) => {
			    panic!("Failed to create configuration folder: {}", error);
		    }
	    };
    }

	return location;
}

<commit_msg>Got rid of an uneeded Path::new() because String is AsPath<commit_after>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! The Elision term rewriting library.
//!
//! Elision is a custom term rewriter intended for use in analyzing
//! and computing the behavior of compiled software.  Elision is
//! Turing complete.

// Tell the documentation system about some icons and require
// documentation.  Enable core.
#![doc(html_logo_url = "https://raw.githubusercontent.com/relision/things/master/graphics/relision.png",
	html_favicon_url = "https://raw.githubusercontent.com/relision/things/master/graphics/favicon.ico",
	html_root_url = "https://github.com/relision")]
#![warn(missing_docs)]

extern crate num;

/* Load platform specific definitions. */

mod win32;
mod linux;
mod macos;
mod terms;

#[cfg(target_os = "linux")]
use linux::os_spec;
#[cfg(target_os = "win32")]
use win32::os_spec;
#[cfg(target_os = "macos")]
use macos::os_spec;
#[cfg(not(any(target_os = "macos",
              target_os = "win32",
              target_os = "linux")))]
use linux::os_spec;

use std::path::Path;

/// Get the name of the platform on which this was built.
pub fn get_platform() -> &'static str {
	os_spec::tos()
}

/// Get the configuration folder.  This creates it if it does not exist.
pub fn get_config_dir() -> String {
    let location = os_spec::get_config_dir();
    match std::fs::create_dir_all(&location) {
        Ok(_) => {},
        Err(error) => {
            panic!("Failed to create configuration folder: {}", error);
		}
	};

	return location;
}

<|endoftext|>


<commit_before>extern crate toml;

// Import traits
use std::io::prelude::Read;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

pub fn test() {
    println!("Hello from lib.rs");
}

#[derive(Debug)]
enum OnSuccess {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum OnFailure {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum Step {
    Echo {name: String, string: String},
    Run {name: String, command: String, arguments: String, on_success: OnSuccess, on_failure: OnFailure},
    Shell,
    SetEnv,
}

fn parse_toml(filename: &str) -> Vec<Step> {

    println!("Reading toml file {}", filename);

    // Read toml file content
    let mut input = String::new();
    std::fs::File::open(&filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();

    // Pase toml file
    let mut parser = toml::Parser::new(&input);

    let toml = parser.parse().unwrap_or_else(|| {
        for err in &parser.errors {
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            println!("{}:{}:{}-{}:{} error: {}",
                     filename, loline, locol, hiline, hicol, err.desc);
        }
        panic!("Error parsing toml file.");
    });

    // println!("toml: {:#?}", toml);
    println!("toml: {:?}", toml.len());

    // Parse "on" table
    // unimplemented!();

    // Parse "variables" table
    // unimplemented!();

    // Parse "steps" table
    let mut steps = Vec::<Step>::with_capacity(10);

    for step in toml.get("step").unwrap().as_slice().unwrap() {
        let action = step.as_table().unwrap().get("action").unwrap().as_str().unwrap();
        let name = step.as_table().unwrap().get("name").unwrap().as_str().unwrap().to_string();
        let details = step.as_table().unwrap().get("details").unwrap().as_table().unwrap();
        let step = match action {
            "echo" => {
                let string = details.get("string").unwrap().as_str().unwrap().to_string();
                Step::Echo {name: name, string: string}
            },
            "run" => {
                let command = details.get("command").unwrap().as_str().unwrap().to_string();
                let arguments = details.get("arguments").unwrap().as_str().unwrap().to_string();

                let on_success = match details.get("on_success") {
                    None => {
                        println!("WARNING: No 'on_success' set for {:?}, default of 'OnSuccess::Continue'", name);
                        OnSuccess::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnSuccess::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnSuccess::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                let on_failure = match details.get("on_failure") {
                    None => {
                        println!("WARNING: No 'on_failure' set for {:?}, default of 'OnFailure::Continue'", name);
                        OnFailure::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnFailure::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnFailure::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                Step::Run {name: name, command: command, arguments: arguments, on_success: on_success, on_failure: on_failure}
            },
            // "shell" => {
            // },
            // "setenv" => {
            // },
            _ => {
                println!("Unknown action '{}' in toml file", action);
                unimplemented!();
            },
        };
        println!("Step: {:?}", step);

        steps.push(step);
    }

    steps
}

pub fn execute_steps(filename: &str) {

    let steps = parse_toml(filename);

    println!("Steps: {:#?}", steps);
}
<commit_msg>Cleanups<commit_after>extern crate toml;

// Import traits
use std::io::prelude::Read;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

pub fn test() {
    println!("Hello from lib.rs");
}

#[derive(Debug)]
enum OnSuccess {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum OnFailure {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum Step {
    Echo {name: String, string: String},
    Run {name: String, command: String, arguments: String, on_success: OnSuccess, on_failure: OnFailure},
    Shell,
    SetEnv,
}

fn parse_toml(filename: &str) -> Vec<Step> {

    println!("Reading toml file {}", filename);

    // Read toml file content
    let mut input = String::new();
    std::fs::File::open(&filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();

    // Pase toml file
    let mut parser = toml::Parser::new(&input);

    let toml = parser.parse().unwrap_or_else(|| {
        for err in &parser.errors {
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            println!("{}:{}:{}-{}:{} error: {}",
                     filename, loline, locol, hiline, hicol, err.desc);
        }
        panic!("Error parsing toml file.");
    });

    // println!("toml: {:#?}", toml);

    // Parse "variables" table
    // unimplemented!();

    // Parse "steps" table
    let mut steps = Vec::<Step>::with_capacity(10);

    for step in toml.get("step").unwrap().as_slice().unwrap() {
        let action = step.as_table().unwrap().get("action").unwrap().as_str().unwrap();
        let name = step.as_table().unwrap().get("name").unwrap().as_str().unwrap().to_string();
        let details = step.as_table().unwrap().get("details").unwrap().as_table().unwrap();
        let step = match action {
            "echo" => {
                let string = details.get("string").unwrap().as_str().unwrap().to_string();
                Step::Echo {name: name, string: string}
            },
            "run" => {
                let command = details.get("command").unwrap().as_str().unwrap().to_string();
                let arguments = details.get("arguments").unwrap().as_str().unwrap().to_string();

                let on_success = match details.get("on_success") {
                    None => {
                        println!("WARNING: No 'on_success' set for {:?}, default of 'OnSuccess::Continue'", name);
                        OnSuccess::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnSuccess::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnSuccess::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                let on_failure = match details.get("on_failure") {
                    None => {
                        println!("WARNING: No 'on_failure' set for {:?}, default of 'OnFailure::Continue'", name);
                        OnFailure::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnFailure::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnFailure::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                Step::Run {name: name, command: command, arguments: arguments, on_success: on_success, on_failure: on_failure}
            },
            // "shell" => {
            // },
            // "setenv" => {
            // },
            _ => {
                println!("Unknown action '{}' in toml file", action);
                unimplemented!();
            },
        };
        // println!("Step: {:?}", step);

        steps.push(step);
    }

    steps
}

pub fn execute_steps(filename: &str) {

    let steps = parse_toml(filename);

    println!("Steps: {:#?}", steps);
}
<|endoftext|>


<commit_before>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//! This crate implements
//! the
//! [generic cell rate algorithm](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm) (GCRA)
//! for rate-limiting and scheduling in Rust.
//!
//! ## Interface
//!
//! There is currently one rate limiter implementation in this crate,
//! the Generic Cell Rate Algorithm. Use it by creating a builder from
//! the [`GCRA`](struct.GCRA.html) struct:
//!
//! ``` rust
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build(); // Construct a non-threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Whenever possible, additional
//! information about why a cell should be denied - the `GCRA`
//! implementation will return a `time::Instant` alongside the decision to
//! allow callers to e.g. provide better error messages to users.
//!
//! Due to this, the `ratelimit_meter` crate does not provide any facility
//! to wait until a cell would be allowed - if you require this, you
//! should use the `Instant` returned with negative decisions and wait
//! in your own, e.g. event loop.
//!
//! ## Rate-limiting Algorithms
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also, the
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more consise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! None of the stateful implementations in this crate can be used
//! across threads by default. However, there is a wrapper struct
//! [`Threadsafe`](algorithms/struct.Threadsafe.html), that wraps each
//! implementation's hot path in an atomically reference-counted
//! mutex. It still manages to be pretty fast (see the benchmarks
//! above), but the lock comes with an overhead even in
//! single-threaded operation.
//!
//! Example:
//!
//! ```
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build_sync(); // Construct a threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```

pub mod example_algorithms;
pub mod errors;
pub mod algorithms;
mod implementation;

#[macro_use]
extern crate error_chain;

use std::time::{Instant};

pub use errors::*;
pub use self::algorithms::*;
use implementation::*;

#[derive(PartialEq, Debug)]
/// A decision on a single cell from the metered rate-limiter.
pub enum Decision<T> {
    /// The cell is conforming, allow it through.
    Yes,

    /// The cell is non-conforming. A rate-limiting algorithm
    /// implementation may return additional information for the
    /// caller, e.g. a time when the cell was expected to arrive.
    No(T),
}

impl<T> Decision<T> {
    /// Check if a decision on a cell indicates the cell is compliant
    /// or not. Returns `true` iff the cell was compliant, i.e. the
    /// decision was `Decision::Yes`.
    ///
    /// Note: This method is mostly useful in tests.
    pub fn is_compliant(&self) -> bool {
        match self {
            &Decision::Yes => true,
            &Decision::No(_) => false,
        }
    }
}

/// A prerequisite for implementing any Decider trait. It provides the
/// associated type for [`Decision`](enum.Decision.html)'s additional
/// information for negative decisions.
pub trait TypedDecider {
    /// The type for additional information on negative decisions.
    type T;
}

/// The main decision trait. It allows checking a single cell against
/// the rate-limiter, either at the current time instant, or at a
/// given instant in time, both destructively.
pub trait Decider: DeciderImpl {
    /// Tests if a single cell can be accomodated at
    /// `Instant::now()`. See [`check_at`](#method.check_at).
    fn check(&mut self) -> Result<Decision<Self::T>> {
        self.test_and_update(Instant::now())
    }

    /// Tests is a single cell can be accomodated at the given time
    /// stamp.
    fn check_at(&mut self, at: Instant) -> Result<Decision<Self::T>> {
        self.test_and_update(at)
    }
}

pub trait MultiDecider: MultiDeciderImpl {
    /// Tests if `n` cells can be accomodated at the given time
    /// stamp. An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n_at(&mut self, n: u32, at: Instant) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, at)
    }

    /// Tests if `n` cells can be accomodated at the current time
    /// (`Instant::now()`). An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n(&mut self, n: u32) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, Instant::now())
    }
}
<commit_msg>Clippy: Dereference expression, avoid & on all patterns.<commit_after>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//! This crate implements
//! the
//! [generic cell rate algorithm](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm) (GCRA)
//! for rate-limiting and scheduling in Rust.
//!
//! ## Interface
//!
//! There is currently one rate limiter implementation in this crate,
//! the Generic Cell Rate Algorithm. Use it by creating a builder from
//! the [`GCRA`](struct.GCRA.html) struct:
//!
//! ``` rust
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build(); // Construct a non-threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Whenever possible, additional
//! information about why a cell should be denied - the `GCRA`
//! implementation will return a `time::Instant` alongside the decision to
//! allow callers to e.g. provide better error messages to users.
//!
//! Due to this, the `ratelimit_meter` crate does not provide any facility
//! to wait until a cell would be allowed - if you require this, you
//! should use the `Instant` returned with negative decisions and wait
//! in your own, e.g. event loop.
//!
//! ## Rate-limiting Algorithms
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also, the
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more consise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! None of the stateful implementations in this crate can be used
//! across threads by default. However, there is a wrapper struct
//! [`Threadsafe`](algorithms/struct.Threadsafe.html), that wraps each
//! implementation's hot path in an atomically reference-counted
//! mutex. It still manages to be pretty fast (see the benchmarks
//! above), but the lock comes with an overhead even in
//! single-threaded operation.
//!
//! Example:
//!
//! ```
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build_sync(); // Construct a threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```

pub mod example_algorithms;
pub mod errors;
pub mod algorithms;
mod implementation;

#[macro_use]
extern crate error_chain;

use std::time::{Instant};

pub use errors::*;
pub use self::algorithms::*;
use implementation::*;

#[derive(PartialEq, Debug)]
/// A decision on a single cell from the metered rate-limiter.
pub enum Decision<T> {
    /// The cell is conforming, allow it through.
    Yes,

    /// The cell is non-conforming. A rate-limiting algorithm
    /// implementation may return additional information for the
    /// caller, e.g. a time when the cell was expected to arrive.
    No(T),
}

impl<T> Decision<T> {
    /// Check if a decision on a cell indicates the cell is compliant
    /// or not. Returns `true` iff the cell was compliant, i.e. the
    /// decision was `Decision::Yes`.
    ///
    /// Note: This method is mostly useful in tests.
    pub fn is_compliant(&self) -> bool {
        match *self {
            Decision::Yes => true,
            Decision::No(_) => false,
        }
    }
}

/// A prerequisite for implementing any Decider trait. It provides the
/// associated type for [`Decision`](enum.Decision.html)'s additional
/// information for negative decisions.
pub trait TypedDecider {
    /// The type for additional information on negative decisions.
    type T;
}

/// The main decision trait. It allows checking a single cell against
/// the rate-limiter, either at the current time instant, or at a
/// given instant in time, both destructively.
pub trait Decider: DeciderImpl {
    /// Tests if a single cell can be accomodated at
    /// `Instant::now()`. See [`check_at`](#method.check_at).
    fn check(&mut self) -> Result<Decision<Self::T>> {
        self.test_and_update(Instant::now())
    }

    /// Tests is a single cell can be accomodated at the given time
    /// stamp.
    fn check_at(&mut self, at: Instant) -> Result<Decision<Self::T>> {
        self.test_and_update(at)
    }
}

pub trait MultiDecider: MultiDeciderImpl {
    /// Tests if `n` cells can be accomodated at the given time
    /// stamp. An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n_at(&mut self, n: u32, at: Instant) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, at)
    }

    /// Tests if `n` cells can be accomodated at the current time
    /// (`Instant::now()`). An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n(&mut self, n: u32) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, Instant::now())
    }
}
<|endoftext|>


<commit_before>#![crate_name = "amethyst"]
#![crate_type = "lib"]
#![doc(html_logo_url = "http://tinyurl.com/hgsb45k")]

//! Amethyst is a free and open source game engine written in idiomatic
//! [Rust][rs] for building video games and interactive multimedia applications.
//! The source code is available for download on [GitHub][gh].
//!
//! [rs]: https://www.rust-lang.org/
//! [gh]: https://github.com/ebkalderon/amethyst
//!
//! This project is a work in progress and is very incomplete. Pardon the dust!
//!
//! # Example
//!
//! ```ignore
//! extern crate amethyst;
//!
//! use amethyst::*;
//!
//! struct GameState;
//!
//! impl State for GameState {
//!     fn handle_events(&mut self, events: &Vec<Event>) -> Trans {
//!         for e in events {
//!             match e {
//!                 Event::Closed => Trans::Quit,
//!                 Event::Resized(x, y) => println!("x: {}, y: {}", x, y),
//!                 Event::KeyPressed(k) => if k == Key::Esc { Trans::Quit },
//!             }
//!         }
//!         Trans::None
//!     }
//!
//!     fn update(&mut self, _delta: Duration) -> Trans {
//!         println!("Computing some more whoop-ass...");
//!         Trans::None
//!     }
//! }
//!
//! fn main() {
//!     let mut game = Application::new(GameState);
//!     game.run();
//! }
//! ```

mod engine;
pub mod renderer;

pub use self::engine::app::Application;
pub use self::engine::state::{State, StateMachine, Trans};
pub use self::engine::timing::{Duration, Stopwatch};
<commit_msg>link to online book in API docs<commit_after>#![crate_name = "amethyst"]
#![crate_type = "lib"]
#![doc(html_logo_url = "http://tinyurl.com/hgsb45k")]

//! Amethyst is a free and open source game engine written in idiomatic
//! [Rust][rs] for building video games and interactive multimedia applications.
//! The source code is available for download on [GitHub][gh]. See the online
//! [online book][bk] for a complete guide to using Amethyst.
//!
//! [rs]: https://www.rust-lang.org/
//! [gh]: https://github.com/ebkalderon/amethyst
//! [bk]: http://ebkalderon.github.io/amethyst/
//!
//! This project is a work in progress and is very incomplete. Pardon the dust!
//!
//! # Example
//!
//! ```ignore
//! extern crate amethyst;
//!
//! use amethyst::*;
//!
//! struct GameState;
//!
//! impl State for GameState {
//!     fn handle_events(&mut self, events: &Vec<Event>) -> Trans {
//!         for e in events {
//!             match e {
//!                 Event::Closed => Trans::Quit,
//!                 Event::Resized(x, y) => println!("x: {}, y: {}", x, y),
//!                 Event::KeyPressed(k) => if k == Key::Esc { Trans::Quit },
//!             }
//!         }
//!         Trans::None
//!     }
//!
//!     fn update(&mut self, _delta: Duration) -> Trans {
//!         println!("Computing some more whoop-ass...");
//!         Trans::None
//!     }
//! }
//!
//! fn main() {
//!     let mut game = Application::new(GameState);
//!     game.run();
//! }
//! ```

mod engine;
pub mod renderer;

pub use self::engine::app::Application;
pub use self::engine::state::{State, StateMachine, Trans};
pub use self::engine::timing::{Duration, Stopwatch};
<|endoftext|>


<commit_before>use std::cmp::Ord;
use std::option::{None, Option, Some};
use std::to_string::ToString;

/// FourNode
struct FourNode<V: ToString+Ord>(V, V, V, Option<(Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>)>);

impl <V: ToString+Ord> FourNode<V> {

    fn new(node: Node<V>, value: V) -> FourNode<V> {
        match node {
            LeafThreeNode(value1, value2) =>
                if value > value2      { FourNode(value1, value2, value, None) }
                else if value < value1 { FourNode(value, value1, value2, None) }
                else                   { FourNode(value1, value, value2, None) },
            _ => fail!(""),
        }
    }

    /// Convert a Split into a TwoNode with the middle value as the value of the new parent node
    fn to_two_node(self) -> Node<V> {
        match self {
            FourNode(v1, v2, v3, None) => TwoNode(v2, box LeafTwoNode(v1), box LeafTwoNode(v3)),
            FourNode(v1, v2, v3, Some((n1, n2, n3, n4))) => TwoNode(v2, box TwoNode(v1, n1, n2), box TwoNode(v3, n3, n4)),
        }
    }
}

/// InsertResult
enum InsertResult<V: ToString+Ord> {
    Fit(Node<V>),  // box this node?
    Split(FourNode<V>),  // split should always contain a ThreeNode/LeafThreeNode. box this?
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Node
enum Node<V: ToString+Ord> {
    LeafTwoNode(V),
    LeafThreeNode(V, V),
    TwoNode(V, Box<Node<V>>, Box<Node<V>>),
    ThreeNode(V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
}

impl <V: ToString+Ord> ToString for Node<V> {
    fn to_string(&self) -> String {
        match *self {
            LeafTwoNode(ref v) => format!("LeafTwoNode({:s})", v.to_string()),
            LeafThreeNode(ref v1, ref v2) => format!("LeafThreeNode({:s}, {:s})", v1.to_string(), v2.to_string()),
            TwoNode(ref v, ref left, ref middle) => format!("TwoNode({:s}, {:s}, {:s})", v.to_string(), left.to_string(), middle.to_string()),
            ThreeNode(_, _, ref left, ref middle, ref right) => format!("ThreeNode({:s}, {:s}, {:s})", left.to_string(), middle.to_string(), right.to_string()),
        }
    }
}

impl <V: ToString+Ord> Node<V> {
    // PRIVATE
    /// Extend this TwoNode with the provided value and child node to make it a ThreeNode
    fn extend(self, other_value: V, other_node: Box<Node<V>>) -> Node<V> {
        match self {
            TwoNode(self_value, self_left, self_middle) => {
                if self_value > other_value {
                    ThreeNode(other_value, self_value, other_node, self_left, self_middle)
                } else {
                    ThreeNode(self_value, other_value, self_left, self_middle, other_node)
                }
            }
            _ => fail!(""),
        }
    }

    fn extend4(self, other_value: V, other_node: Box<Node<V>>) -> FourNode<V> {
        match self {
            ThreeNode(self_value1, self_value2, self_left, self_middle, self_right) => {
                if other_value < self_value1 {
                    FourNode(other_value, self_value1, self_value2, Some((other_node, self_left, self_middle, self_right)))
                } else {
                    FourNode(self_value1, self_value2, other_value, Some((self_left, self_middle, self_right, other_node)))
                }
            }
            _ => fail!(""),
        }
    }

    fn next_direction(&self, to_insert: &V) -> Direction {
        match *self {
            TwoNode(ref value, _, _) =>
                if to_insert < value { Left }
                else                 { Middle },
            ThreeNode(ref value1, ref value2, _, _, _) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &TwoNode(ref v, _, _) |
                &LeafTwoNode(ref v) if to_check == v => true,

            &ThreeNode(ref v1, ref v2, _, _, _) |
                &LeafThreeNode(ref v1, ref v2) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            LeafTwoNode(value) => {
                if to_insert > value { Fit(LeafThreeNode(value, to_insert)) }
                else                 { Fit(LeafThreeNode(to_insert, value)) }
            },

            // Split if leaf ThreeNode
            node @ LeafThreeNode(..) => Split(FourNode::new(node, to_insert)),

            // Recurse down if internal Node and handle results
            TwoNode(value, box left, box middle) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => fail!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left => TwoNode(value, box returned_node, box other_node),
                            Middle => TwoNode(value, box other_node, box returned_node),
                            _ => fail!(""),
                        },
                    Split(four_node) => four_node.to_two_node().extend(value, box other_node),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            ThreeNode(value1, value2, left, middle, right) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => fail!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let new_node = match next_direction {
                            Left => ThreeNode(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => ThreeNode(value1, value2, other_node1, box returned_node, other_node2),
                            Right => ThreeNode(value1, value2, other_node1, other_node2, box returned_node),
                            _ => fail!(""),
                        };
                        Fit(new_node)
                    },
                    Split(four_node) => {
                        let new_node: FourNode<V> = match next_direction {
                            Left => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Middle => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Right => four_node.to_two_node().extend(value2, other_node2).extend4(value1, other_node1),
                            _ => fail!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: ToString+Ord> {
    root: Option<Node<V>>,
}

impl <V: ToString+Ord> ToString for TTTree<V> {
    fn to_string(&self) -> String {
        match self.root {
            Some(ref node) => node.to_string(),
            None => "TTTree(<empty>)".to_string(),
        }
    }
}

impl <V: ToString+Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => LeafTwoNode(value),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(node @ FourNode(..)) => node.to_two_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}

// TODO:
// Collection trait
// convert this to Key/Value K/V
// remove ToString debugging stuffs

#[test]
fn it_works() {
    let mut tree: TTTree<uint> = TTTree::new();

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(60);
    match tree {
        TTTree{root: Some(LeafThreeNode(50, 60))} => (),
        _ => fail!(),
    }

    tree.insert(70);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafTwoNode(70)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(100);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(55);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafThreeNode(50, 55),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(68);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafTwoNode(100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(75);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafThreeNode(75, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(52);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box TwoNode(52,
                    box LeafTwoNode(50),
                    box LeafTwoNode(55),
                ),
                box TwoNode(70,
                    box LeafTwoNode(68),
                    box LeafThreeNode(75, 100),
                ),
            )
        )} => (),
        _ => fail!(),
    }
}
<commit_msg>Match style of other 'match'es<commit_after>use std::cmp::Ord;
use std::option::{None, Option, Some};
use std::to_string::ToString;

/// FourNode
struct FourNode<V: ToString+Ord>(V, V, V, Option<(Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>)>);

impl <V: ToString+Ord> FourNode<V> {

    fn new(node: Node<V>, value: V) -> FourNode<V> {
        match node {
            LeafThreeNode(value1, value2) =>
                if value > value2      { FourNode(value1, value2, value, None) }
                else if value < value1 { FourNode(value, value1, value2, None) }
                else                   { FourNode(value1, value, value2, None) },
            _ => fail!(""),
        }
    }

    /// Convert a Split into a TwoNode with the middle value as the value of the new parent node
    fn to_two_node(self) -> Node<V> {
        match self {
            FourNode(v1, v2, v3, None) => TwoNode(v2, box LeafTwoNode(v1), box LeafTwoNode(v3)),
            FourNode(v1, v2, v3, Some((n1, n2, n3, n4))) => TwoNode(v2, box TwoNode(v1, n1, n2), box TwoNode(v3, n3, n4)),
        }
    }
}

/// InsertResult
enum InsertResult<V: ToString+Ord> {
    Fit(Node<V>),  // box this node?
    Split(FourNode<V>),  // split should always contain a ThreeNode/LeafThreeNode. box this?
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Node
enum Node<V: ToString+Ord> {
    LeafTwoNode(V),
    LeafThreeNode(V, V),
    TwoNode(V, Box<Node<V>>, Box<Node<V>>),
    ThreeNode(V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
}

impl <V: ToString+Ord> ToString for Node<V> {
    fn to_string(&self) -> String {
        match *self {
            LeafTwoNode(ref v) => format!("LeafTwoNode({:s})", v.to_string()),
            LeafThreeNode(ref v1, ref v2) => format!("LeafThreeNode({:s}, {:s})", v1.to_string(), v2.to_string()),
            TwoNode(ref v, ref left, ref middle) => format!("TwoNode({:s}, {:s}, {:s})", v.to_string(), left.to_string(), middle.to_string()),
            ThreeNode(_, _, ref left, ref middle, ref right) => format!("ThreeNode({:s}, {:s}, {:s})", left.to_string(), middle.to_string(), right.to_string()),
        }
    }
}

impl <V: ToString+Ord> Node<V> {
    // PRIVATE
    /// Extend this TwoNode with the provided value and child node to make it a ThreeNode
    fn extend(self, other_value: V, other_node: Box<Node<V>>) -> Node<V> {
        match self {
            TwoNode(self_value, self_left, self_middle) => {
                if self_value > other_value {
                    ThreeNode(other_value, self_value, other_node, self_left, self_middle)
                } else {
                    ThreeNode(self_value, other_value, self_left, self_middle, other_node)
                }
            }
            _ => fail!(""),
        }
    }

    fn extend4(self, other_value: V, other_node: Box<Node<V>>) -> FourNode<V> {
        match self {
            ThreeNode(self_value1, self_value2, self_left, self_middle, self_right) => {
                if other_value < self_value1 {
                    FourNode(other_value, self_value1, self_value2, Some((other_node, self_left, self_middle, self_right)))
                } else {
                    FourNode(self_value1, self_value2, other_value, Some((self_left, self_middle, self_right, other_node)))
                }
            }
            _ => fail!(""),
        }
    }

    fn next_direction(&self, to_insert: &V) -> Direction {
        match self {
            &TwoNode(ref value, _, _) =>
                if to_insert < value { Left }
                else                 { Middle },
            &ThreeNode(ref value1, ref value2, _, _, _) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &TwoNode(ref v, _, _) |
                &LeafTwoNode(ref v) if to_check == v => true,

            &ThreeNode(ref v1, ref v2, _, _, _) |
                &LeafThreeNode(ref v1, ref v2) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            LeafTwoNode(value) => {
                if to_insert > value { Fit(LeafThreeNode(value, to_insert)) }
                else                 { Fit(LeafThreeNode(to_insert, value)) }
            },

            // Split if leaf ThreeNode
            node @ LeafThreeNode(..) => Split(FourNode::new(node, to_insert)),

            // Recurse down if internal Node and handle results
            TwoNode(value, box left, box middle) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => fail!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left => TwoNode(value, box returned_node, box other_node),
                            Middle => TwoNode(value, box other_node, box returned_node),
                            _ => fail!(""),
                        },
                    Split(four_node) => four_node.to_two_node().extend(value, box other_node),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            ThreeNode(value1, value2, left, middle, right) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => fail!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let new_node = match next_direction {
                            Left => ThreeNode(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => ThreeNode(value1, value2, other_node1, box returned_node, other_node2),
                            Right => ThreeNode(value1, value2, other_node1, other_node2, box returned_node),
                            _ => fail!(""),
                        };
                        Fit(new_node)
                    },
                    Split(four_node) => {
                        let new_node: FourNode<V> = match next_direction {
                            Left => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Middle => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Right => four_node.to_two_node().extend(value2, other_node2).extend4(value1, other_node1),
                            _ => fail!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: ToString+Ord> {
    root: Option<Node<V>>,
}

impl <V: ToString+Ord> ToString for TTTree<V> {
    fn to_string(&self) -> String {
        match self.root {
            Some(ref node) => node.to_string(),
            None => "TTTree(<empty>)".to_string(),
        }
    }
}

impl <V: ToString+Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => LeafTwoNode(value),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(node @ FourNode(..)) => node.to_two_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}

// TODO:
// Collection trait
// convert this to Key/Value K/V
// remove ToString debugging stuffs

#[test]
fn it_works() {
    let mut tree: TTTree<uint> = TTTree::new();

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(60);
    match tree {
        TTTree{root: Some(LeafThreeNode(50, 60))} => (),
        _ => fail!(),
    }

    tree.insert(70);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafTwoNode(70)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(100);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(55);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafThreeNode(50, 55),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(68);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafTwoNode(100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(75);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafThreeNode(75, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(52);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box TwoNode(52,
                    box LeafTwoNode(50),
                    box LeafTwoNode(55),
                ),
                box TwoNode(70,
                    box LeafTwoNode(68),
                    box LeafThreeNode(75, 100),
                ),
            )
        )} => (),
        _ => fail!(),
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::fmt;

/// Describes grid trait and gives a basic implementation in 'BasicGrid'
pub mod grid;

/// Provides utilities for generating mazes from existing grids
pub mod generator;

#[cfg(test)]
mod tests;

/// The 'Direction' type. Used to describe a direction to move in
#[derive(Copy, Clone)]
pub enum Direction
{
    /// Move up
    Up,
    /// Move down
    Down,
    /// Move left
    Left,
    /// Move right
    Right,
    /// Stay in place
    Stay,
}

/// The 'Tile' type. Used to describe the state of a grid position
#[derive(Copy, Clone, PartialEq)]
pub enum Tile
{
    // An empty grid tile with no connections
    Empty,

    // A connected tile, with data on how it is linked
    Connected
    {
        up: bool,
        down: bool,
        left: bool,
        right: bool,
    },
}

impl Tile
{
    /// Creates a new, unlinked, tile
    pub fn new() -> Tile
    {
        Tile::Connected {
            up: false,
            down: false,
            left: false,
            right: false,
        }
    }

    /// Checks if a tile has any links available
    pub fn is_available(&self) -> bool
    {
        match self
        {
            &Tile::Connected {
                 up: u,
                 down: d,
                 left: l,
                 right: r,
             } => !u && !d && !l && !r,
            _ => false,
        }
    }
}

impl fmt::Display for Tile
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let fmt_char: char = match self
        {
            // ━┃┏┓┗┛┣┫┳┻╋
            // ═║╔╗╚╝╠╣╦╩╬
            &Tile::Connected {
                 up: u,
                 down: d,
                 left: l,
                 right: r,
             } =>
            {
                if u && d && l && r
                {
                    '╋'
                }
                else if u && d && l
                {
                    '┫'
                }
                else if u && d && r
                {
                    '┣'
                }
                else if u && l && r
                {
                    '┻'
                }
                else if d && l && r
                {
                    '┳'
                }
                else if u && l
                {
                    '┛'
                }
                else if u && r
                {
                    '┗'
                }
                else if d && l
                {
                    '┓'
                }
                else if d && r
                {
                    '┏'
                }
                else if u || d
                {
                    '┃'
                }
                else if l || r
                {
                    '━'
                }
                else
                {
                    '█'
                }
            }

            &Tile::Empty => '░',
        };

        write!(f, "{}", fmt_char)
    }
}
<commit_msg>Added unsaved file missing from previous commit<commit_after>extern crate rand;

use std::fmt;

/// Describes grid trait and gives a basic implementation in 'BasicGrid'
pub mod grid;

/// Provides utilities for generating mazes from existing grids
pub mod generator;

#[cfg(test)]
mod tests;

/// The 'Direction' type. Used to describe a direction to move in
#[derive(Copy, Clone, PartialEq)]
pub enum Direction
{
    /// Move up
    Up,
    /// Move down
    Down,
    /// Move left
    Left,
    /// Move right
    Right,
    /// Stay in place
    Stay,
}

/// The 'Tile' type. Used to describe the state of a grid position
#[derive(Copy, Clone, PartialEq)]
pub enum Tile
{
    // An empty grid tile with no connections
    Empty,

    // A connected tile, with data on how it is linked
    Connected
    {
        up: bool,
        down: bool,
        left: bool,
        right: bool,
    },
}

impl Tile
{
    /// Creates a new, unlinked, tile
    pub fn new() -> Tile
    {
        Tile::Connected {
            up: false,
            down: false,
            left: false,
            right: false,
        }
    }

    /// Checks if a tile has any links available
    pub fn is_available(&self) -> bool
    {
        match self
        {
            &Tile::Connected {
                 up: u,
                 down: d,
                 left: l,
                 right: r,
             } => !u && !d && !l && !r,
            _ => false,
        }
    }
}

impl fmt::Display for Tile
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let fmt_char: char = match self
        {
            // ━┃┏┓┗┛┣┫┳┻╋
            // ═║╔╗╚╝╠╣╦╩╬
            &Tile::Connected {
                 up: u,
                 down: d,
                 left: l,
                 right: r,
             } =>
            {
                if u && d && l && r
                {
                    '╋'
                }
                else if u && d && l
                {
                    '┫'
                }
                else if u && d && r
                {
                    '┣'
                }
                else if u && l && r
                {
                    '┻'
                }
                else if d && l && r
                {
                    '┳'
                }
                else if u && l
                {
                    '┛'
                }
                else if u && r
                {
                    '┗'
                }
                else if d && l
                {
                    '┓'
                }
                else if d && r
                {
                    '┏'
                }
                else if u || d
                {
                    '┃'
                }
                else if l || r
                {
                    '━'
                }
                else
                {
                    '█'
                }
            }

            &Tile::Empty => '░',
        };

        write!(f, "{}", fmt_char)
    }
}
<|endoftext|>