<commit_before>#![crate_id = "ansi_term#0.1dev"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![desc = "A rust library for ANSI terminal colours and styles (bold, underline)"]

//! This is a library for controlling colours and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//! Simple Colours
//! --------------
//!
//! You can format strings by calling the `paint` method on a Colour
//! or a Style object, passing in the string you want to format. For
//! example, to get some red text, call the `paint` method on `Red`:
//!
//! ```rust
//! Red.paint("Red!")
//! ```
//!
//! You can also call the `paint` method on a Style. To turn a Colour
//! into a Style, use the `normal` method, though this does the exact
//! some thing as above:
//!
//! ```rust
//! Red.normal().paint("Still red!")
//! ```
//!
//! Bold, Underline, and Background
//! -------------------------------
//!
//! To do anything more complex than just foreground colours, you need
//! to use Style objects. Calling the `bold` or `underline` method on
//! a Colour returns a Style that has the appropriate property set on
//! it:
//!
//! ```rust
//! Blue.bold().paint("Blue bold!")
//! Yellow.underline().paint("Yellow underline!")
//! ```
//!
//! Again, you can call these methods on Styles as well as just Colours:
//!
//! ```rust
//! Blue.normal().bold().paint("Still blue bold!")
//! ```
//!
//! Finally, you can set the background colour of a Style by using the
//! `on` method:
//!
//! ```rust
//! Blue.on(Yellow).paint("Blue on yellow!")
//! ```
//!
//! Extended Colours
//! ----------------
//!
//! You can access the extended range of 256 colours by using the
//! Fixed constructor, which takes an argument of the colour number to
//! use. This can be used wherever you would use a Colour:
//!
//! ```rust
//! Fixed(134).paint("A sort of light purple.")
//! ```
//!
//! This even works for background colours:
//!
//! ```rust
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup.")
//! ```
//!
//! No Formatting
//! -------------
//!
//! Finally, for the sake of completeness, the Plain style provides
//! neither colours nor formatting.
//!
//! ```rust
//! Plain.paint("No colours here.")
//! ```

#![feature(phase)] extern crate regex;
#[phase(plugin)] extern crate regex_macros;

trait Paint {
    /// Paints the given text with this colour.
    fn paint(&self, input: &str) -> String;

    /// Returns a Style with the underline property set.
    fn underline(&self) -> Style;

    /// Return a Style with the bold property set.
    fn bold(&self) -> Style;

    /// Return a Style with the background colour set.
    fn on(&self, background: Colour) -> Style;
}

/// A colour is one specific type of ANSI escape code, and can refer
/// to either the foreground or background colour.
pub enum Colour {
    Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed(u8),
}

// These are the standard numeric sequences.
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

impl Colour {
    fn foreground_code(&self) -> String {
        match *self {
            Black => "30".to_string(),
            Red => "31".to_string(),
            Green => "32".to_string(),
            Yellow => "33".to_string(),
            Blue => "34".to_string(),
            Purple => "35".to_string(),
            Cyan => "36".to_string(),
            White => "37".to_string(),
            Fixed(num) => format!("38;5;{}", num),
        }
    }

    fn background_code(&self) -> String {
        match *self {
            Black => "40".to_string(),
            Red => "41".to_string(),
            Green => "42".to_string(),
            Yellow => "43".to_string(),
            Blue => "44".to_string(),
            Purple => "45".to_string(),
            Cyan => "46".to_string(),
            White => "47".to_string(),
            Fixed(num) => format!("48;5;{}", num),
        }
    }

    /// Return a Style with the foreground colour set to this colour.
    pub fn normal(&self) -> Style {
        Style(StyleStruct { foreground: *self, background: None, bold: false, underline: false })
    }
}

/// The Paint trait represents a style or colour that can be applied
/// to a piece of text.
impl Paint for Colour {
    /// This is a short-cut so you don't have to use Blue.normal() just
    /// to get blue text.
    fn paint(&self, input: &str) -> String {
        let re = format!("\x1B[{}m{}\x1B[0m", self.foreground_code(), input);
        return re.to_string();
    }

    fn underline(&self) -> Style {
        Style(StyleStruct { foreground: *self, background: None, bold: false, underline: true })
    }

    fn bold(&self) -> Style {
        Style(StyleStruct { foreground: *self, background: None, bold: true, underline: false })
    }

    fn on(&self, background: Colour) -> Style {
        Style(StyleStruct { foreground: *self, background: Some(background), bold: false, underline: false })
    }
}

/// A style is a collection of properties that can format a string
/// using ANSI escape codes.
pub enum Style {
    /// The Plain style provides no formatting.
    Plain,
    /// The Foreground style provides just a foreground colour.
    Foreground(Colour),
    /// The Style style is a catch-all for anything more complicated
    /// than that. It's technically possible for there to be other
    /// cases, such as "bold foreground", but probably isn't worth it.
    Style(StyleStruct),
}

// Having a struct inside an enum is currently unfinished in Rust, but
// should be put in there when that feature is complete.

struct StyleStruct {
    foreground: Colour,
    background: Option<Colour>,
    bold: bool,
    underline: bool,
}

impl Paint for Style {
    fn paint(&self, input: &str) -> String {
        match *self {
            Plain => input.to_string(),
            Foreground(c) => c.paint(input),
            Style(s) => match s {
                StyleStruct { foreground, background, bold, underline } => {
                    let bg = match background {
                        Some(c) => format!("{};", c.background_code()),
                        None => "".to_string()
                    };
                    let bo = if bold { "1;" } else { "" };
                    let un = if underline { "4;" } else { "" };
                    let painted = format!("\x1B[{}{}{}{}m{}\x1B[0m", bo, un, bg, foreground.foreground_code(), input.to_string());
                    return painted.to_string();
                }
            }
        }
    }

    fn bold(&self) -> Style {
        match *self {
            Plain => Style(StyleStruct         { foreground: White,         background: None,          bold: true, underline: false }),
            Foreground(c) => Style(StyleStruct { foreground: c,             background: None,          bold: true, underline: false }),
            Style(st) => Style(StyleStruct     { foreground: st.foreground, background: st.background, bold: true, underline: st.underline }),
        }
    }

    fn underline(&self) -> Style {
        match *self {
            Plain => Style(StyleStruct         { foreground: White,         background: None,          bold: false,   underline: true }),
            Foreground(c) => Style(StyleStruct { foreground: c,             background: None,          bold: false,   underline: true }),
            Style(st) => Style(StyleStruct     { foreground: st.foreground, background: st.background, bold: st.bold, underline: true }),
        }
    }

    fn on(&self, background: Colour) -> Style {
        match *self {
            Plain => Style(StyleStruct         { foreground: White,         background: Some(background), bold: false,   underline: false }),
            Foreground(c) => Style(StyleStruct { foreground: c,             background: Some(background), bold: false,   underline: false }),
            Style(st) => Style(StyleStruct     { foreground: st.foreground, background: Some(background), bold: st.bold, underline: st.underline }),
        }
    }
}

/// Return a String with all ANSI escape codes removed. For example:
///
/// ```rust
/// strip_formatting(Blue.paint("hello!")) == "hello!"
/// ```
pub fn strip_formatting(input: String) -> String {
    // What's blue and smells like red paint? Blue paint.
    let re = regex!("\x1B\\[.+?m");
    re.replace_all(input.as_slice(), "").to_string()
}

#[cfg(test)]
mod tests {
    use super::{Paint, Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed, Plain, strip_formatting};

    #[test]
    fn test_plain() {
        let hi = Plain.paint("text/plain");
        assert!(hi == "text/plain".to_string());
    }

    #[test]
    fn test_red() {
        let hi = Red.paint("hi");
        assert!(hi == "\x1B[31mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_black() {
        let hi = Black.normal().paint("hi");
        assert!(hi == "\x1B[30mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold() {
        let hi = Yellow.bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold_2() {
        let hi = Yellow.normal().bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_blue_underline() {
        let hi = Blue.underline().paint("hi");
        assert!(hi == "\x1B[4;34mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline() {
        let hi = Green.bold().underline().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline_2() {
        let hi = Green.underline().bold().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white() {
        let hi = Purple.on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white_2() {
        let hi = Purple.normal().on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_on_white() {
        let hi = Cyan.bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_on_white() {
        let hi = Cyan.underline().on(White).paint("hi");
        assert!(hi == "\x1B[4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_underline_on_white() {
        let hi = Cyan.bold().underline().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_bold_on_white() {
        let hi = Cyan.underline().bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed() {
        let hi = Fixed(100).paint("hi");
        assert!(hi == "\x1B[38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_purple() {
        let hi = Fixed(100).on(Purple).paint("hi");
        assert!(hi == "\x1B[45;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_fixed() {
        let hi = Fixed(100).on(Fixed(200)).paint("hi");
        assert!(hi == "\x1B[48;5;200;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_strip_formatting() {
        let hi = strip_formatting(Blue.paint("hi"));
        assert!(hi == "hi".to_string());
    }

    #[test]
    fn test_strip_formatting_2() {
        let hi = strip_formatting(Blue.on(Fixed(230)).bold().paint("hi"));
        assert!(hi == "hi".to_string());
    }
}
<commit_msg>Make Paint trait public<commit_after>#![crate_id = "ansi_term#0.1dev"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![desc = "A rust library for ANSI terminal colours and styles (bold, underline)"]

//! This is a library for controlling colours and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//! Simple Colours
//! --------------
//!
//! You can format strings by calling the `paint` method on a Colour
//! or a Style object, passing in the string you want to format. For
//! example, to get some red text, call the `paint` method on `Red`:
//!
//! ```rust
//! Red.paint("Red!")
//! ```
//!
//! You can also call the `paint` method on a Style. To turn a Colour
//! into a Style, use the `normal` method, though this does the exact
//! some thing as above:
//!
//! ```rust
//! Red.normal().paint("Still red!")
//! ```
//!
//! Bold, Underline, and Background
//! -------------------------------
//!
//! To do anything more complex than just foreground colours, you need
//! to use Style objects. Calling the `bold` or `underline` method on
//! a Colour returns a Style that has the appropriate property set on
//! it:
//!
//! ```rust
//! Blue.bold().paint("Blue bold!")
//! Yellow.underline().paint("Yellow underline!")
//! ```
//!
//! Again, you can call these methods on Styles as well as just Colours:
//!
//! ```rust
//! Blue.normal().bold().paint("Still blue bold!")
//! ```
//!
//! Finally, you can set the background colour of a Style by using the
//! `on` method:
//!
//! ```rust
//! Blue.on(Yellow).paint("Blue on yellow!")
//! ```
//!
//! Extended Colours
//! ----------------
//!
//! You can access the extended range of 256 colours by using the
//! Fixed constructor, which takes an argument of the colour number to
//! use. This can be used wherever you would use a Colour:
//!
//! ```rust
//! Fixed(134).paint("A sort of light purple.")
//! ```
//!
//! This even works for background colours:
//!
//! ```rust
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup.")
//! ```
//!
//! No Formatting
//! -------------
//!
//! Finally, for the sake of completeness, the Plain style provides
//! neither colours nor formatting.
//!
//! ```rust
//! Plain.paint("No colours here.")
//! ```

#![feature(phase)] extern crate regex;
#[phase(plugin)] extern crate regex_macros;

pub trait Paint {
    /// Paints the given text with this colour.
    fn paint(&self, input: &str) -> String;

    /// Returns a Style with the underline property set.
    fn underline(&self) -> Style;

    /// Return a Style with the bold property set.
    fn bold(&self) -> Style;

    /// Return a Style with the background colour set.
    fn on(&self, background: Colour) -> Style;
}

/// A colour is one specific type of ANSI escape code, and can refer
/// to either the foreground or background colour.
pub enum Colour {
    Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed(u8),
}

// These are the standard numeric sequences.
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

impl Colour {
    fn foreground_code(&self) -> String {
        match *self {
            Black => "30".to_string(),
            Red => "31".to_string(),
            Green => "32".to_string(),
            Yellow => "33".to_string(),
            Blue => "34".to_string(),
            Purple => "35".to_string(),
            Cyan => "36".to_string(),
            White => "37".to_string(),
            Fixed(num) => format!("38;5;{}", num),
        }
    }

    fn background_code(&self) -> String {
        match *self {
            Black => "40".to_string(),
            Red => "41".to_string(),
            Green => "42".to_string(),
            Yellow => "43".to_string(),
            Blue => "44".to_string(),
            Purple => "45".to_string(),
            Cyan => "46".to_string(),
            White => "47".to_string(),
            Fixed(num) => format!("48;5;{}", num),
        }
    }

    /// Return a Style with the foreground colour set to this colour.
    pub fn normal(&self) -> Style {
        Style(StyleStruct { foreground: *self, background: None, bold: false, underline: false })
    }
}

/// The Paint trait represents a style or colour that can be applied
/// to a piece of text.
impl Paint for Colour {
    /// This is a short-cut so you don't have to use Blue.normal() just
    /// to get blue text.
    fn paint(&self, input: &str) -> String {
        let re = format!("\x1B[{}m{}\x1B[0m", self.foreground_code(), input);
        return re.to_string();
    }

    fn underline(&self) -> Style {
        Style(StyleStruct { foreground: *self, background: None, bold: false, underline: true })
    }

    fn bold(&self) -> Style {
        Style(StyleStruct { foreground: *self, background: None, bold: true, underline: false })
    }

    fn on(&self, background: Colour) -> Style {
        Style(StyleStruct { foreground: *self, background: Some(background), bold: false, underline: false })
    }
}

/// A style is a collection of properties that can format a string
/// using ANSI escape codes.
pub enum Style {
    /// The Plain style provides no formatting.
    Plain,
    /// The Foreground style provides just a foreground colour.
    Foreground(Colour),
    /// The Style style is a catch-all for anything more complicated
    /// than that. It's technically possible for there to be other
    /// cases, such as "bold foreground", but probably isn't worth it.
    Style(StyleStruct),
}

// Having a struct inside an enum is currently unfinished in Rust, but
// should be put in there when that feature is complete.

struct StyleStruct {
    foreground: Colour,
    background: Option<Colour>,
    bold: bool,
    underline: bool,
}

impl Paint for Style {
    fn paint(&self, input: &str) -> String {
        match *self {
            Plain => input.to_string(),
            Foreground(c) => c.paint(input),
            Style(s) => match s {
                StyleStruct { foreground, background, bold, underline } => {
                    let bg = match background {
                        Some(c) => format!("{};", c.background_code()),
                        None => "".to_string()
                    };
                    let bo = if bold { "1;" } else { "" };
                    let un = if underline { "4;" } else { "" };
                    let painted = format!("\x1B[{}{}{}{}m{}\x1B[0m", bo, un, bg, foreground.foreground_code(), input.to_string());
                    return painted.to_string();
                }
            }
        }
    }

    fn bold(&self) -> Style {
        match *self {
            Plain => Style(StyleStruct         { foreground: White,         background: None,          bold: true, underline: false }),
            Foreground(c) => Style(StyleStruct { foreground: c,             background: None,          bold: true, underline: false }),
            Style(st) => Style(StyleStruct     { foreground: st.foreground, background: st.background, bold: true, underline: st.underline }),
        }
    }

    fn underline(&self) -> Style {
        match *self {
            Plain => Style(StyleStruct         { foreground: White,         background: None,          bold: false,   underline: true }),
            Foreground(c) => Style(StyleStruct { foreground: c,             background: None,          bold: false,   underline: true }),
            Style(st) => Style(StyleStruct     { foreground: st.foreground, background: st.background, bold: st.bold, underline: true }),
        }
    }

    fn on(&self, background: Colour) -> Style {
        match *self {
            Plain => Style(StyleStruct         { foreground: White,         background: Some(background), bold: false,   underline: false }),
            Foreground(c) => Style(StyleStruct { foreground: c,             background: Some(background), bold: false,   underline: false }),
            Style(st) => Style(StyleStruct     { foreground: st.foreground, background: Some(background), bold: st.bold, underline: st.underline }),
        }
    }
}

/// Return a String with all ANSI escape codes removed. For example:
///
/// ```rust
/// strip_formatting(Blue.paint("hello!")) == "hello!"
/// ```
pub fn strip_formatting(input: String) -> String {
    // What's blue and smells like red paint? Blue paint.
    let re = regex!("\x1B\\[.+?m");
    re.replace_all(input.as_slice(), "").to_string()
}

#[cfg(test)]
mod tests {
    use super::{Paint, Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed, Plain, strip_formatting};

    #[test]
    fn test_plain() {
        let hi = Plain.paint("text/plain");
        assert!(hi == "text/plain".to_string());
    }

    #[test]
    fn test_red() {
        let hi = Red.paint("hi");
        assert!(hi == "\x1B[31mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_black() {
        let hi = Black.normal().paint("hi");
        assert!(hi == "\x1B[30mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold() {
        let hi = Yellow.bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold_2() {
        let hi = Yellow.normal().bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_blue_underline() {
        let hi = Blue.underline().paint("hi");
        assert!(hi == "\x1B[4;34mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline() {
        let hi = Green.bold().underline().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline_2() {
        let hi = Green.underline().bold().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white() {
        let hi = Purple.on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white_2() {
        let hi = Purple.normal().on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_on_white() {
        let hi = Cyan.bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_on_white() {
        let hi = Cyan.underline().on(White).paint("hi");
        assert!(hi == "\x1B[4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_underline_on_white() {
        let hi = Cyan.bold().underline().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_bold_on_white() {
        let hi = Cyan.underline().bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed() {
        let hi = Fixed(100).paint("hi");
        assert!(hi == "\x1B[38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_purple() {
        let hi = Fixed(100).on(Purple).paint("hi");
        assert!(hi == "\x1B[45;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_fixed() {
        let hi = Fixed(100).on(Fixed(200)).paint("hi");
        assert!(hi == "\x1B[48;5;200;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_strip_formatting() {
        let hi = strip_formatting(Blue.paint("hi"));
        assert!(hi == "hi".to_string());
    }

    #[test]
    fn test_strip_formatting_2() {
        let hi = strip_formatting(Blue.on(Fixed(230)).bold().paint("hi"));
        assert!(hi == "hi".to_string());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::cell::RefCell;
use std::rc::Rc;
use std::collections::HashMap;
use std::result::Result;
use handle_table::{Handle};
use {PromiseFulfiller, EventLoop, ErrorHandler};

pub mod promise_node;

thread_local!(pub static EVENT_LOOP: RefCell<Option<EventLoop>> = RefCell::new(None));

pub fn with_current_event_loop<F, R>(f: F) -> R
    where F: FnOnce(&EventLoop) -> R
{
    EVENT_LOOP.with(|maybe_event_loop| {
        match &*maybe_event_loop.borrow() {
            &None => panic!("current thread has no event loop"),
            &Some(ref event_loop) => f(event_loop),
        }
    })
}

pub trait PromiseNode<T, E> {
    /// Arms the given event when the promised value is ready.
    fn on_ready(&mut self, event: EventHandle);

    fn set_self_pointer(&mut self) {}
    fn get(self: Box<Self>) -> Result<T, E>;
}

pub trait Event {
    fn fire(&mut self) -> Option<EventDropper>;
}

#[derive(PartialEq, Eq, Copy, Clone, Hash)]
pub struct EventHandle(pub Handle);

impl EventHandle {
    pub fn new() -> (EventHandle, EventDropper) {
        return with_current_event_loop(|event_loop| {
            let node = EventNode { event: None, next: None, prev: None };
            let handle = EventHandle(event_loop.events.borrow_mut().push(node));
            return (handle, EventDropper { event_handle: handle });
        });
    }

    pub fn set(&self, event: Box<Event>) {
        return with_current_event_loop(|event_loop| {
            event_loop.events.borrow_mut()[self.0].event = Some(event);
        });
    }

    pub fn arm_breadth_first(self) {
        with_current_event_loop(|event_loop| {
            event_loop.arm_breadth_first(self);
        });
    }

    pub fn arm_depth_first(self) {
        with_current_event_loop(|event_loop| {
            event_loop.arm_depth_first(self);
        });
    }
}

pub struct EventNode {
    pub event: Option<Box<Event>>,
    pub next: Option<EventHandle>,
    pub prev: Option<EventHandle>
}

#[derive(PartialEq, Eq, Hash)]
pub struct EventDropper {
    event_handle: EventHandle,
}

impl Drop for EventDropper {
    fn drop(&mut self) {
        with_current_event_loop(|event_loop| {
            let maybe_event_node = event_loop.events.borrow_mut().remove(self.event_handle.0);

            match maybe_event_node {
                None => {}
                Some(event_node) => {

                    // event_node.next.prev = event_node.prev
                    match event_node.next {
                        Some(e) => {
                            event_loop.events.borrow_mut()[e.0].prev = event_node.prev;
                        }
                        None => {}
                    }
                    // event_node.prev.next = event_node.next
                    match event_node.prev {
                        Some(e) => {
                            event_loop.events.borrow_mut()[e.0].next = event_node.next;
                            event_loop.tail.set(e);
                        }
                        None => {}
                    }
                }
            }
        });
    }
}

pub struct BoolEvent {
    fired: ::std::rc::Rc<::std::cell::Cell<bool>>,
}

impl BoolEvent {
    pub fn new(fired: ::std::rc::Rc<::std::cell::Cell<bool>>) -> BoolEvent {
        BoolEvent { fired: fired }
    }
}

impl Event for BoolEvent {
    fn fire(&mut self) -> Option<EventDropper> {
        self.fired.set(true);
        return None;
    }
}

pub enum OnReadyEvent {
    Empty,
    AlreadyReady,
    Full(EventHandle),
}

impl OnReadyEvent {
    fn is_already_ready(&self) -> bool {
        match self {
            &OnReadyEvent::AlreadyReady => return true,
            _ => return false,
        }
    }

    fn is_empty(&self) -> bool {
        match self {
            &OnReadyEvent::Empty => return true,
            _ => return false,
        }
    }

    fn init(&mut self, new_event: EventHandle) {
        if self.is_already_ready() {
            new_event.arm_breadth_first();
        } else {
            *self = OnReadyEvent::Full(new_event);
        }
    }

    fn arm(&mut self) {
        if self.is_empty() {
            *self = OnReadyEvent::AlreadyReady;
        } else {
            let old_self = ::std::mem::replace(self, OnReadyEvent::Empty);
            match old_self {
                OnReadyEvent::Full(event) => {
                    event.arm_depth_first();
                }
                _ => {
                    panic!("armed an event twice?");
                }
            }
        }
    }
}

pub struct PromiseAndFulfillerHub<T, E> where T: 'static, E: 'static {
    result: Option<Result<T, E>>,
    on_ready_event: OnReadyEvent,
}

impl <T, E> PromiseAndFulfillerHub<T, E> {
    pub fn new() -> PromiseAndFulfillerHub<T, E> {
        PromiseAndFulfillerHub { result: None::<Result<T, E>>, on_ready_event: OnReadyEvent::Empty }
    }
}

impl <T, E> PromiseAndFulfillerHub<T, E> {
    fn fulfill(&mut self, value: T) {
        if self.result.is_none() {
            self.result = Some(Ok(value));
        }
        self.on_ready_event.arm();
    }

    fn reject(&mut self, error: E) {
        if self.result.is_none() {
            self.result = Some(Err(error));
        }
    }
}

impl <T, E> PromiseNode<T, E> for ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T, E>>> {
    fn on_ready(&mut self, event: EventHandle) {
        self.borrow_mut().on_ready_event.init(event);
    }
    fn get(self: Box<Self>) -> Result<T, E> {
        match ::std::mem::replace(&mut self.borrow_mut().result, None) {
            None => panic!("no result!"),
            Some(r) => r
        }
    }
}

impl <T, E> PromiseFulfiller<T, E> for Rc<RefCell<PromiseAndFulfillerHub<T, E>>>
    where T: 'static, E: 'static
{
    fn fulfill(self: Box<Self>, value: T) {
        self.borrow_mut().fulfill(value);
    }

    fn reject(self: Box<Self>, error: E) {
        self.borrow_mut().reject(error);
    }
}

pub struct TaskSetImpl<T, E> where T: 'static, E: 'static {
    error_handler: Box<ErrorHandler<T, E>>,
    tasks: HashMap<EventHandle, EventDropper>,
}

impl <T, E> TaskSetImpl <T, E> {
    pub fn new(error_handler: Box<ErrorHandler<T, E>>) -> TaskSetImpl<T, E> {
        TaskSetImpl { error_handler: error_handler,
                      tasks: HashMap::new() }
    }

      pub fn add(task_set: Rc<RefCell<Self>>, mut node: Box<PromiseNode<T, E>>) {
          let (handle, dropper) = EventHandle::new();
          node.on_ready(handle);
          let task = Task { task_set: task_set.clone(), node: Some(node), event_handle: handle };
          handle.set(Box::new(task));
          task_set.borrow_mut().tasks.insert(handle, dropper);
    }
}

pub struct Task<T, E> where T: 'static, E: 'static {
    task_set: Rc<RefCell<TaskSetImpl<T, E>>>,
    node: Option<Box<PromiseNode<T, E>>>,
    event_handle: EventHandle,
}

impl <T, E> Event for Task<T, E> {
    fn fire(&mut self) -> Option<EventDropper> {
        let maybe_node = ::std::mem::replace(&mut self.node, None);
        match maybe_node {
            None => {
                panic!()
            }
            Some(node) => {
                match node.get() {
                    Ok(v) => {
                        self.task_set.borrow_mut().error_handler.task_succeeded(v);
                        return self.task_set.borrow_mut().tasks.remove(&self.event_handle);
                    }
                    Err(e) => {
                        self.task_set.borrow_mut().error_handler.task_failed(e);
                        return None;
                    }
                }
            }
        }
    }
}
<commit_msg>style<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::cell::RefCell;
use std::rc::Rc;
use std::collections::HashMap;
use std::result::Result;
use handle_table::{Handle};
use {PromiseFulfiller, EventLoop, ErrorHandler};

pub mod promise_node;

thread_local!(pub static EVENT_LOOP: RefCell<Option<EventLoop>> = RefCell::new(None));

pub fn with_current_event_loop<F, R>(f: F) -> R
    where F: FnOnce(&EventLoop) -> R
{
    EVENT_LOOP.with(|maybe_event_loop| {
        match &*maybe_event_loop.borrow() {
            &None => panic!("current thread has no event loop"),
            &Some(ref event_loop) => f(event_loop),
        }
    })
}

pub trait PromiseNode<T, E> {
    /// Arms the given event when the promised value is ready.
    fn on_ready(&mut self, event: EventHandle);

    fn set_self_pointer(&mut self) {}
    fn get(self: Box<Self>) -> Result<T, E>;
}

pub trait Event {
    fn fire(&mut self) -> Option<EventDropper>;
}

#[derive(PartialEq, Eq, Copy, Clone, Hash)]
pub struct EventHandle(pub Handle);

impl EventHandle {
    pub fn new() -> (EventHandle, EventDropper) {
        with_current_event_loop(|event_loop| {
            let node = EventNode { event: None, next: None, prev: None };
            let handle = EventHandle(event_loop.events.borrow_mut().push(node));
            (handle, EventDropper { event_handle: handle })
        })
    }

    pub fn set(&self, event: Box<Event>) {
        with_current_event_loop(|event_loop| {
            event_loop.events.borrow_mut()[self.0].event = Some(event);
        })
    }

    pub fn arm_breadth_first(self) {
        with_current_event_loop(|event_loop| {
            event_loop.arm_breadth_first(self);
        });
    }

    pub fn arm_depth_first(self) {
        with_current_event_loop(|event_loop| {
            event_loop.arm_depth_first(self);
        });
    }
}

pub struct EventNode {
    pub event: Option<Box<Event>>,
    pub next: Option<EventHandle>,
    pub prev: Option<EventHandle>
}

#[derive(PartialEq, Eq, Hash)]
pub struct EventDropper {
    event_handle: EventHandle,
}

impl Drop for EventDropper {
    fn drop(&mut self) {
        with_current_event_loop(|event_loop| {
            let maybe_event_node = event_loop.events.borrow_mut().remove(self.event_handle.0);

            match maybe_event_node {
                None => {}
                Some(event_node) => {

                    // event_node.next.prev = event_node.prev
                    match event_node.next {
                        Some(e) => {
                            event_loop.events.borrow_mut()[e.0].prev = event_node.prev;
                        }
                        None => {}
                    }
                    // event_node.prev.next = event_node.next
                    match event_node.prev {
                        Some(e) => {
                            event_loop.events.borrow_mut()[e.0].next = event_node.next;
                            event_loop.tail.set(e);
                        }
                        None => {}
                    }
                }
            }
        });
    }
}

pub struct BoolEvent {
    fired: ::std::rc::Rc<::std::cell::Cell<bool>>,
}

impl BoolEvent {
    pub fn new(fired: ::std::rc::Rc<::std::cell::Cell<bool>>) -> BoolEvent {
        BoolEvent { fired: fired }
    }
}

impl Event for BoolEvent {
    fn fire(&mut self) -> Option<EventDropper> {
        self.fired.set(true);
        None
    }
}

pub enum OnReadyEvent {
    Empty,
    AlreadyReady,
    Full(EventHandle),
}

impl OnReadyEvent {
    fn is_already_ready(&self) -> bool {
        match self {
            &OnReadyEvent::AlreadyReady => true,
            _ => false,
        }
    }

    fn is_empty(&self) -> bool {
        match self {
            &OnReadyEvent::Empty => true,
            _ => false,
        }
    }

    fn init(&mut self, new_event: EventHandle) {
        if self.is_already_ready() {
            new_event.arm_breadth_first();
        } else {
            *self = OnReadyEvent::Full(new_event);
        }
    }

    fn arm(&mut self) {
        if self.is_empty() {
            *self = OnReadyEvent::AlreadyReady;
        } else {
            let old_self = ::std::mem::replace(self, OnReadyEvent::Empty);
            match old_self {
                OnReadyEvent::Full(event) => {
                    event.arm_depth_first();
                }
                _ => {
                    panic!("armed an event twice?");
                }
            }
        }
    }
}

pub struct PromiseAndFulfillerHub<T, E> where T: 'static, E: 'static {
    result: Option<Result<T, E>>,
    on_ready_event: OnReadyEvent,
}

impl <T, E> PromiseAndFulfillerHub<T, E> {
    pub fn new() -> PromiseAndFulfillerHub<T, E> {
        PromiseAndFulfillerHub { result: None::<Result<T, E>>, on_ready_event: OnReadyEvent::Empty }
    }
}

impl <T, E> PromiseAndFulfillerHub<T, E> {
    fn fulfill(&mut self, value: T) {
        if self.result.is_none() {
            self.result = Some(Ok(value));
        }
        self.on_ready_event.arm();
    }

    fn reject(&mut self, error: E) {
        if self.result.is_none() {
            self.result = Some(Err(error));
        }
    }
}

impl <T, E> PromiseNode<T, E> for ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T, E>>> {
    fn on_ready(&mut self, event: EventHandle) {
        self.borrow_mut().on_ready_event.init(event);
    }
    fn get(self: Box<Self>) -> Result<T, E> {
        match ::std::mem::replace(&mut self.borrow_mut().result, None) {
            None => panic!("no result!"),
            Some(r) => r
        }
    }
}

impl <T, E> PromiseFulfiller<T, E> for Rc<RefCell<PromiseAndFulfillerHub<T, E>>>
    where T: 'static, E: 'static
{
    fn fulfill(self: Box<Self>, value: T) {
        self.borrow_mut().fulfill(value);
    }

    fn reject(self: Box<Self>, error: E) {
        self.borrow_mut().reject(error);
    }
}

pub struct TaskSetImpl<T, E> where T: 'static, E: 'static {
    error_handler: Box<ErrorHandler<T, E>>,
    tasks: HashMap<EventHandle, EventDropper>,
}

impl <T, E> TaskSetImpl <T, E> {
    pub fn new(error_handler: Box<ErrorHandler<T, E>>) -> TaskSetImpl<T, E> {
        TaskSetImpl { error_handler: error_handler,
                      tasks: HashMap::new() }
    }

      pub fn add(task_set: Rc<RefCell<Self>>, mut node: Box<PromiseNode<T, E>>) {
          let (handle, dropper) = EventHandle::new();
          node.on_ready(handle);
          let task = Task { task_set: task_set.clone(), node: Some(node), event_handle: handle };
          handle.set(Box::new(task));
          task_set.borrow_mut().tasks.insert(handle, dropper);
    }
}

pub struct Task<T, E> where T: 'static, E: 'static {
    task_set: Rc<RefCell<TaskSetImpl<T, E>>>,
    node: Option<Box<PromiseNode<T, E>>>,
    event_handle: EventHandle,
}

impl <T, E> Event for Task<T, E> {
    fn fire(&mut self) -> Option<EventDropper> {
        let maybe_node = ::std::mem::replace(&mut self.node, None);
        match maybe_node {
            None => {
                panic!()
            }
            Some(node) => {
                match node.get() {
                    Ok(v) => {
                        self.task_set.borrow_mut().error_handler.task_succeeded(v);
                        self.task_set.borrow_mut().tasks.remove(&self.event_handle)
                    }
                    Err(e) => {
                        self.task_set.borrow_mut().error_handler.task_failed(e);
                        None
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/* AES ECB cut and paste
 *
 * Dmitry Vasiliev <dima@hlabs.org>
 */

use std::collections::HashMap;

fn parse_kv(string: &[u8]) -> HashMap<String, String> {
    let kv = string.split(|&c| c == b'&');
    let mut pairs = kv.map(|kv| kv.split(|&c| c == b'='));
    let mut map = HashMap::new();
    for mut it in pairs {
        let pair: Vec<&[u8]> = it.collect();
        map.insert(String::from_utf8(pair[0].to_vec()).unwrap(),
                   String::from_utf8(pair[1].to_vec()).unwrap());
    }
    map
}

fn encode_kv(map: HashMap<String, String>) -> Vec<u8> {
    let mut bytes = Vec::new();
    for (k, v) in map.iter() {
        bytes.push_all(k.clone().into_bytes().as_slice());
        bytes.push(b'=');
        bytes.push_all(v.clone().into_bytes().as_slice());
        bytes.push(b'&');
    }
    bytes.pop();
    bytes
}

fn main() {
    let obj = parse_kv(b"foo=bar&baz=qux&zap=zazzle");
    println!("Obj: {}", obj);
    let s = encode_kv(obj);
    println!("String: {}", String::from_utf8_lossy(s.as_slice()));
}
<commit_msg>Add tests for parse_kv/encode_kv<commit_after>/* AES ECB cut and paste
 *
 * Dmitry Vasiliev <dima@hlabs.org>
 */

use std::collections::HashMap;

fn parse_kv(string: &[u8]) -> HashMap<String, String> {
    let kv = string.split(|&c| c == b'&');
    let mut pairs = kv.map(|kv| kv.split(|&c| c == b'='));
    let mut map = HashMap::new();
    for mut it in pairs {
        let pair: Vec<&[u8]> = it.collect();
        map.insert(String::from_utf8(pair[0].to_vec()).unwrap(),
                   String::from_utf8(pair[1].to_vec()).unwrap());
    }
    map
}

fn encode_kv(map: HashMap<String, String>) -> Vec<u8> {
    let mut bytes = Vec::new();
    for (k, v) in map.iter() {
        bytes.push_all(k.clone().into_bytes().as_slice());
        bytes.push(b'=');
        bytes.push_all(v.clone().into_bytes().as_slice());
        bytes.push(b'&');
    }
    bytes.pop();
    bytes
}

#[cfg(not(test))]
fn main() {
    let obj = parse_kv(b"foo=bar&baz=qux&zap=zazzle");
    println!("Obj: {}", obj);
    let s = encode_kv(obj);
    println!("String: {}", String::from_utf8_lossy(s.as_slice()));
}

/*
 * Tests
 */
#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use super::{parse_kv, encode_kv};

    fn split_encoded(string: &[u8]) -> Vec<&[u8]> {
        let mut pairs: Vec<&[u8]> = string.split(|&c| c == b'&').collect();
        pairs.sort();
        pairs
    }

    #[test]
    fn test_parse_encode_kv() {
        let mut map: HashMap<String, String> = HashMap::new();
        let encoded: Vec<u8> = b"foo=bar&baz=qux&zap=zazzle".to_vec();
        map.insert("foo".into_string(), "bar".into_string());
        map.insert("baz".into_string(), "qux".into_string());
        map.insert("zap".into_string(), "zazzle".into_string());
        assert_eq!(map, parse_kv(encoded.as_slice()));
        assert_eq!(split_encoded(encode_kv(map).as_slice()),
                   split_encoded(encoded.as_slice()));
    }
}
<|endoftext|>


<commit_before><commit_msg>Added imax/imin() as variations of iamax/iamin()<commit_after><|endoftext|>


<commit_before>use executable::Executable;
use file::read;
use solution::Solution;
use std::cmp::max;
use test::stats;
use time::precise_time_ns;

static MAX_BENCH_TIME: u64 = 3_000_000_000;
static MIN_BENCH_TIME: u64 = 100_000_000;
static NSAMPLES: uint = 50;
static WINSORIZE_PCT: f64 = 5.0;

#[deriving(Encodable)]
pub struct Metric<'a> {
    language: &'a str,
    median: f64,
    noise: f64,
}

impl<'l> Metric<'l> {
    pub fn median(&self) -> f64 {
        self.median
    }
}

pub fn benchmark<'l, 'p>(solution: &Solution<'l, 'p>) -> Option<Metric<'l>> {
    let language = solution.language();
    let problem = solution.problem();

    let compiler_output = language.compiler().map(|compiler| {
        compiler.compile(solution.file())
    });

    let executable = match compiler_output {
        None => Executable::new(solution.file(), language.interpreter()),
        Some(ref output) => {
            Executable::new(output.binary(), language.interpreter())
        },
    };

    if executable.test() == read(problem.answer()) {
        println!("Incorrect answer");

        return None;
    }

    // this block implements the algorithm used for the Rust bencher framework
    let mut n = max(1_000_000 / max(executable.bench(1), 1), 1);
    let mut samples = [0.0, ..NSAMPLES];
    let mut summ5;
    let mut total_run = 0;
    loop {
        let loop_start = precise_time_ns();

        for sample in samples.mut_iter() {
            *sample = executable.bench(n) as f64;
        };

        stats::winsorize(samples, WINSORIZE_PCT);
        let summ = stats::Summary::new(samples);

        for sample in samples.mut_iter() {
            *sample = executable.bench(5 * n) as f64;
        };

        stats::winsorize(samples, WINSORIZE_PCT);
        summ5 = stats::Summary::new(samples);

        let now = precise_time_ns();
        let loop_run = now - loop_start;

        if loop_run > MIN_BENCH_TIME &&
            summ.median_abs_dev_pct < 1.0 &&
            summ.median - summ5.median < summ5.median_abs_dev {
            break;
        }

        total_run += loop_run;

        if total_run > MAX_BENCH_TIME {
            break;
        }

        n *= 2;
    }
    // end of block

    let median = if summ5.median < 1.0 { 1.0 } else { summ5.median };
    let noise = summ5.max - summ5.min;

    println!("{} ns (+/- {})", median as u64, noise as u64);

    Some(Metric {
        language: language.name(),
        median: median,
        noise: noise,
    })
}
<commit_msg>eulermark: report "ns/iter" instead of just "ns"<commit_after>use executable::Executable;
use file::read;
use solution::Solution;
use std::cmp::max;
use test::stats;
use time::precise_time_ns;

static MAX_BENCH_TIME: u64 = 3_000_000_000;
static MIN_BENCH_TIME: u64 = 100_000_000;
static NSAMPLES: uint = 50;
static WINSORIZE_PCT: f64 = 5.0;

#[deriving(Encodable)]
pub struct Metric<'a> {
    language: &'a str,
    median: f64,
    noise: f64,
}

impl<'l> Metric<'l> {
    pub fn median(&self) -> f64 {
        self.median
    }
}

pub fn benchmark<'l, 'p>(solution: &Solution<'l, 'p>) -> Option<Metric<'l>> {
    let language = solution.language();
    let problem = solution.problem();

    let compiler_output = language.compiler().map(|compiler| {
        compiler.compile(solution.file())
    });

    let executable = match compiler_output {
        None => Executable::new(solution.file(), language.interpreter()),
        Some(ref output) => {
            Executable::new(output.binary(), language.interpreter())
        },
    };

    if executable.test() == read(problem.answer()) {
        println!("Incorrect answer");

        return None;
    }

    // this block implements the algorithm used for the Rust bencher framework
    let mut n = max(1_000_000 / max(executable.bench(1), 1), 1);
    let mut samples = [0.0, ..NSAMPLES];
    let mut summ5;
    let mut total_run = 0;
    loop {
        let loop_start = precise_time_ns();

        for sample in samples.mut_iter() {
            *sample = executable.bench(n) as f64;
        };

        stats::winsorize(samples, WINSORIZE_PCT);
        let summ = stats::Summary::new(samples);

        for sample in samples.mut_iter() {
            *sample = executable.bench(5 * n) as f64;
        };

        stats::winsorize(samples, WINSORIZE_PCT);
        summ5 = stats::Summary::new(samples);

        let now = precise_time_ns();
        let loop_run = now - loop_start;

        if loop_run > MIN_BENCH_TIME &&
            summ.median_abs_dev_pct < 1.0 &&
            summ.median - summ5.median < summ5.median_abs_dev {
            break;
        }

        total_run += loop_run;

        if total_run > MAX_BENCH_TIME {
            break;
        }

        n *= 2;
    }
    // end of block

    let median = if summ5.median < 1.0 { 1.0 } else { summ5.median };
    let noise = summ5.max - summ5.min;

    println!("{} ns/iter (+/- {})", median as u64, noise as u64);

    Some(Metric {
        language: language.name(),
        median: median,
        noise: noise,
    })
}
<|endoftext|>


<commit_before>
struct Node {
    keys: Vec<i32>,
    vals: Option<Vec<i32>>,
    children: Option<Vec<Box<Node>>>
}

struct KeyNodePair(i32, Box<Node>);

pub struct BTree {
    root: Option<Box<Node>>,
    max: usize
}

impl BTree {
    pub fn new(max: usize) -> BTree {
        BTree{ root: None, max: max }
    }

    pub fn get(&self, key: i32) -> Option<i32> {
        match self.root {
            None => None,
            Some(ref node) => node.get(key)
        }
    }

    pub fn insert(&mut self, key: i32, value: i32) -> Option<i32> {
        match self.root {
            None => {
                self.root = Node::new_leaf(key, value);
                None
            },
            Some(_) => {
                let (prev, split) = self.root.as_mut().unwrap().insert(key, value, self.max);
                if split.is_some() {
                    let KeyNodePair(key, child) = split.unwrap();
                    let children = vec![self.root.take().unwrap(), child];
                    self.root = Node::new_root(key, children);
                }
                prev
            }
        }
    }
}

impl KeyNodePair {
    fn new(
        key: i32,
        keys: Vec<i32>,
        vals: Option<Vec<i32>>,
        children: Option<Vec<Box<Node>>>) -> KeyNodePair {
            KeyNodePair(key, Box::new(Node{keys:keys, vals:vals, children: children}))
    }
}

impl Node {

    fn new_leaf(key: i32, value: i32) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: Some(vec![value]), children: None }))
    }

    fn new_root(key: i32, children: Vec<Box<Node>>) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: None, children: Some(children) }))
    }

    fn get(&self, key: i32) -> Option<i32> {
        let position = self.keys.binary_search(&key);
        if self.vals.is_none() {
            let index = Node::index(position);
            self.child(index).get(key)
        } else {
            match position {
                Ok(index) => Some(self.value(index)),
                Err(_) => None
            }
        }
    }

    fn split(&mut self, max: usize) -> Option<KeyNodePair> {
        if self.keys.len() > max {
            let partition = self.keys.len() / 2;
            match self.children {
                Some(ref mut children) => {
                    let mut newkeys = self.keys.split_off(partition);
                    let newchildren = children.split_off(partition + 1);
                    let newkey = newkeys.remove(0);
                    Some(KeyNodePair::new(newkey, newkeys, None, Some(newchildren)))
                },
                None => {
                    let newkeys = self.keys.split_off(partition);
                    let newvals = Some(self.mut_values().split_off(partition));
                    Some(KeyNodePair::new(newkeys[0], newkeys, newvals, None))
                }
            }
        } else {
            None
        }
    }

    fn insert(&mut self, key: i32, value: i32, max: usize) -> (Option<i32>, Option<KeyNodePair>) {
        let position = self.keys.binary_search(&key);
        let prev = match self.children {
            Some(ref mut children) => {
                let index = Node::index(position);
                let (prev, newchild) = children[index].insert(key, value, max);
                if newchild.is_some() {
                    let KeyNodePair(key, newchild) = newchild.unwrap();
                    let index = Node::index(self.keys.binary_search(&key));
                    self.keys.insert(index, key);
                    children.insert(index + 1, newchild);
                }
                prev
            },
            None => {
                let prev = match position {
                    Ok(index) => Some(self.value(index)),
                    Err(_) => None
                };
                match position {
                    Ok(index) => {
                        self.mut_values()[index] = value;
                    },
                    Err(index) => {
                        self.keys.insert(index, value);
                        self.mut_values().insert(index, value);
                    }
                };
                prev
            }
        };
        (prev, self.split(max))
    }

    fn index(position: Result<usize,usize>) -> usize {
        match position {
            Ok(index) => index + 1,
            Err(index) => index,
        }
    }

    fn ref_values(&self) -> &Vec<i32> {
        self.vals.as_ref().unwrap()
    }

    fn mut_values(&mut self) -> &mut Vec<i32> {
        self.vals.as_mut().unwrap()
    }

    fn ref_children(&self) -> &Vec<Box<Node>> {
        self.children.as_ref().unwrap()
    }

    fn value(&self, index: usize) -> i32 {
        *self.ref_values().get(index).unwrap()
    }

    fn child(&self, index: usize) -> &Box<Node> {
        self.ref_children().get(index).unwrap()
    }
}

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

    #[test]
    fn basic_construction() {
        let mut tree = BTree::new(2);
        assert_eq!(tree.get(0), None);
        assert_eq!(tree.insert(0, 1), None);
        assert_eq!(tree.insert(0, 2), Some(1));
        assert_eq!(tree.get(0), Some(2));
    }

    #[test]
    fn insert_sequence() {
        let mut tree = BTree::new(2);
        for i in 0..256 {
            assert_eq!(tree.insert(i, i), None);
            assert_eq!(tree.get(i), Some(i));
        }
    }
}
<commit_msg>Add documentation for btree.<commit_after>
struct Node {
    keys: Vec<i32>,
    vals: Option<Vec<i32>>,
    children: Option<Vec<Box<Node>>>
}

struct KeyNodePair(i32, Box<Node>);

pub struct BTree {
    root: Option<Box<Node>>,
    max: usize
}

impl BTree {
    /// Makes a new empty BTree.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    ///
    /// // entries can now be inserted into the empty map
    /// map.insert(1, 1);
    /// ```
    pub fn new(max: usize) -> BTree {
        BTree{ root: None, max: max }
    }

    /// Returns the value corresponding to the key.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    /// map.insert(1, 1);
    /// assert_eq!(map.get(1), Some(1));
    /// assert_eq!(map.get(2), None);
    /// ```
    pub fn get(&self, key: i32) -> Option<i32> {
        match self.root {
            None => None,
            Some(ref node) => node.get(key)
        }
    }

    /// Returns true if the map contains no elements.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut a = BTree::new(16);
    /// assert!(a.is_empty());
    /// a.insert(1, 1);
    /// assert!(!a.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// Inserts a key-value pair into the map.
    ///
    /// If the map did not have this key present, `None` is returned.
    ///
    /// If the map did have this key present, the value is updated, and the old
    /// value is returned.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    /// assert_eq!(map.insert(37, 1), None);
    /// assert_eq!(map.is_empty(), false);
    ///
    /// map.insert(37, 2);
    /// assert_eq!(map.insert(37, 3), Some(2));
    /// ```
    pub fn insert(&mut self, key: i32, value: i32) -> Option<i32> {
        match self.root {
            None => {
                self.root = Node::new_leaf(key, value);
                None
            },
            Some(_) => {
                let (prev, split) = self.root.as_mut().unwrap().insert(key, value, self.max);
                if split.is_some() {
                    let KeyNodePair(key, child) = split.unwrap();
                    let children = vec![self.root.take().unwrap(), child];
                    self.root = Node::new_root(key, children);
                }
                prev
            }
        }
    }
}

impl KeyNodePair {
    fn new(
        key: i32,
        keys: Vec<i32>,
        vals: Option<Vec<i32>>,
        children: Option<Vec<Box<Node>>>) -> KeyNodePair {
            KeyNodePair(key, Box::new(Node{keys:keys, vals:vals, children: children}))
    }
}

impl Node {

    fn new_leaf(key: i32, value: i32) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: Some(vec![value]), children: None }))
    }

    fn new_root(key: i32, children: Vec<Box<Node>>) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: None, children: Some(children) }))
    }

    fn get(&self, key: i32) -> Option<i32> {
        let position = self.keys.binary_search(&key);
        if self.vals.is_none() {
            let index = Node::index(position);
            self.child(index).get(key)
        } else {
            match position {
                Ok(index) => Some(self.value(index)),
                Err(_) => None
            }
        }
    }

    fn split(&mut self, max: usize) -> Option<KeyNodePair> {
        if self.keys.len() > max {
            let partition = self.keys.len() / 2;
            match self.children {
                Some(ref mut children) => {
                    let mut newkeys = self.keys.split_off(partition);
                    let newchildren = children.split_off(partition + 1);
                    let newkey = newkeys.remove(0);
                    Some(KeyNodePair::new(newkey, newkeys, None, Some(newchildren)))
                },
                None => {
                    let newkeys = self.keys.split_off(partition);
                    let newvals = Some(self.mut_values().split_off(partition));
                    Some(KeyNodePair::new(newkeys[0], newkeys, newvals, None))
                }
            }
        } else {
            None
        }
    }

    fn insert(&mut self, key: i32, value: i32, max: usize) -> (Option<i32>, Option<KeyNodePair>) {
        let position = self.keys.binary_search(&key);
        let prev = match self.children {
            Some(ref mut children) => {
                let index = Node::index(position);
                let (prev, newchild) = children[index].insert(key, value, max);
                if newchild.is_some() {
                    let KeyNodePair(key, newchild) = newchild.unwrap();
                    let index = Node::index(self.keys.binary_search(&key));
                    self.keys.insert(index, key);
                    children.insert(index + 1, newchild);
                }
                prev
            },
            None => {
                let prev = match position {
                    Ok(index) => Some(self.value(index)),
                    Err(_) => None
                };
                match position {
                    Ok(index) => {
                        self.mut_values()[index] = value;
                    },
                    Err(index) => {
                        self.keys.insert(index, value);
                        self.mut_values().insert(index, value);
                    }
                };
                prev
            }
        };
        (prev, self.split(max))
    }

    fn index(position: Result<usize,usize>) -> usize {
        match position {
            Ok(index) => index + 1,
            Err(index) => index,
        }
    }

    fn ref_values(&self) -> &Vec<i32> {
        self.vals.as_ref().unwrap()
    }

    fn mut_values(&mut self) -> &mut Vec<i32> {
        self.vals.as_mut().unwrap()
    }

    fn ref_children(&self) -> &Vec<Box<Node>> {
        self.children.as_ref().unwrap()
    }

    fn value(&self, index: usize) -> i32 {
        *self.ref_values().get(index).unwrap()
    }

    fn child(&self, index: usize) -> &Box<Node> {
        self.ref_children().get(index).unwrap()
    }
}

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

    #[test]
    fn basic_construction() {
        let mut tree = BTree::new(2);
        assert_eq!(tree.get(0), None);
        assert_eq!(tree.insert(0, 1), None);
        assert_eq!(tree.insert(0, 2), Some(1));
        assert_eq!(tree.get(0), Some(2));
    }

    #[test]
    fn insert_sequence() {
        let mut tree = BTree::new(2);
        for i in 0..256 {
            assert_eq!(tree.insert(i, i), None);
            assert_eq!(tree.get(i), Some(i));
        }
    }
}
<|endoftext|>


<commit_before>//! This provides wrappers around the `StdoutTerminal` and `StderrTerminal` types
//! that does not fail if `StdoutTerminal` etc can't be constructed, which happens
//! if TERM isn't defined.

use lazy_static::lazy_static;
use rustup::utils::tty;
use std::io;
use std::sync::Mutex;

pub use term::color;
pub use term::Attr;
pub use term::Terminal;

mod termhack {
    // Things we should submit to term as improvements: here temporarily.
    use std::collections::HashMap;
    use std::io;
    use term::terminfo::TermInfo;
    #[cfg(windows)]
    use term::WinConsole;
    use term::{StderrTerminal, StdoutTerminal, Terminal, TerminfoTerminal};

    // Works around stdio instances being unclonable.
    pub trait Instantiable {
        fn instance() -> Self;
    }

    impl Instantiable for io::Stdout {
        fn instance() -> Self {
            io::stdout()
        }
    }

    impl Instantiable for io::Stderr {
        fn instance() -> Self {
            io::stderr()
        }
    }

    /// Return a Terminal object for T on this platform.
    /// If there is no terminfo and the platform requires terminfo, then None is returned.
    fn make_terminal<T>(terminfo: Option<TermInfo>) -> Option<Box<Terminal<Output = T> + Send>>
    where
        T: 'static + io::Write + Send + Instantiable,
    {
        let mut result = terminfo
            .map(move |ti| TerminfoTerminal::new_with_terminfo(T::instance(), ti.clone()))
            .map(|t| Box::new(t) as Box<Terminal<Output = T> + Send>);
        #[cfg(windows)]
        {
            result = result.or_else(|| {
                WinConsole::new(T::instance())
                    .ok()
                    .map(|t| Box::new(t) as Box<Terminal<Output = T> + Send>)
            })
        }
        result
    }

    fn make_terminal_with_fallback<T>(
        terminfo: Option<TermInfo>,
    ) -> Box<Terminal<Output = T> + Send>
    where
        T: 'static + io::Write + Send + Instantiable,
    {
        make_terminal(terminfo)
            .or_else(|| {
                let ti = TermInfo {
                    names: vec![],
                    bools: HashMap::new(),
                    numbers: HashMap::new(),
                    strings: HashMap::new(),
                };
                let t = TerminfoTerminal::new_with_terminfo(T::instance(), ti);
                Some(Box::new(t) as Box<Terminal<Output = T> + Send>)
            })
            .unwrap()
    }
    /// Return a Terminal wrapping stdout, or None if a terminal couldn't be
    /// opened.
    #[allow(unused)]
    pub fn stdout(terminfo: Option<TermInfo>) -> Option<Box<StdoutTerminal>> {
        make_terminal(terminfo)
    }

    /// Return a Terminal wrapping stderr, or None if a terminal couldn't be
    /// opened.
    #[allow(unused)]
    pub fn stderr(terminfo: Option<TermInfo>) -> Option<Box<StderrTerminal>> {
        make_terminal(terminfo)
    }

    /// Return a Terminal wrapping stdout.
    pub fn stdout_with_fallback(terminfo: Option<TermInfo>) -> Box<StdoutTerminal> {
        make_terminal_with_fallback(terminfo)
    }

    /// Return a Terminal wrapping stderr.
    pub fn stderr_with_fallback(terminfo: Option<TermInfo>) -> Box<StderrTerminal> {
        make_terminal_with_fallback(terminfo)
    }
}

pub trait Isatty {
    fn isatty() -> bool;
}

impl Isatty for io::Stdout {
    fn isatty() -> bool {
        tty::stdout_isatty()
    }
}

impl Isatty for io::Stderr {
    fn isatty() -> bool {
        tty::stderr_isatty()
    }
}

// Decorator to:
// - Disable all terminal controls on non-tty's
// - Swallow errors when we try to use features a terminal doesn't have
//   such as setting colours when no TermInfo DB is present
pub struct AutomationFriendlyTerminal<T>(Box<dyn term::Terminal<Output = T> + Send>)
where
    T: Isatty + io::Write;
pub type StdoutTerminal = AutomationFriendlyTerminal<io::Stdout>;
pub type StderrTerminal = AutomationFriendlyTerminal<io::Stderr>;

macro_rules! swallow_unsupported {
    ( $call:expr ) => {{
        use term::Error::*;
        match $call {
            Ok(()) | Err(ColorOutOfRange) | Err(NotSupported) => Ok(()),
            Err(e) => Err(e),
        }
    }};
}

impl<T> term::Terminal for AutomationFriendlyTerminal<T>
where
    T: io::Write + Isatty,
{
    type Output = T;

    fn fg(&mut self, color: color::Color) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }
        swallow_unsupported!(self.0.fg(color))
    }

    fn bg(&mut self, color: color::Color) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }
        swallow_unsupported!(self.0.bg(color))
    }

    fn attr(&mut self, attr: Attr) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }

        if let Err(e) = self.0.attr(attr) {
            // If `attr` is not supported, try to emulate it
            match attr {
                Attr::Bold => swallow_unsupported!(self.0.fg(color::BRIGHT_WHITE)),
                _ => swallow_unsupported!(Err(e)),
            }
        } else {
            Ok(())
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        self.0.supports_attr(attr)
    }

    fn reset(&mut self) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }
        swallow_unsupported!(self.0.reset())
    }

    /// Returns true if reset is supported.
    fn supports_reset(&self) -> bool {
        self.0.supports_reset()
    }

    fn supports_color(&self) -> bool {
        self.0.supports_color()
    }

    fn cursor_up(&mut self) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }

        swallow_unsupported!(self.0.cursor_up())
    }

    fn delete_line(&mut self) -> term::Result<()> {
        swallow_unsupported!(self.0.delete_line())
    }

    fn carriage_return(&mut self) -> term::Result<()> {
        // This might leak control chars in !isatty? needs checking.
        swallow_unsupported!(self.0.carriage_return())
    }

    fn get_ref(&self) -> &Self::Output {
        self.0.get_ref()
    }

    fn get_mut(&mut self) -> &mut Self::Output {
        self.0.get_mut()
    }

    /// Returns the contained stream, destroying the `Terminal`
    fn into_inner(self) -> Self::Output
    where
        Self: Sized,
    {
        unimplemented!()
        // self.0.into_inner().into_inner()
    }
}

impl<T: Isatty + io::Write> io::Write for AutomationFriendlyTerminal<T> {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        self.0.flush()
    }
}

lazy_static! {
    // Cache the terminfo database for performance.
    // Caching the actual terminals may be better, as on Windows terminal
    // detection is per-fd, but this at least avoids the IO subsystem and
    // caching the stdout instances is more complex
    static ref TERMINFO: Mutex<Option<term::terminfo::TermInfo>> =
        Mutex::new(term::terminfo::TermInfo::from_env().ok());
}

pub fn stdout() -> StdoutTerminal {
    let info_result = TERMINFO.lock().unwrap().clone();
    AutomationFriendlyTerminal(termhack::stdout_with_fallback(info_result))
}

pub fn stderr() -> StderrTerminal {
    let info_result = TERMINFO.lock().unwrap().clone();
    AutomationFriendlyTerminal(termhack::stderr_with_fallback(info_result))
}
<commit_msg>Rebind to remove unused_mut warning<commit_after>//! This provides wrappers around the `StdoutTerminal` and `StderrTerminal` types
//! that does not fail if `StdoutTerminal` etc can't be constructed, which happens
//! if TERM isn't defined.

use lazy_static::lazy_static;
use rustup::utils::tty;
use std::io;
use std::sync::Mutex;

pub use term::color;
pub use term::Attr;
pub use term::Terminal;

mod termhack {
    // Things we should submit to term as improvements: here temporarily.
    use std::collections::HashMap;
    use std::io;
    use term::terminfo::TermInfo;
    use term::{StderrTerminal, StdoutTerminal, Terminal, TerminfoTerminal};

    // Works around stdio instances being unclonable.
    pub trait Instantiable {
        fn instance() -> Self;
    }

    impl Instantiable for io::Stdout {
        fn instance() -> Self {
            io::stdout()
        }
    }

    impl Instantiable for io::Stderr {
        fn instance() -> Self {
            io::stderr()
        }
    }

    /// Return a Terminal object for T on this platform.
    /// If there is no terminfo and the platform requires terminfo, then None is returned.
    fn make_terminal<T>(terminfo: Option<TermInfo>) -> Option<Box<Terminal<Output = T> + Send>>
    where
        T: 'static + io::Write + Send + Instantiable,
    {
        let result = terminfo
            .map(move |ti| TerminfoTerminal::new_with_terminfo(T::instance(), ti.clone()))
            .map(|t| Box::new(t) as Box<Terminal<Output = T> + Send>);
        #[cfg(windows)]
        {
            result.or_else(|| {
                term::WinConsole::new(T::instance())
                    .ok()
                    .map(|t| Box::new(t) as Box<Terminal<Output = T> + Send>)
            })
        }
        #[cfg(not(windows))]
        {
            result
        }
    }

    fn make_terminal_with_fallback<T>(
        terminfo: Option<TermInfo>,
    ) -> Box<Terminal<Output = T> + Send>
    where
        T: 'static + io::Write + Send + Instantiable,
    {
        make_terminal(terminfo)
            .or_else(|| {
                let ti = TermInfo {
                    names: vec![],
                    bools: HashMap::new(),
                    numbers: HashMap::new(),
                    strings: HashMap::new(),
                };
                let t = TerminfoTerminal::new_with_terminfo(T::instance(), ti);
                Some(Box::new(t) as Box<Terminal<Output = T> + Send>)
            })
            .unwrap()
    }
    /// Return a Terminal wrapping stdout, or None if a terminal couldn't be
    /// opened.
    #[allow(unused)]
    pub fn stdout(terminfo: Option<TermInfo>) -> Option<Box<StdoutTerminal>> {
        make_terminal(terminfo)
    }

    /// Return a Terminal wrapping stderr, or None if a terminal couldn't be
    /// opened.
    #[allow(unused)]
    pub fn stderr(terminfo: Option<TermInfo>) -> Option<Box<StderrTerminal>> {
        make_terminal(terminfo)
    }

    /// Return a Terminal wrapping stdout.
    pub fn stdout_with_fallback(terminfo: Option<TermInfo>) -> Box<StdoutTerminal> {
        make_terminal_with_fallback(terminfo)
    }

    /// Return a Terminal wrapping stderr.
    pub fn stderr_with_fallback(terminfo: Option<TermInfo>) -> Box<StderrTerminal> {
        make_terminal_with_fallback(terminfo)
    }
}

pub trait Isatty {
    fn isatty() -> bool;
}

impl Isatty for io::Stdout {
    fn isatty() -> bool {
        tty::stdout_isatty()
    }
}

impl Isatty for io::Stderr {
    fn isatty() -> bool {
        tty::stderr_isatty()
    }
}

// Decorator to:
// - Disable all terminal controls on non-tty's
// - Swallow errors when we try to use features a terminal doesn't have
//   such as setting colours when no TermInfo DB is present
pub struct AutomationFriendlyTerminal<T>(Box<dyn term::Terminal<Output = T> + Send>)
where
    T: Isatty + io::Write;
pub type StdoutTerminal = AutomationFriendlyTerminal<io::Stdout>;
pub type StderrTerminal = AutomationFriendlyTerminal<io::Stderr>;

macro_rules! swallow_unsupported {
    ( $call:expr ) => {{
        use term::Error::*;
        match $call {
            Ok(()) | Err(ColorOutOfRange) | Err(NotSupported) => Ok(()),
            Err(e) => Err(e),
        }
    }};
}

impl<T> term::Terminal for AutomationFriendlyTerminal<T>
where
    T: io::Write + Isatty,
{
    type Output = T;

    fn fg(&mut self, color: color::Color) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }
        swallow_unsupported!(self.0.fg(color))
    }

    fn bg(&mut self, color: color::Color) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }
        swallow_unsupported!(self.0.bg(color))
    }

    fn attr(&mut self, attr: Attr) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }

        if let Err(e) = self.0.attr(attr) {
            // If `attr` is not supported, try to emulate it
            match attr {
                Attr::Bold => swallow_unsupported!(self.0.fg(color::BRIGHT_WHITE)),
                _ => swallow_unsupported!(Err(e)),
            }
        } else {
            Ok(())
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        self.0.supports_attr(attr)
    }

    fn reset(&mut self) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }
        swallow_unsupported!(self.0.reset())
    }

    /// Returns true if reset is supported.
    fn supports_reset(&self) -> bool {
        self.0.supports_reset()
    }

    fn supports_color(&self) -> bool {
        self.0.supports_color()
    }

    fn cursor_up(&mut self) -> term::Result<()> {
        if !T::isatty() {
            return Ok(());
        }

        swallow_unsupported!(self.0.cursor_up())
    }

    fn delete_line(&mut self) -> term::Result<()> {
        swallow_unsupported!(self.0.delete_line())
    }

    fn carriage_return(&mut self) -> term::Result<()> {
        // This might leak control chars in !isatty? needs checking.
        swallow_unsupported!(self.0.carriage_return())
    }

    fn get_ref(&self) -> &Self::Output {
        self.0.get_ref()
    }

    fn get_mut(&mut self) -> &mut Self::Output {
        self.0.get_mut()
    }

    /// Returns the contained stream, destroying the `Terminal`
    fn into_inner(self) -> Self::Output
    where
        Self: Sized,
    {
        unimplemented!()
        // self.0.into_inner().into_inner()
    }
}

impl<T: Isatty + io::Write> io::Write for AutomationFriendlyTerminal<T> {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        self.0.flush()
    }
}

lazy_static! {
    // Cache the terminfo database for performance.
    // Caching the actual terminals may be better, as on Windows terminal
    // detection is per-fd, but this at least avoids the IO subsystem and
    // caching the stdout instances is more complex
    static ref TERMINFO: Mutex<Option<term::terminfo::TermInfo>> =
        Mutex::new(term::terminfo::TermInfo::from_env().ok());
}

pub fn stdout() -> StdoutTerminal {
    let info_result = TERMINFO.lock().unwrap().clone();
    AutomationFriendlyTerminal(termhack::stdout_with_fallback(info_result))
}

pub fn stderr() -> StderrTerminal {
    let info_result = TERMINFO.lock().unwrap().clone();
    AutomationFriendlyTerminal(termhack::stderr_with_fallback(info_result))
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_ttf;
use sdl2::render::{Renderer, BlendMode};
use sdl2::pixels::Color;
use std::env;
use font::*;
use display::{self, Display};
use subtitles::Subtitles;
use utils::*;

pub struct Displayer<'a> {
    fonts: FontList,
    renderer: Renderer<'a>,
    #[allow(dead_code)]
    ttf_context: sdl2_ttf::Sdl2TtfContext,
    subtitles: Option<Subtitles>,
}

mod subtitles_display {
    use sdl2::pixels::Color;
    pub const DEFAULT_SUB_COLORS : (Color,Color,Color) = (Color::RGB(0, 0xFF, 0xFF),
                                              Color::RGB(0xFF, 0, 0),
                                              Color::RGB(0xFF, 0xFF, 0));
    pub const DEFAULT_FADE_INTERVAL: u32 = 10;
    pub const DEFAULT_TRANSITION_INTERVAL: u32 = DEFAULT_FADE_INTERVAL + 5;

    #[derive(Copy,Clone)]
    pub struct Options {
        pub fade_interval:u32,
        pub transition_interval:u32,
        pub sub_colors:(Color,Color,Color)
    }

    impl Options {
        pub fn new() -> Options {
            Options {
                fade_interval:DEFAULT_FADE_INTERVAL,
                transition_interval:DEFAULT_TRANSITION_INTERVAL,
                sub_colors:DEFAULT_SUB_COLORS
            }
        }

        pub fn with_transition_interval(mut self,value:u32) -> Options {
            self.transition_interval = value;
            self
        }

        pub fn with_fade_interval(mut self,value:u32) -> Options {
            self.fade_interval =value;
            self
        }

        /// alive : not yet displayed;
        /// active: being displayed;
        /// dead: finished being displayed
        pub fn with_sub_colors(mut self,alive:Color,active:Color,dead:Color) -> Options {
            self.sub_colors = (alive,active,dead);
            self
        }
    }
}

impl<'a> Displayer<'a> {
    pub fn new(mut renderer: Renderer<'a>,
               subtitles: Option<Subtitles>)
               -> Result<Displayer<'a>, ()> {
        renderer.set_blend_mode(BlendMode::Blend);
        let ttf_context = sdl2_ttf::init().unwrap();
        let font_list = FontList::new(&ttf_context).unwrap();
        let displayer = Displayer {
            fonts: font_list,
            ttf_context: ttf_context,
            renderer: renderer,
            subtitles: subtitles,
        };
        Ok(displayer)
    }

    fn add_syllabus(mut text_elts : &mut Vec<display::TextElement>,
                    syllabus:&str,
                    current_frame:u32,
                    frame_begin:u32,
                    frame_end:u32,
                    alpha:f32,
                    sub_options:subtitles_display::Options) {
        if (current_frame < frame_begin) {
            // not yet

            let text_2d = display::TextElement {
                text: String::from(syllabus),
                color: fade_color(sub_options.sub_colors.2, alpha),
                outline: Some(Color::RGB(0, 0, 0)),
                shadow: None,
            };
            text_elts.push(text_2d);

        } else if (frame_begin <= current_frame) && (current_frame <= frame_end) {
            let percent = (current_frame - frame_begin) as f32 /
                          (frame_end - frame_begin) as f32;
            // lets ease the percent a lil bits
            let percent = 1.0 - (1.0 - percent).sqrt();
            // let percent = (percent * consts::PI / 2.0).sin();
            let transition_color = mix_colors(sub_options.sub_colors.1, sub_options.sub_colors.0, percent);
            let text_2d = display::TextElement {
                text: String::from(syllabus),
                color: transition_color,
                outline: Some(Color::RGB(0, 0, 0)),
                shadow: None,
            };
            text_elts.push(text_2d);
        } else {
            if (text_elts.is_empty()) {
                let text_2d = display::TextElement {
                    text: String::from(syllabus),
                    color: fade_color(sub_options.sub_colors.0, alpha),
                    outline: Some(Color::RGB(0, 0, 0)),
                    shadow: None,
                };
                text_elts.push(text_2d);
            } else {
                let mut text_2d = text_elts.last_mut().unwrap();
                text_2d.text.push_str(&syllabus);
            }
        }
    }

    pub fn error_message(&self,title:&str,info:&str) {
        ::sdl2::messagebox::show_simple_message_box(::sdl2::messagebox::MESSAGEBOX_ERROR,
                                                    title,
                                                    info,
                                                    self.sdl_renderer().window());
    }

    pub fn render_subtitles(&mut self, frame_number: u32) {
        let (w,h) = self.renderer.output_size().expect("unable to get renderer size");
        let mut target_texture = self.renderer.create_texture_target(sdl2::pixels::PixelFormatEnum::ARGB8888,
                                                                 w,
                                                                 h).expect("Unable to create texture");
        target_texture.set_blend_mode(BlendMode::Blend);
        let original_texture : Option<_> = self.renderer.render_target()
                                                        .expect("Unsupported graphic card")
                                                        .set(target_texture)
                                                        .unwrap();
        let sub_colors = (Color::RGB(0, 0xFF, 0xFF),
                          Color::RGB(0xFF, 0, 0),
                          Color::RGB(0xFF, 0xFF, 0));
        let mut text2d_vec = vec![];
        let sub_options = subtitles_display::Options::new();
        let finished_fade_interval = sub_options.transition_interval - sub_options.fade_interval;
        match self.subtitles {
            Some(ref subtitles) => {
                let subtitles = subtitles.get_subtitles();
                let iter = subtitles.iter().enumerate().filter(|&(_, line)| {
                    match (line.first(), line.last()) {
                        (Some(&(_, (frame_begin, _))), Some(&(_, (_, frame_end)))) => {
                            frame_begin.saturating_sub(sub_options.transition_interval) < frame_number &&
                            frame_end.saturating_add(sub_options.transition_interval) > frame_number
                        }
                        _ => false,
                    }
                });
                for (i, line) in iter {
                    let text_pos_y = match i % 2 {
                        0 => display::PosY::FromTopPercent(0.02),
                        1 => display::PosY::FromTopPercent(0.12),
                        _ => unreachable!(),
                    };
                    let alpha: f32 = match (line.first(), line.last()) {
                        (Some(&(_, (frame_begin, _))), Some(&(_, (_, frame_end)))) => {

                            let begin_first_fade_frame =
                                frame_begin.saturating_sub(sub_options.transition_interval);
                            let end_first_fade_frame =
                                frame_begin.saturating_sub(finished_fade_interval);
                            let begin_second_fade_frame =
                                frame_end.saturating_add(finished_fade_interval);
                            let end_second_fade_frame =
                                frame_end.saturating_add(sub_options.transition_interval);
                            debug_assert_eq!(end_second_fade_frame - begin_second_fade_frame,
                                             sub_options.fade_interval);
                            if (end_first_fade_frame < frame_number &&
                                begin_second_fade_frame > frame_number) {
                                1.0
                            } else if begin_first_fade_frame <= frame_number &&
                               end_first_fade_frame >= frame_number {
                                (frame_number - begin_first_fade_frame) as f32 /
                                (end_first_fade_frame - begin_first_fade_frame) as f32
                            } else if begin_second_fade_frame <= frame_number &&
                               end_second_fade_frame >= frame_number {
                                1.0 -
                                ((frame_number - begin_second_fade_frame) as f32 /
                                 (end_second_fade_frame - begin_second_fade_frame) as f32)
                            } else {
                                0.0
                            }
                        }
                        _ => 0.0,
                    };
                    let mut text_elts = Vec::new();
                    for &(ref syllabus,(frame_begin,frame_end)) in line.iter() {
                        Self::add_syllabus(&mut text_elts,syllabus,frame_number,frame_begin,frame_end,alpha,sub_options);
                    }
                    let text_2d = display::Text2D {
                        text: text_elts,
                        size: display::Size::FitPercent(Some(0.95), Some(0.1)),
                        pos: (display::PosX::Centered, text_pos_y),
                        anchor: (0.5, 0.0),
                    };
                    text2d_vec.push(text_2d);
                }
            }
            None => {}
        };
        for text_2d in text2d_vec.into_iter() {
            text_2d.draw(self);
        };
        // TODO : restore first texture instead of asssuming it's window every time
        let target_texture = self.renderer.render_target().unwrap().reset().unwrap().unwrap();
        self.renderer.copy(&target_texture,None,None);
    }

    // width and height must be between 0 and 1
    pub fn sub_screen_dims(&self,
                           width: Option<f32>,
                           height: Option<f32>)
                           -> (Option<u32>, Option<u32>) {
        let dims: (u32, u32) = self.renderer.window().unwrap().size();
        (width.and_then(|width| Some((width * (dims.0 as f32)) as u32)),
         height.and_then(|height| Some((height * (dims.1 as f32)) as u32)))
    }

    pub fn render(&mut self) {
        self.sdl_renderer_mut().window().unwrap().gl_swap_window();
    }

    pub fn sdl_renderer_mut(&mut self) -> &mut Renderer<'a> {
        &mut self.renderer
    }

    pub fn sdl_renderer(&self) -> &Renderer<'a> {
        &self.renderer
    }

    pub fn fonts(&self) -> &FontList {
        &self.fonts
    }
}
<commit_msg>Changed formula for active-to-dead syllabus transition<commit_after>extern crate sdl2;
extern crate sdl2_ttf;
use sdl2::render::{Renderer, BlendMode};
use sdl2::pixels::Color;
use std::env;
use font::*;
use display::{self, Display};
use subtitles::Subtitles;
use utils::*;

pub struct Displayer<'a> {
    fonts: FontList,
    renderer: Renderer<'a>,
    #[allow(dead_code)]
    ttf_context: sdl2_ttf::Sdl2TtfContext,
    subtitles: Option<Subtitles>,
}

mod subtitles_display {
    use sdl2::pixels::Color;
    pub const DEFAULT_SUB_COLORS : (Color,Color,Color) = (Color::RGB(0, 0xFF, 0xFF),
                                              Color::RGB(0xFF, 0, 0),
                                              Color::RGB(0xFF, 0xFF, 0));
    pub const DEFAULT_FADE_INTERVAL: u32 = 10;
    pub const DEFAULT_TRANSITION_INTERVAL: u32 = DEFAULT_FADE_INTERVAL + 5;

    #[derive(Copy,Clone)]
    pub struct Options {
        pub fade_interval:u32,
        pub transition_interval:u32,
        pub sub_colors:(Color,Color,Color)
    }

    impl Options {
        pub fn new() -> Options {
            Options {
                fade_interval:DEFAULT_FADE_INTERVAL,
                transition_interval:DEFAULT_TRANSITION_INTERVAL,
                sub_colors:DEFAULT_SUB_COLORS
            }
        }

        pub fn with_transition_interval(mut self,value:u32) -> Options {
            self.transition_interval = value;
            self
        }

        pub fn with_fade_interval(mut self,value:u32) -> Options {
            self.fade_interval =value;
            self
        }

        /// alive : not yet displayed;
        /// active: being displayed;
        /// dead: finished being displayed
        pub fn with_sub_colors(mut self,alive:Color,active:Color,dead:Color) -> Options {
            self.sub_colors = (alive,active,dead);
            self
        }
    }
}

impl<'a> Displayer<'a> {
    pub fn new(mut renderer: Renderer<'a>,
               subtitles: Option<Subtitles>)
               -> Result<Displayer<'a>, ()> {
        renderer.set_blend_mode(BlendMode::Blend);
        let ttf_context = sdl2_ttf::init().unwrap();
        let font_list = FontList::new(&ttf_context).unwrap();
        let displayer = Displayer {
            fonts: font_list,
            ttf_context: ttf_context,
            renderer: renderer,
            subtitles: subtitles,
        };
        Ok(displayer)
    }

    fn add_syllabus(mut text_elts : &mut Vec<display::TextElement>,
                    syllabus:&str,
                    current_frame:u32,
                    frame_begin:u32,
                    frame_end:u32,
                    alpha:f32,
                    sub_options:subtitles_display::Options) {
        if (current_frame < frame_begin) {
            // not yet

            let text_2d = display::TextElement {
                text: String::from(syllabus),
                color: fade_color(sub_options.sub_colors.2, alpha),
                outline: Some(Color::RGB(0, 0, 0)),
                shadow: None,
            };
            text_elts.push(text_2d);

        } else if (frame_begin <= current_frame) && (current_frame <= frame_end) {
            let percent = (current_frame - frame_begin) as f32 /
                          (frame_end - frame_begin) as f32;
            // lets ease the percent a lil bits
            let percent = 1.0 - (1.0 - percent*percent).sqrt();
            // let percent = (percent * consts::PI / 2.0).sin();
            let transition_color = mix_colors(sub_options.sub_colors.1, sub_options.sub_colors.0, percent);
            let text_2d = display::TextElement {
                text: String::from(syllabus),
                color: transition_color,
                outline: Some(Color::RGB(0, 0, 0)),
                shadow: None,
            };
            text_elts.push(text_2d);
        } else {
            if (text_elts.is_empty()) {
                let text_2d = display::TextElement {
                    text: String::from(syllabus),
                    color: fade_color(sub_options.sub_colors.0, alpha),
                    outline: Some(Color::RGB(0, 0, 0)),
                    shadow: None,
                };
                text_elts.push(text_2d);
            } else {
                let mut text_2d = text_elts.last_mut().unwrap();
                text_2d.text.push_str(&syllabus);
            }
        }
    }

    pub fn error_message(&self,title:&str,info:&str) {
        ::sdl2::messagebox::show_simple_message_box(::sdl2::messagebox::MESSAGEBOX_ERROR,
                                                    title,
                                                    info,
                                                    self.sdl_renderer().window());
    }

    pub fn render_subtitles(&mut self, frame_number: u32) {
        let (w,h) = self.renderer.output_size().expect("unable to get renderer size");
        let mut target_texture = self.renderer.create_texture_target(sdl2::pixels::PixelFormatEnum::ARGB8888,
                                                                 w,
                                                                 h).expect("Unable to create texture");
        target_texture.set_blend_mode(BlendMode::Blend);
        let original_texture : Option<_> = self.renderer.render_target()
                                                        .expect("Unsupported graphic card")
                                                        .set(target_texture)
                                                        .unwrap();
        let sub_colors = (Color::RGB(0, 0xFF, 0xFF),
                          Color::RGB(0xFF, 0, 0),
                          Color::RGB(0xFF, 0xFF, 0));
        let mut text2d_vec = vec![];
        let sub_options = subtitles_display::Options::new();
        let finished_fade_interval = sub_options.transition_interval - sub_options.fade_interval;
        match self.subtitles {
            Some(ref subtitles) => {
                let subtitles = subtitles.get_subtitles();
                let iter = subtitles.iter().enumerate().filter(|&(_, line)| {
                    match (line.first(), line.last()) {
                        (Some(&(_, (frame_begin, _))), Some(&(_, (_, frame_end)))) => {
                            frame_begin.saturating_sub(sub_options.transition_interval) < frame_number &&
                            frame_end.saturating_add(sub_options.transition_interval) > frame_number
                        }
                        _ => false,
                    }
                });
                for (i, line) in iter {
                    let text_pos_y = match i % 2 {
                        0 => display::PosY::FromTopPercent(0.02),
                        1 => display::PosY::FromTopPercent(0.12),
                        _ => unreachable!(),
                    };
                    let alpha: f32 = match (line.first(), line.last()) {
                        (Some(&(_, (frame_begin, _))), Some(&(_, (_, frame_end)))) => {

                            let begin_first_fade_frame =
                                frame_begin.saturating_sub(sub_options.transition_interval);
                            let end_first_fade_frame =
                                frame_begin.saturating_sub(finished_fade_interval);
                            let begin_second_fade_frame =
                                frame_end.saturating_add(finished_fade_interval);
                            let end_second_fade_frame =
                                frame_end.saturating_add(sub_options.transition_interval);
                            debug_assert_eq!(end_second_fade_frame - begin_second_fade_frame,
                                             sub_options.fade_interval);
                            if (end_first_fade_frame < frame_number &&
                                begin_second_fade_frame > frame_number) {
                                1.0
                            } else if begin_first_fade_frame <= frame_number &&
                               end_first_fade_frame >= frame_number {
                                (frame_number - begin_first_fade_frame) as f32 /
                                (end_first_fade_frame - begin_first_fade_frame) as f32
                            } else if begin_second_fade_frame <= frame_number &&
                               end_second_fade_frame >= frame_number {
                                1.0 -
                                ((frame_number - begin_second_fade_frame) as f32 /
                                 (end_second_fade_frame - begin_second_fade_frame) as f32)
                            } else {
                                0.0
                            }
                        }
                        _ => 0.0,
                    };
                    let mut text_elts = Vec::new();
                    for &(ref syllabus,(frame_begin,frame_end)) in line.iter() {
                        Self::add_syllabus(&mut text_elts,syllabus,frame_number,frame_begin,frame_end,alpha,sub_options);
                    }
                    let text_2d = display::Text2D {
                        text: text_elts,
                        size: display::Size::FitPercent(Some(0.95), Some(0.1)),
                        pos: (display::PosX::Centered, text_pos_y),
                        anchor: (0.5, 0.0),
                    };
                    text2d_vec.push(text_2d);
                }
            }
            None => {}
        };
        for text_2d in text2d_vec.into_iter() {
            text_2d.draw(self);
        };
        // TODO : restore first texture instead of asssuming it's window every time
        let target_texture = self.renderer.render_target().unwrap().reset().unwrap().unwrap();
        self.renderer.copy(&target_texture,None,None);
    }

    // width and height must be between 0 and 1
    pub fn sub_screen_dims(&self,
                           width: Option<f32>,
                           height: Option<f32>)
                           -> (Option<u32>, Option<u32>) {
        let dims: (u32, u32) = self.renderer.window().unwrap().size();
        (width.and_then(|width| Some((width * (dims.0 as f32)) as u32)),
         height.and_then(|height| Some((height * (dims.1 as f32)) as u32)))
    }

    pub fn render(&mut self) {
        self.sdl_renderer_mut().window().unwrap().gl_swap_window();
    }

    pub fn sdl_renderer_mut(&mut self) -> &mut Renderer<'a> {
        &mut self.renderer
    }

    pub fn sdl_renderer(&self) -> &Renderer<'a> {
        &self.renderer
    }

    pub fn fonts(&self) -> &FontList {
        &self.fonts
    }
}
<|endoftext|>