<commit_before>//! Shapes in the game, like units (triangles) and buildings (squares).
extern crate graphics;
use self::graphics::types::Triangle;
use self::graphics::math;
use self::graphics::math::{sub, square_len};
use super::state;
use std::f64;

use common::Vec2;

pub trait Shape {
    fn get_shape(&self, size: f64) -> Triangle;

    fn is_hit(&self, size: f64, position: Vec2) -> bool;

    fn collision_detect(&self, other: &Self, size: f64) -> bool;
}

impl Shape for state::Unit {
    /// Return the base shape of the unit.
    fn get_shape(&self, radius: f64) -> Triangle {
        // calculate side length
        let a = radius * 3.0 / 3.0f64.sqrt();

        let mut triangle: Triangle = [
            [-radius,        0.0], // Left
            [ radius*0.5,  a/2.0], // Top right
            [ radius*0.5, -a/2.0], // Bottom right
        ];

        // Transformations
        for point in triangle.iter_mut() {
            // Rotate
            let rotation_matrix = math::rotate_radians(self.angle);
            *point = math::transform_vec(rotation_matrix, *point);

            // Translate to effective position
            *point = math::add(*point, self.position.into());
        }

        triangle
    }

    /// Calculate whether or not this unit is hit by the point at the specified position.
    fn is_hit(&self, size: f64, position: Vec2) -> bool {
        let hitbox = self.get_shape(size);
        math::inside_triangle(hitbox, position.into())
    }

    fn collision_detect(&self, other: &Self, size: f64) -> bool {
        let dv = sub(self.position.into(), other.position.into());
        square_len(dv) <= (2.0 * size * 2.0 * size)
    }
}

#[cfg(test)]
mod test {
    use std::f64::consts::FRAC_PI_2;

    use super::{Shape, Vec2, state};

    #[test]
    fn test_hitbox() {
        // Create a unit at position (100,100) that has been rotated by 90° CW.
        //
        //    /\
        //   /__\
        //
        let mut unit = state::Unit::new(0, Vec2::new(100.0, 100.0));
        unit.angle = FRAC_PI_2;

        // The following points should be outside of the hitbox.
        assert_eq!(unit.is_hit(50.0, Vec2::new(0.0, 0.0)), false);
        assert_eq!(unit.is_hit(50.0, Vec2::new(50.0, 50.0)), false);

        // The following five points should be inside the hitbox.
        //      .
        //     /.\
        //   ./_._\.
        //
        let vertical_distance = 50.0 / 2.0 - 1.0;
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0, 100.0)), true);
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0, 100.0 - vertical_distance)), true);
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0, 100.0 + vertical_distance)), true);
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0 - vertical_distance, 100.0 + vertical_distance)), true);
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0 + vertical_distance, 100.0 + vertical_distance)), true);

        // The following two points should be outside the hitbox.
        //
        //  . /\ .
        //   /__\
        //
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0 - vertical_distance, 100.0)), false);
        assert_eq!(unit.is_hit(50.0, Vec2::new(100.0 + vertical_distance, 100.0)), false);
    }
}
<commit_msg>Fix Shape unit tests<commit_after>//! Shapes in the game, like units (triangles) and buildings (squares).
extern crate graphics;
use self::graphics::types::Triangle;
use self::graphics::math;
use self::graphics::math::{sub, square_len};
use super::state;
use std::f64;

use common::Vec2;

pub trait Shape {
    fn get_shape(&self, size: f64) -> Triangle;

    fn is_hit(&self, size: f64, position: Vec2) -> bool;

    fn collision_detect(&self, other: &Self, size: f64) -> bool;
}

impl Shape for state::Unit {
    /// Return the base shape of the unit.
    fn get_shape(&self, radius: f64) -> Triangle {
        // calculate side length
        let a = radius * 3.0 / 3.0f64.sqrt();

        // <|
        let mut triangle: Triangle = [
            [-radius,        0.0], // Left
            [ radius*0.5,  a/2.0], // Top right
            [ radius*0.5, -a/2.0], // Bottom right
        ];

        // Transformations
        for point in triangle.iter_mut() {
            // Rotate
            let rotation_matrix = math::rotate_radians(self.angle);
            *point = math::transform_vec(rotation_matrix, *point);

            // Translate to effective position
            *point = math::add(*point, self.position.into());
        }

        triangle
    }

    /// Calculate whether or not this unit is hit by the point at the specified position.
    fn is_hit(&self, size: f64, position: Vec2) -> bool {
        let hitbox = self.get_shape(size);
        math::inside_triangle(hitbox, position.into())
    }

    fn collision_detect(&self, other: &Self, size: f64) -> bool {
        let dv = sub(self.position.into(), other.position.into());
        square_len(dv) <= (2.0 * size * 2.0 * size)
    }
}

#[cfg(test)]
mod test {
    use std::f64::consts::FRAC_PI_2;

    use super::{Shape, Vec2, state};

    #[test]
    fn test_hitbox() {
        // Create a unit at position (100,100) that has been rotated by 90° CW.
        //
        //    /\
        //   /__\
        //
        let mut unit = state::Unit::new(0, Vec2::new(0.0, 0.0));
        unit.angle = FRAC_PI_2;

        let epsilon = 0.001;
        let size = 1.0;
        let a = size * 3.0 / 3.0f64.sqrt();

        // The following points should be outside of the hitbox.
        assert_eq!(unit.is_hit(1.0, Vec2::new(a/2.0, epsilon)), false);
        assert_eq!(unit.is_hit(1.0, Vec2::new(a/2.0, epsilon)), false);

        // The following five points should be inside the hitbox.
        //      .
        //     /.\
        //   ./_._\.
        //
        assert_eq!(unit.is_hit(1.0, Vec2::new(0.0, 0.0)), true);
        assert_eq!(unit.is_hit(1.0, Vec2::new(0.0, -size + epsilon)), true);
        assert_eq!(unit.is_hit(1.0, Vec2::new(0.0, size / 2.0 - epsilon)), true);
        assert_eq!(unit.is_hit(1.0, Vec2::new(-a / 2.0 + epsilon, size / 2.0 - epsilon)), true);
        assert_eq!(unit.is_hit(1.0, Vec2::new( a / 2.0 - epsilon, size / 2.0 - epsilon)), true);

        // The following two points should be outside the hitbox.
        //
        //  . /\ .
        //   /__\
        //
        assert_eq!(unit.is_hit(1.0, Vec2::new(a/2.0, 0.0)), false);
        assert_eq!(unit.is_hit(1.0, Vec2::new(a/2.0, 0.0)), false);
    }
}
<|endoftext|>


<commit_before>// Filesystem scanning.

use ::Result;
use escape::*;
use suretree::{AttMap, SureFile, SureTree};

use std::fs::{self, symlink_metadata, Metadata};
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use libc;

pub fn scan_fs<P: AsRef<Path>>(root: P) -> Result<SureTree> {
    let root = root.as_ref().to_path_buf();

    walk_root(&root)
}

fn walk_root(path: &Path) -> Result<SureTree> {
    let meta = try!(symlink_metadata(path));

    if !meta.is_dir() {
        return Err(From::from("Root must be a directory"));
    }

    walk("__root__".to_string(), path, encode_atts(path, &meta), &meta)
}

fn walk(my_name: String, path: &Path, my_atts: AttMap, my_meta: &Metadata)
    -> Result<SureTree>
{
    let mut entries = vec![];

    // TODO: Instead of failing everything because of read failure, just
    // fail some things.

    for entry in try!(fs::read_dir(path)) {
        let entry = try!(entry);
        entries.push(entry);
    }

    // Sort by inode before sorting.  This helps performance on some
    // filesystems (such as ext4).
    entries.sort_by(|a, b| a.ino().cmp(&b.ino()));

    let mut files: Vec<_> = entries.iter().filter_map(|e| {
        match e.metadata() {
            Ok(m) => {
                let path = e.path();
                let atts = encode_atts(&path, &m);

                // Check for crossing mountpoints.
                if m.is_dir() && m.dev() != my_meta.dev() {
                    return None;
                }

                Some(OneFile {
                    path: path,
                    meta: m,
                    atts: atts,
                })
            },
            Err(err) => {
                error!("Unable to stat file: {:?} ({})", e.path(), err);
                None
            },
        }
    }).collect();

    // Sort them back by name.
    files.sort_by(|a, b| a.path.file_name().cmp(&b.path.file_name()));

    // Build the SureTree data.
    let mut node = SureTree {
        name: my_name,
        atts: my_atts,
        children: Vec::new(),
        files: Vec::new(),
    };

    // Process all of the nodes.
    for ch in files {
        if ch.meta.is_dir() {
            let child_name = ch.path.file_name().unwrap().as_bytes().escaped();
            let child = try!(walk(child_name, &ch.path, ch.atts, &ch.meta));
            node.children.push(child);
        } else {
            let child_name = ch.path.file_name().unwrap().as_bytes().escaped();
            let child = SureFile {
                name: child_name,
                atts: ch.atts,
            };
            node.files.push(child);
        }
    }

    Ok(node)
}

// Encode the attributes for the given node.  Note that this returns, even
// when there is an error (resolving a symlink).  It logs an error, and
// returns a placeholder.
fn encode_atts(name: &Path, meta: &Metadata) -> AttMap {
    // let fname = name.file_name().unwrap().as_bytes().escaped();
    let mode = meta.mode() & libc::S_IFMT;

    let mut base = AttMap::new();

    // These attributes apply to every node.
    base.insert("uid".to_string(), meta.uid().to_string());
    base.insert("gid".to_string(), meta.gid().to_string());
    base.insert("perm".to_string(), (meta.mode() & !libc::S_IFMT).to_string());

    // Other permissions are based on the type of the node.
    match mode {
        libc::S_IFDIR => {
            base.insert("kind".to_string(), "dir".to_string());
        },
        libc::S_IFREG => {
            base.insert("kind".to_string(), "file".to_string());
            base.insert("ino".to_string(), meta.ino().to_string());
            base.insert("size".to_string(), meta.size().to_string());
            time_info(&mut base, meta);
            // Note that the 'sha1' attribute is computed later.
        },
        libc::S_IFLNK => {
            base.insert("kind".to_string(), "lnk".to_string());
            let link = match fs::read_link(name) {
                Ok(l) => l,
                Err(err) => {
                    error!("Unable to read link: {:?} ({})", name, err);
                    // TODO: Generate a unique placeholder so this will
                    // always show up.
                    From::from("???")
                },
            };
            base.insert("lnk".to_string(), link.as_os_str().as_bytes().escaped());
        },
        libc::S_IFIFO => {
            base.insert("kind".to_string(), "fifo".to_string());
        },
        /* libc::S_IFSOCK */ 0o140000 => {
            base.insert("kind".to_string(), "sock".to_string());
        },
        libc::S_IFCHR => {
            base.insert("kind".to_string(), "chr".to_string());
            add_dev(&mut base, meta);
        },
        libc::S_IFBLK => {
            base.insert("kind".to_string(), "blk".to_string());
            add_dev(&mut base, meta);
        },
        _ => panic!("Unknown file type: 0o{:o}", mode),
    }

    // println!("{:?}: atts: {:?}", fname, base);
    base
}

fn add_dev(base: &mut AttMap, meta: &Metadata) {
    let rdev = meta.rdev();
    // This is defined in a macro, and hasn't made it into libc.  Given how
    // it is defined in the header, it is unlikely to change, at least on
    // Linux.
    base.insert("devmaj".to_string(), ((rdev >> 8) & 0xfff).to_string());
    base.insert("devmin".to_string(), (rdev & 0xff).to_string());
}

fn time_info(base: &mut AttMap, meta: &Metadata) {
    // TODO: Handle the nsec part of the time.
    base.insert("mtime".to_string(), meta.mtime().to_string());
    base.insert("ctime".to_string(), meta.ctime().to_string());
}

// Temp struct to hold information on intermediate files.
struct OneFile {
    path: PathBuf,
    meta: Metadata,
    atts: AttMap,
}
<commit_msg>surefs: Correct attribute for symlink<commit_after>// Filesystem scanning.

use ::Result;
use escape::*;
use suretree::{AttMap, SureFile, SureTree};

use std::fs::{self, symlink_metadata, Metadata};
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use libc;

pub fn scan_fs<P: AsRef<Path>>(root: P) -> Result<SureTree> {
    let root = root.as_ref().to_path_buf();

    walk_root(&root)
}

fn walk_root(path: &Path) -> Result<SureTree> {
    let meta = try!(symlink_metadata(path));

    if !meta.is_dir() {
        return Err(From::from("Root must be a directory"));
    }

    walk("__root__".to_string(), path, encode_atts(path, &meta), &meta)
}

fn walk(my_name: String, path: &Path, my_atts: AttMap, my_meta: &Metadata)
    -> Result<SureTree>
{
    let mut entries = vec![];

    // TODO: Instead of failing everything because of read failure, just
    // fail some things.

    for entry in try!(fs::read_dir(path)) {
        let entry = try!(entry);
        entries.push(entry);
    }

    // Sort by inode before sorting.  This helps performance on some
    // filesystems (such as ext4).
    entries.sort_by(|a, b| a.ino().cmp(&b.ino()));

    let mut files: Vec<_> = entries.iter().filter_map(|e| {
        match e.metadata() {
            Ok(m) => {
                let path = e.path();
                let atts = encode_atts(&path, &m);

                // Check for crossing mountpoints.
                if m.is_dir() && m.dev() != my_meta.dev() {
                    return None;
                }

                Some(OneFile {
                    path: path,
                    meta: m,
                    atts: atts,
                })
            },
            Err(err) => {
                error!("Unable to stat file: {:?} ({})", e.path(), err);
                None
            },
        }
    }).collect();

    // Sort them back by name.
    files.sort_by(|a, b| a.path.file_name().cmp(&b.path.file_name()));

    // Build the SureTree data.
    let mut node = SureTree {
        name: my_name,
        atts: my_atts,
        children: Vec::new(),
        files: Vec::new(),
    };

    // Process all of the nodes.
    for ch in files {
        if ch.meta.is_dir() {
            let child_name = ch.path.file_name().unwrap().as_bytes().escaped();
            let child = try!(walk(child_name, &ch.path, ch.atts, &ch.meta));
            node.children.push(child);
        } else {
            let child_name = ch.path.file_name().unwrap().as_bytes().escaped();
            let child = SureFile {
                name: child_name,
                atts: ch.atts,
            };
            node.files.push(child);
        }
    }

    Ok(node)
}

// Encode the attributes for the given node.  Note that this returns, even
// when there is an error (resolving a symlink).  It logs an error, and
// returns a placeholder.
fn encode_atts(name: &Path, meta: &Metadata) -> AttMap {
    // let fname = name.file_name().unwrap().as_bytes().escaped();
    let mode = meta.mode() & libc::S_IFMT;

    let mut base = AttMap::new();

    // These attributes apply to every node.
    base.insert("uid".to_string(), meta.uid().to_string());
    base.insert("gid".to_string(), meta.gid().to_string());
    base.insert("perm".to_string(), (meta.mode() & !libc::S_IFMT).to_string());

    // Other permissions are based on the type of the node.
    match mode {
        libc::S_IFDIR => {
            base.insert("kind".to_string(), "dir".to_string());
        },
        libc::S_IFREG => {
            base.insert("kind".to_string(), "file".to_string());
            base.insert("ino".to_string(), meta.ino().to_string());
            base.insert("size".to_string(), meta.size().to_string());
            time_info(&mut base, meta);
            // Note that the 'sha1' attribute is computed later.
        },
        libc::S_IFLNK => {
            base.insert("kind".to_string(), "lnk".to_string());
            let link = match fs::read_link(name) {
                Ok(l) => l,
                Err(err) => {
                    error!("Unable to read link: {:?} ({})", name, err);
                    // TODO: Generate a unique placeholder so this will
                    // always show up.
                    From::from("???")
                },
            };
            base.insert("targ".to_string(), link.as_os_str().as_bytes().escaped());
        },
        libc::S_IFIFO => {
            base.insert("kind".to_string(), "fifo".to_string());
        },
        /* libc::S_IFSOCK */ 0o140000 => {
            base.insert("kind".to_string(), "sock".to_string());
        },
        libc::S_IFCHR => {
            base.insert("kind".to_string(), "chr".to_string());
            add_dev(&mut base, meta);
        },
        libc::S_IFBLK => {
            base.insert("kind".to_string(), "blk".to_string());
            add_dev(&mut base, meta);
        },
        _ => panic!("Unknown file type: 0o{:o}", mode),
    }

    // println!("{:?}: atts: {:?}", fname, base);
    base
}

fn add_dev(base: &mut AttMap, meta: &Metadata) {
    let rdev = meta.rdev();
    // This is defined in a macro, and hasn't made it into libc.  Given how
    // it is defined in the header, it is unlikely to change, at least on
    // Linux.
    base.insert("devmaj".to_string(), ((rdev >> 8) & 0xfff).to_string());
    base.insert("devmin".to_string(), (rdev & 0xff).to_string());
}

fn time_info(base: &mut AttMap, meta: &Metadata) {
    // TODO: Handle the nsec part of the time.
    base.insert("mtime".to_string(), meta.mtime().to_string());
    base.insert("ctime".to_string(), meta.ctime().to_string());
}

// Temp struct to hold information on intermediate files.
struct OneFile {
    path: PathBuf,
    meta: Metadata,
    atts: AttMap,
}
<|endoftext|>


<commit_before>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
pub const STACK_SIZE: u64 = 16384;

/// Get the offset in bytes of some particular struct member.
///
/// Idea is simply to see what the address of that member would be if the
/// struct was created at address 0x0 (which gives its offset in bytes).
macro_rules! offset_of {
    ($kind:ty, $member:ident) => {
        unsafe {
            let ptr = 0x0usize as *const $kind;
            let member_addr = (&(*ptr).$member as *const _) as usize;

            member_addr
        }
    };
}

/// Return a pointer to the TLS value at the given offset.
pub unsafe fn get_tls_mem<T>(offset: usize) -> *mut T {
    let dest_ptr: *mut T;

    // We can't use constant segment offsets here due to some odd
    // asm! behavior, so just use indirect (it's slower, oh well).
    asm!("mov %fs:($1), $0"
         : "=r"(dest_ptr)
         : "r" (offset)
         :: "volatile");

    dest_ptr
}

pub unsafe fn set_tls_mem<T>(offset: usize, expr: T) {
    asm!("movl $1, %fs:($0)" :
         : "r"(offset), "r"(expr)
         :: "volatile");
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

pub fn get_current_thread() -> &'static Thread {
    let thd_ptr: *mut Thread = unsafe { get_tls_mem(0) };
    if thd_ptr.is_null() {
        panic!("TLS thread return NULL");
    }

    let thd = unsafe { &*thd_ptr };

    thd
}

pub fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = unsafe {
        libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0)
    };

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<commit_msg>Inline functions, that is.<commit_after>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
pub const STACK_SIZE: u64 = 16384;

/// Get the offset in bytes of some particular struct member.
///
/// Idea is simply to see what the address of that member would be if the
/// struct was created at address 0x0 (which gives its offset in bytes).
macro_rules! offset_of {
    ($kind:ty, $member:ident) => {
        unsafe {
            let ptr = 0x0usize as *const $kind;
            let member_addr = (&(*ptr).$member as *const _) as usize;

            member_addr
        }
    };
}

/// Return a pointer to the TLS value at the given offset.
#[inline(always)]
pub unsafe fn get_tls_mem<T>(offset: usize) -> *mut T {
    let dest_ptr: *mut T;

    // We can't use constant segment offsets here due to some odd
    // asm! behavior, so just use indirect (it's slower, oh well).
    asm!("mov %fs:($1), $0"
         : "=r"(dest_ptr)
         : "r" (offset)
         :: "volatile");

    dest_ptr
}

#[inline(always)]
pub unsafe fn set_tls_mem<T>(offset: usize, expr: T) {
    asm!("movl $1, %fs:($0)" :
         : "r"(offset), "r"(expr)
         :: "volatile");
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

pub fn get_current_thread() -> &'static Thread {
    let thd_ptr: *mut Thread = unsafe { get_tls_mem(0) };
    if thd_ptr.is_null() {
        panic!("TLS thread return NULL");
    }

    let thd = unsafe { &*thd_ptr };

    thd
}

pub fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = unsafe {
        libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0)
    };

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<|endoftext|>


<commit_before>use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use mouse::Mouse;
use point::Point;
use rectangle;
use graphics::Graphics;
use graphics::character::CharacterCache;
use ui_context::{ UIID, UiContext };
use widget::Widget;

/// Represents the state of the Toggle widget.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(Toggle, State, Widget::Toggle(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// A context on which the builder pattern can be implemented.
pub struct Toggle<'a, F> {
    ui_id: UIID,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
    value: bool,
}

impl<'a, F> Toggle<'a, F> {

    /// Create a toggle context to be built upon.
    pub fn new(ui_id: UIID, value: bool) -> Toggle<'a, F> {
        Toggle {
            ui_id: ui_id,
            pos: [0.0, 0.0],
            dim: [64.0, 64.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
            value: value,
        }
    }

}

impl<'a, F> Colorable for Toggle<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Toggle<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

/*
quack! {
    toggle: Toggle['a, F]
    get:
        fn () -> Size [] { Size(toggle.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::Toggle(State::Normal))
        }
        fn () -> Id [] { Id(toggle.ui_id) }
    set:
        fn (val: Callback<F>) [where F: FnMut(bool) + 'a] {
            toggle.maybe_callback = Some(val.0)
        }
        fn (val: LabelText<'a>) [] { toggle.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { toggle.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] {
            toggle.maybe_label_font_size = Some(val.0)
        }
        fn (val: Position) [] { toggle.pos = val.0 }
        fn (val: Size) [] { toggle.dim = val.0 }
    action:
}
*/

impl<'a, F> ::draw::Drawable for Toggle<'a, F> where F: FnMut(bool) + 'a {
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let color = match self.value {
            true => color,
            false => color * Color::new(0.1, 0.1, 0.1, 1.0)
        };
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over = rectangle::is_over(self.pos, mouse.pos, self.dim);
        let new_state = get_new_state(is_over, state, mouse);
        let rect_state = new_state.as_rectangle_state();
        match self.maybe_callback {
            Some(ref mut callback) => {
                match (is_over, state, new_state) {
                    (true, State::Clicked, State::Highlighted) =>
                        (*callback)(match self.value { true => false, false => true }),
                    _ => (),
                }
            }, None => (),
        }
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        match self.maybe_label {
            None => {
                rectangle::draw(
                    uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                    self.dim, maybe_frame, color
                )
            },
            Some(text) => {
                let text_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
                let size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
                rectangle::draw_with_centered_label(
                    uic.win_w, uic.win_h, graphics, uic, rect_state,
                    self.pos, self.dim, maybe_frame, color,
                    text, size, text_color
                )
            },
        }

        set_state(uic, self.ui_id, Widget::Toggle(new_state), self.pos, self.dim);

    }
}
<commit_msg>Implemented `Callable` for `Toggle`<commit_after>use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use mouse::Mouse;
use point::Point;
use rectangle;
use graphics::Graphics;
use graphics::character::CharacterCache;
use ui_context::{ UIID, UiContext };
use widget::Widget;

/// Represents the state of the Toggle widget.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(Toggle, State, Widget::Toggle(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// A context on which the builder pattern can be implemented.
pub struct Toggle<'a, F> {
    ui_id: UIID,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
    value: bool,
}

impl<'a, F> Toggle<'a, F> {

    /// Create a toggle context to be built upon.
    pub fn new(ui_id: UIID, value: bool) -> Toggle<'a, F> {
        Toggle {
            ui_id: ui_id,
            pos: [0.0, 0.0],
            dim: [64.0, 64.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
            value: value,
        }
    }

}

impl<'a, F> Colorable for Toggle<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Toggle<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Callable<F> for Toggle<'a, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

/*
quack! {
    toggle: Toggle['a, F]
    get:
        fn () -> Size [] { Size(toggle.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::Toggle(State::Normal))
        }
        fn () -> Id [] { Id(toggle.ui_id) }
    set:
        fn (val: LabelText<'a>) [] { toggle.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { toggle.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] {
            toggle.maybe_label_font_size = Some(val.0)
        }
        fn (val: Position) [] { toggle.pos = val.0 }
        fn (val: Size) [] { toggle.dim = val.0 }
    action:
}
*/

impl<'a, F> ::draw::Drawable for Toggle<'a, F> where F: FnMut(bool) + 'a {
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let color = match self.value {
            true => color,
            false => color * Color::new(0.1, 0.1, 0.1, 1.0)
        };
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over = rectangle::is_over(self.pos, mouse.pos, self.dim);
        let new_state = get_new_state(is_over, state, mouse);
        let rect_state = new_state.as_rectangle_state();
        match self.maybe_callback {
            Some(ref mut callback) => {
                match (is_over, state, new_state) {
                    (true, State::Clicked, State::Highlighted) =>
                        (*callback)(match self.value { true => false, false => true }),
                    _ => (),
                }
            }, None => (),
        }
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        match self.maybe_label {
            None => {
                rectangle::draw(
                    uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                    self.dim, maybe_frame, color
                )
            },
            Some(text) => {
                let text_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
                let size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
                rectangle::draw_with_centered_label(
                    uic.win_w, uic.win_h, graphics, uic, rect_state,
                    self.pos, self.dim, maybe_frame, color,
                    text, size, text_color
                )
            },
        }

        set_state(uic, self.ui_id, Widget::Toggle(new_state), self.pos, self.dim);

    }
}
<|endoftext|>


<commit_before>use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use mouse::Mouse;
use point::Point;
use rectangle;
use graphics::Graphics;
use graphics::character::CharacterCache;
use ui_context::{ UIID, UiContext };
use widget::Widget;

/// Represents the state of the Toggle widget.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(Toggle, State, Widget::Toggle(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// A context on which the builder pattern can be implemented.
pub struct Toggle<'a, F> {
    ui_id: UIID,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
    value: bool,
}

impl<'a, F> Toggle<'a, F> {

    /// Create a toggle context to be built upon.
    pub fn new(ui_id: UIID, value: bool) -> Toggle<'a, F> {
        Toggle {
            ui_id: ui_id,
            pos: [0.0, 0.0],
            dim: [64.0, 64.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
            value: value,
        }
    }

}

impl<'a, F> Colorable for Toggle<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Toggle<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Callable<F> for Toggle<'a, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

/*
quack! {
    toggle: Toggle['a, F]
    get:
        fn () -> Size [] { Size(toggle.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::Toggle(State::Normal))
        }
        fn () -> Id [] { Id(toggle.ui_id) }
    set:
        fn (val: LabelText<'a>) [] { toggle.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { toggle.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] {
            toggle.maybe_label_font_size = Some(val.0)
        }
        fn (val: Position) [] { toggle.pos = val.0 }
        fn (val: Size) [] { toggle.dim = val.0 }
    action:
}
*/

impl<'a, F> ::draw::Drawable for Toggle<'a, F> where F: FnMut(bool) + 'a {
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let color = match self.value {
            true => color,
            false => color * Color::new(0.1, 0.1, 0.1, 1.0)
        };
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over = rectangle::is_over(self.pos, mouse.pos, self.dim);
        let new_state = get_new_state(is_over, state, mouse);
        let rect_state = new_state.as_rectangle_state();
        match self.maybe_callback {
            Some(ref mut callback) => {
                match (is_over, state, new_state) {
                    (true, State::Clicked, State::Highlighted) =>
                        (*callback)(match self.value { true => false, false => true }),
                    _ => (),
                }
            }, None => (),
        }
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        match self.maybe_label {
            None => {
                rectangle::draw(
                    uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                    self.dim, maybe_frame, color
                )
            },
            Some(text) => {
                let text_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
                let size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
                rectangle::draw_with_centered_label(
                    uic.win_w, uic.win_h, graphics, uic, rect_state,
                    self.pos, self.dim, maybe_frame, color,
                    text, size, text_color
                )
            },
        }

        set_state(uic, self.ui_id, Widget::Toggle(new_state), self.pos, self.dim);

    }
}
<commit_msg>Implement `Labelable` for `Toggle`<commit_after>use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use label::{ FontSize, Labelable };
use dimensions::Dimensions;
use mouse::Mouse;
use point::Point;
use rectangle;
use graphics::Graphics;
use graphics::character::CharacterCache;
use ui_context::{ UIID, UiContext };
use widget::Widget;

/// Represents the state of the Toggle widget.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(Toggle, State, Widget::Toggle(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// A context on which the builder pattern can be implemented.
pub struct Toggle<'a, F> {
    ui_id: UIID,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
    value: bool,
}

impl<'a, F> Toggle<'a, F> {

    /// Create a toggle context to be built upon.
    pub fn new(ui_id: UIID, value: bool) -> Toggle<'a, F> {
        Toggle {
            ui_id: ui_id,
            pos: [0.0, 0.0],
            dim: [64.0, 64.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
            value: value,
        }
    }

}

impl<'a, F> Colorable for Toggle<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Toggle<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Callable<F> for Toggle<'a, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

impl<'a, F> Labelable<'a> for Toggle<'a, F>
{
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.maybe_label_font_size = Some(size);
        self
    }
}

/*
quack! {
    toggle: Toggle['a, F]
    get:
        fn () -> Size [] { Size(toggle.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::Toggle(State::Normal))
        }
        fn () -> Id [] { Id(toggle.ui_id) }
    set:
        fn (val: Position) [] { toggle.pos = val.0 }
        fn (val: Size) [] { toggle.dim = val.0 }
    action:
}
*/

impl<'a, F> ::draw::Drawable for Toggle<'a, F> where F: FnMut(bool) + 'a {
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let color = match self.value {
            true => color,
            false => color * Color::new(0.1, 0.1, 0.1, 1.0)
        };
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over = rectangle::is_over(self.pos, mouse.pos, self.dim);
        let new_state = get_new_state(is_over, state, mouse);
        let rect_state = new_state.as_rectangle_state();
        match self.maybe_callback {
            Some(ref mut callback) => {
                match (is_over, state, new_state) {
                    (true, State::Clicked, State::Highlighted) =>
                        (*callback)(match self.value { true => false, false => true }),
                    _ => (),
                }
            }, None => (),
        }
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        match self.maybe_label {
            None => {
                rectangle::draw(
                    uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                    self.dim, maybe_frame, color
                )
            },
            Some(text) => {
                let text_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
                let size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
                rectangle::draw_with_centered_label(
                    uic.win_w, uic.win_h, graphics, uic, rect_state,
                    self.pos, self.dim, maybe_frame, color,
                    text, size, text_color
                )
            },
        }

        set_state(uic, self.ui_id, Widget::Toggle(new_state), self.pos, self.dim);

    }
}
<|endoftext|>


<commit_before>//! Some iterator that produces tuples

use std::marker::PhantomData;

/// An iterator that groups the items in tuples of a specific size.
///
/// See [`.tuples()`](../trait.Itertools.html#method.tuples) for more information.
pub struct Tuples<I, T>
    where I: Iterator
{
    iter: I,
    buf: Option<Vec<I::Item>>,
    _marker: PhantomData<T>,
}

/// Create a new tuples iterator.
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    Tuples {
        iter: iter,
        buf: None,
        _marker: PhantomData,
    }
}

impl<I, T> Iterator for Tuples<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        match T::try_collect_from_iter(&mut self.iter) {
            Ok(v) => Some(v),
            Err(buf) => {
                if self.buf.is_none() {
                    self.buf = Some(buf);
                }
                None
            }
        }
    }
}

impl<I, T> Tuples<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let mut iter = (0..5).tuples();
    /// assert_eq!(Some((0, 1, 2)), iter.next());
    /// assert_eq!(None, iter.next());
    /// assert_eq!(vec![3, 4], iter.into_buffer());
    /// ```
    pub fn into_buffer(self) -> Vec<I::Item> {
        self.buf.unwrap_or_else(|| vec![])
    }
}

/// An iterator over all contiguous windows that produces tuples of a specific size.
///
/// See [`.tuple_windows()`](../trait.Itertools.html#method.tuple_windows) for more
/// information.
pub struct TupleWindows<I, T>
    where I: Iterator
{
    iter: I,
    last: Option<T>,
    buf: Option<Vec<I::Item>>,
    _marker: PhantomData<T>,
}

/// Create a new tuple windows iterator.
pub fn tuple_windows<I, T>(iter: I) -> TupleWindows<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    TupleWindows {
        iter: iter,
        last: None,
        buf: None,
        _marker: PhantomData,
    }
}

impl<I, T> Iterator for TupleWindows<I, T>
    where I: Iterator,
          I::Item: Clone,
          T: TupleCollect<I::Item> + Clone
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if let Some(ref mut last) = self.last {
            if let Some(new) = self.iter.next() {
                last.left_shift_push(new);
                Some(last.clone())
            } else {
                self.buf = Some(vec![]);
                None
            }
        } else {
            match T::try_collect_from_iter(&mut self.iter) {
                Ok(v) => {
                    self.last = Some(v);
                    self.last.clone()
                },
                Err(buf) => {
                    if self.buf.is_none() {
                        self.buf = Some(buf);
                    }
                    None
                }
            }
        }
    }
}

impl<I, T> TupleWindows<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item> + ::std::fmt::Debug
{
    /// Return a pair with a buffer containing the items that was produced but not consumed and the
    /// inner iterator.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let mut w = (0..10).tuple_windows();
    /// assert_eq!(Some((0, 1, 2)), w.next());
    ///
    /// let (buffer, mut iter) = w.into_parts();
    /// // Every produced item was consumed
    /// assert!(buffer.is_empty());
    /// // The next item is 6
    /// assert_eq!(Some(3), iter.next());
    ///
    /// let mut w = (0..2).tuple_windows::<(_, _, _)>();
    /// assert_eq!(None, w.next());
    ///
    /// let (buffer, mut iter) = w.into_parts();
    /// // The items 0 and 1 was produced but not consumed
    /// assert_eq!(vec![0, 1], buffer);
    /// // The is no more items
    /// assert_eq!(None, iter.next());
    /// ```
    pub fn into_parts(self) -> (Vec<I::Item>, I) {
        (self.buf.unwrap_or_else(|| vec![]), self.iter)
    }
}

pub trait TupleCollect<Item>: Sized {
    fn try_collect_from_iter<I>(iter: I) -> Result<Self, Vec<Item>>
        where I: IntoIterator<Item = Item>;

    fn collect_from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item = Item>;

    fn left_shift_push(&mut self, item: Item);

    fn into_vec(self) -> Vec<Item>;
}

macro_rules! impl_tuple_collect {
    () => ();
    ($A:ident ; $($X:ident),* ; $($Y:ident),* ; $($Y_rev:ident),*) => (
        impl<$A> TupleCollect<$A> for ($($X),*,) {
            fn try_collect_from_iter<I>(iter: I) -> Result<Self, Vec<$A>>
                where I: IntoIterator<Item = $A>
            {
                let mut iter = iter.into_iter();
                $(let $Y = iter.next();)*

                if $($Y.is_some())&&* {
                    Ok(($($Y.unwrap()),*,))
                } else {
                    let mut v = vec![];
                    $(if let Some(x) = $Y {
                        v.push(x);
                    })*
                    Err(v)
                }
            }

            fn collect_from_iter<I>(iter: I) -> Self
                where I: IntoIterator<Item = $A>
            {
                let mut iter = iter.into_iter();
                // Y must be used, so use it as var name
                ($({let $Y = iter.next().unwrap(); $Y }),*,)
            }

            fn left_shift_push(&mut self, item: $A) {
                use std::mem::replace;

                let &mut ($(ref mut $Y),*,) = self;
                let tmp = item;
                $(
                    let tmp = replace($Y_rev, tmp);
                )*
                drop(tmp);
            }

            fn into_vec(self) -> Vec<$A> {
                let ($($Y),*,) = self;
                let mut v = vec![];
                $(
                    v.push($Y);
                )*
                v
            }
        }
    )
}

impl_tuple_collect!(A; A; a; a);
impl_tuple_collect!(A; A, A; a, b; b, a);
impl_tuple_collect!(A; A, A, A; a, b, c; c, b, a);
impl_tuple_collect!(A; A, A, A, A; a, b, c, d; d, c, b, a);
<commit_msg>Use fused iterators<commit_after>//! Some iterator that produces tuples

use std::marker::PhantomData;
use std::iter::Fuse;

/// An iterator that groups the items in tuples of a specific size.
///
/// See [`.tuples()`](../trait.Itertools.html#method.tuples) for more information.
pub struct Tuples<I, T>
    where I: Iterator
{
    iter: Fuse<I>,
    buf: Option<Vec<I::Item>>,
    _marker: PhantomData<T>,
}

/// Create a new tuples iterator.
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    Tuples {
        iter: iter.fuse(),
        buf: None,
        _marker: PhantomData,
    }
}

impl<I, T> Iterator for Tuples<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        match T::try_collect_from_iter(&mut self.iter) {
            Ok(v) => Some(v),
            Err(buf) => {
                if self.buf.is_none() {
                    self.buf = Some(buf);
                }
                None
            }
        }
    }
}

impl<I, T> Tuples<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let mut iter = (0..5).tuples();
    /// assert_eq!(Some((0, 1, 2)), iter.next());
    /// assert_eq!(None, iter.next());
    /// assert_eq!(vec![3, 4], iter.into_buffer());
    /// ```
    pub fn into_buffer(self) -> Vec<I::Item> {
        self.buf.unwrap_or_else(|| vec![])
    }
}

/// An iterator over all contiguous windows that produces tuples of a specific size.
///
/// See [`.tuple_windows()`](../trait.Itertools.html#method.tuple_windows) for more
/// information.
pub struct TupleWindows<I, T>
    where I: Iterator
{
    iter: Fuse<I>,
    last: Option<T>,
    buf: Option<Vec<I::Item>>,
    _marker: PhantomData<T>,
}

/// Create a new tuple windows iterator.
pub fn tuple_windows<I, T>(iter: I) -> TupleWindows<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item>
{
    TupleWindows {
        iter: iter.fuse(),
        last: None,
        buf: None,
        _marker: PhantomData,
    }
}

impl<I, T> Iterator for TupleWindows<I, T>
    where I: Iterator,
          I::Item: Clone,
          T: TupleCollect<I::Item> + Clone
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if let Some(ref mut last) = self.last {
            if let Some(new) = self.iter.next() {
                last.left_shift_push(new);
                Some(last.clone())
            } else {
                self.buf = Some(vec![]);
                None
            }
        } else {
            match T::try_collect_from_iter(&mut self.iter) {
                Ok(v) => {
                    self.last = Some(v);
                    self.last.clone()
                },
                Err(buf) => {
                    if self.buf.is_none() {
                        self.buf = Some(buf);
                    }
                    None
                }
            }
        }
    }
}

impl<I, T> TupleWindows<I, T>
    where I: Iterator,
          T: TupleCollect<I::Item> + ::std::fmt::Debug
{
    /// Return a pair with a buffer containing the items that was produced but not consumed and the
    /// inner iterator.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let mut w = (0..10).tuple_windows();
    /// assert_eq!(Some((0, 1, 2)), w.next());
    ///
    /// let (buffer, mut iter) = w.into_parts();
    /// // Every produced item was consumed
    /// assert!(buffer.is_empty());
    /// // The next item is 6
    /// assert_eq!(Some(3), iter.next());
    ///
    /// let mut w = (0..2).tuple_windows::<(_, _, _)>();
    /// assert_eq!(None, w.next());
    ///
    /// let (buffer, mut iter) = w.into_parts();
    /// // The items 0 and 1 was produced but not consumed
    /// assert_eq!(vec![0, 1], buffer);
    /// // The is no more items
    /// assert_eq!(None, iter.next());
    /// ```
    pub fn into_parts(self) -> (Vec<I::Item>, Fuse<I>) {
        (self.buf.unwrap_or_else(|| vec![]), self.iter)
    }
}

pub trait TupleCollect<Item>: Sized {
    fn try_collect_from_iter<I>(iter: I) -> Result<Self, Vec<Item>>
        where I: IntoIterator<Item = Item>;

    fn collect_from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item = Item>;

    fn left_shift_push(&mut self, item: Item);

    fn into_vec(self) -> Vec<Item>;
}

macro_rules! impl_tuple_collect {
    () => ();
    ($A:ident ; $($X:ident),* ; $($Y:ident),* ; $($Y_rev:ident),*) => (
        impl<$A> TupleCollect<$A> for ($($X),*,) {
            fn try_collect_from_iter<I>(iter: I) -> Result<Self, Vec<$A>>
                where I: IntoIterator<Item = $A>
            {
                let mut iter = iter.into_iter();
                $(let $Y = iter.next();)*

                if $($Y.is_some())&&* {
                    Ok(($($Y.unwrap()),*,))
                } else {
                    let mut v = vec![];
                    $(if let Some(x) = $Y {
                        v.push(x);
                    })*
                    Err(v)
                }
            }

            fn collect_from_iter<I>(iter: I) -> Self
                where I: IntoIterator<Item = $A>
            {
                let mut iter = iter.into_iter();
                // Y must be used, so use it as var name
                ($({let $Y = iter.next().unwrap(); $Y }),*,)
            }

            fn left_shift_push(&mut self, item: $A) {
                use std::mem::replace;

                let &mut ($(ref mut $Y),*,) = self;
                let tmp = item;
                $(
                    let tmp = replace($Y_rev, tmp);
                )*
                drop(tmp);
            }

            fn into_vec(self) -> Vec<$A> {
                let ($($Y),*,) = self;
                let mut v = vec![];
                $(
                    v.push($Y);
                )*
                v
            }
        }
    )
}

impl_tuple_collect!(A; A; a; a);
impl_tuple_collect!(A; A, A; a, b; b, a);
impl_tuple_collect!(A; A, A, A; a, b, c; c, b, a);
impl_tuple_collect!(A; A, A, A, A; a, b, c, d; d, c, b, a);
<|endoftext|>


<commit_before>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
}<commit_msg>Add div and divAssign impl and tests<commit_after>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Div, DivAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl Div for Vec3 {
  type Output = Vec3;
  fn div(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i / rhs.i, j: self.j / rhs.j, k: self.k / rhs.k}
  }
}

impl DivAssign for Vec3 {
  fn div_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i / rhs.i,
      j: self.j / rhs.j,
      k: self.k / rhs.k,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn divide_elementwise() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let quotient = v1 / v2;
    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_assign_elementwise() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 /= v2;
    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
}<|endoftext|>


<commit_before>//
// writer.rs
// Copyright (C) 2015 Adrian Perez <aperez@igalia.com>
// Distributed under terms of the MIT license.
//

use std::io;
use std::fmt;
use std::collections::BTreeMap;
use super::value::Value;

trait Formatter {
    fn start_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write;
    fn end_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write;
    fn key_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write;
    fn item_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write;
}

pub struct CompactFormatter;

impl Formatter for CompactFormatter {
    fn start_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        writer.write_all(&[ch])
    }

    fn end_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        writer.write_all(&[ch])
    }

    fn key_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        match *next {
            Value::Dict(_) | Value::List(_) => Ok(()),
            _ => writer.write_all(b":"),
        }
    }

    fn item_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        match *next {
            Value::Dict(_) | Value::List(_) => Ok(()),
            _ => writer.write_all(b","),
        }
    }
}

pub struct PrettyFormatter {
    indent: usize,
}

impl PrettyFormatter {
    fn new() -> Self {
        PrettyFormatter { indent: 0 }
    }
}

#[inline]
fn indent<W>(writer: &mut W, indent: usize) -> io::Result<()>
    where W: io::Write
{
    for _ in 0..indent {
        try!(writer.write_all(b"  "));
    }
    Ok(())
}

impl Formatter for PrettyFormatter {
    fn start_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        self.indent += 1;
        try!(writer.write_all(&[ch, b'\n']));
        indent(writer, self.indent)
    }

    fn end_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        self.indent -= 1;
        try!(writer.write(b"\n"));
        try!(indent(writer, self.indent));
        writer.write_all(&[ch])
    }

    fn key_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        match *next {
            Value::Dict(_) | Value::List(_) => writer.write_all(b" "),
            _ => writer.write_all(b": "),
        }
    }

    fn item_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        try!(writer.write(b"\n"));
        indent(writer, self.indent)
    }
}

pub struct Writer<W, F=PrettyFormatter> {
    writer: W,
    format: F,
}

impl<W> Writer<W, CompactFormatter>
    where W: io::Write
{
    #[inline]
    pub fn compact(writer: W) -> Self {
        Writer::with_formatter(writer, CompactFormatter)
    }
}

impl<W> Writer<W>
    where W: io::Write
{
    #[inline]
    pub fn pretty(writer: W) -> Self {
        Writer::with_formatter(writer, PrettyFormatter::new())
    }
}

impl<W, F> Writer<W, F>
    where W: io::Write,
          F: Formatter,
{
    #[inline]
    fn with_formatter(writer: W, formatter: F) -> Self
        where W: io::Write,
              F: Formatter,
    {
        Writer {
            writer: writer,
            format: formatter,
        }
    }

    fn write_value(&mut self, value: &Value) -> io::Result<()> {
        match *value {
            Value::Bool(value) => self.write_bool(value),
            Value::Float(value) => self.write_float(value),
            Value::Integer(value) => self.write_integer(value),
            Value::String(ref value) => self.write_string(value),
            Value::List(ref value) => self.write_list(value),
            Value::Dict(ref value) => self.write_dict(value),
        }
    }

    #[inline]
    fn write_bool(&mut self, value: bool) -> io::Result<()> {
        if value {
            self.writer.write_all(b"True")
        } else {
            self.writer.write_all(b"False")
        }
    }

    #[inline]
    fn write_float(&mut self, value: f64) -> io::Result<()> {
        if value.is_nan() || value.is_infinite() {
            write!(self.writer, "{}", value)
        } else {
            let s = format!("{}", value);
            try!(self.writer.write_all(s.as_bytes()));
            if !s.contains(".") {
                try!(self.writer.write_all(b".0"));
            }
            Ok(())
        }
    }

    #[inline]
    fn write_integer(&mut self, value: i64) -> io::Result<()> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn write_string(&mut self, value: &String) -> io::Result<()> {
        try!(self.writer.write_all(b"\""));
        for ch in value.bytes() {
            try!(match ch {
                0x09 => self.writer.write_all(b"\\t"),
                0x0A => self.writer.write_all(b"\\n"),
                0x0D => self.writer.write_all(b"\\r"),
                0x22 => self.writer.write_all(b"\\\""),
                0x5C => self.writer.write_all(b"\\\\"),
                ch if ch < 0xF => write!(self.writer, "\\0{:X}", ch),
                ch if ch < 0x20 => write!(self.writer, "\\{:X}", ch),
                ch => self.writer.write_all(&[ch]),
            });
        }
        self.writer.write_all(b"\"")
    }

    fn write_list(&mut self, value: &Vec<Value>) -> io::Result<()> {
        if value.is_empty() {
            return self.writer.write_all(b"[]");
        }

        let mut iter = value.iter().peekable();
        try!(self.format.start_compound(&mut self.writer, b'['));
        loop {
            match iter.next() {
                None => break,
                Some(value) => {
                    try!(self.write_value(value));
                    match iter.peek () {
                        Some(_) =>
                            try!(self.format.item_separator(&mut self.writer, value)),
                        None => (),
                    }
                },
            }
        }
        self.format.end_compound(&mut self.writer, b']')
    }

    #[inline]
    fn write_dict(&mut self, dict: &BTreeMap<String, Value>) -> io::Result<()> {
        if dict.is_empty() {
            return self.writer.write_all(b"{}");
        }

        try!(self.format.start_compound(&mut self.writer, b'{'));
        try!(self.write_keyval_items(dict));
        self.format.end_compound(&mut self.writer, b'}')
    }

    fn write_keyval_items(&mut self, dict: &BTreeMap<String, Value>) -> io::Result<()> {
        let mut iter = dict.iter().peekable();
        loop {
            match iter.next() {
                None => break,
                Some((key, value)) => {
                    try!(self.writer.write_all(key.as_bytes()));
                    try!(self.format.key_separator(&mut self.writer, value));
                    try!(self.write_value(value));
                    match iter.peek () {
                        Some(&(_, ref value)) =>
                            try!(self.format.item_separator(&mut self.writer, value)),
                        None => (),
                    }
                },
            }
        }
        Ok(())
    }

    #[inline]
    pub fn write_message(&mut self, value: &BTreeMap<String, Value>) -> io::Result<()> {
        self.write_keyval_items(value)
    }

    #[inline]
    pub fn write_framed_message(&mut self, value: &BTreeMap<String, Value>) -> io::Result<()> {
        self.write_dict(value)
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    use super::super::value::Value;
    use std::io::{Cursor, Write};
    use std::collections::BTreeMap;
    use std::f64::{NAN, INFINITY};

    macro_rules! make_write_test {
        ($name:ident, $value:expr, $pretty:expr, $compact:expr) => {
            #[test]
            fn $name() {
                {
                    println!("Pretty");
                    let mut output = Cursor::new(Vec::new());
                    Writer::pretty(&mut output).write_value($value).ok();
                    assert_eq!($pretty, String::from_utf8(output.into_inner()).unwrap());
                }
                {
                    println!("Compact");
                    let mut output = Cursor::new(Vec::new());
                    Writer::compact(&mut output).write_value($value).ok();
                    assert_eq!($compact, String::from_utf8(output.into_inner()).unwrap());
                }
            }
        }
    }

    make_write_test!(bool_true,  &Value::Bool(true),  "True", "True");
    make_write_test!(bool_false, &Value::Bool(false), "False", "False");

    make_write_test!(list_empty, &Value::List(vec![]), "[]", "[]");
    make_write_test!(list_one,   &Value::List(vec![Value::Bool(true)]), "[\n  True\n]", "[True]");
    make_write_test!(list_two,   &Value::List(vec![Value::Bool(true), Value::Bool(false)]),
        "[\n  True\n  False\n]", "[True,False]");
    make_write_test!(list_nested,
                     &Value::List(vec![
                                  Value::Bool(true),
                                  Value::List(vec![Value::Bool(false)])]),
                     "[\n  True\n  [\n    False\n  ]\n]", "[True,[False]]");

    make_write_test!(dict_empty, &Value::Dict(BTreeMap::new()), "{}", "{}");
    make_write_test!(dict_one,   &Value::Dict((|| {
        let mut b = BTreeMap::new();
        b.insert("item".to_string(), Value::Bool(true));
        b
    })()), "{\n  item: True\n}", "{item:True}");
    make_write_test!(dict_two,   &Value::Dict((|| {
        let mut b = BTreeMap::new();
        b.insert("foo".to_string(), Value::Bool(true));
        b.insert("bar".to_string(), Value::Bool(false));
        b
    })()), "{\n  bar: False\n  foo: True\n}", "{bar:False,foo:True}");

    macro_rules! make_write_string_test {
        ($name:ident, $value:expr, $expected:expr) => {
            make_write_test!($name, &Value::String($value.to_string()), $expected, $expected);
        }
    }

    make_write_string_test!(string_empty, "", "\"\"");
    make_write_string_test!(string_non_empty, "foo bar", "\"foo bar\"");
    make_write_string_test!(string_unicode, "☺", "\"☺\"");
    make_write_string_test!(string_escapes, "\n\r\t\\\"", "\"\\n\\r\\t\\\\\\\"\"");
    make_write_string_test!(string_hexcode, "\0", "\"\\00\"");

    macro_rules! make_write_number_test {
        ($t:ident, $name:ident, $value:expr, $expected:expr) => {
            make_write_test!($name, &Value::$t($value), $expected, $expected);
        }
    }

    make_write_number_test!(Integer, integer_zero, 0, "0");
    make_write_number_test!(Integer, integer_negative, -34, "-34");

    make_write_number_test!(Float, float_zero, 0.0, "0.0");
    make_write_number_test!(Float, float_suffix, 1f64, "1.0");
    make_write_number_test!(Float, float_positive, 4.5, "4.5");
    make_write_number_test!(Float, float_negative, -3.2, "-3.2");
    make_write_number_test!(Float, float_nan, NAN, "NaN");
    make_write_number_test!(Float, float_infinite, INFINITY, "inf");
}
<commit_msg>writer: Remove unused imports<commit_after>//
// writer.rs
// Copyright (C) 2015 Adrian Perez <aperez@igalia.com>
// Distributed under terms of the MIT license.
//

use std::io;
use std::collections::BTreeMap;
use super::value::Value;

trait Formatter {
    fn start_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write;
    fn end_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write;
    fn key_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write;
    fn item_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write;
}

pub struct CompactFormatter;

impl Formatter for CompactFormatter {
    fn start_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        writer.write_all(&[ch])
    }

    fn end_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        writer.write_all(&[ch])
    }

    fn key_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        match *next {
            Value::Dict(_) | Value::List(_) => Ok(()),
            _ => writer.write_all(b":"),
        }
    }

    fn item_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        match *next {
            Value::Dict(_) | Value::List(_) => Ok(()),
            _ => writer.write_all(b","),
        }
    }
}

pub struct PrettyFormatter {
    indent: usize,
}

impl PrettyFormatter {
    fn new() -> Self {
        PrettyFormatter { indent: 0 }
    }
}

#[inline]
fn indent<W>(writer: &mut W, indent: usize) -> io::Result<()>
    where W: io::Write
{
    for _ in 0..indent {
        try!(writer.write_all(b"  "));
    }
    Ok(())
}

impl Formatter for PrettyFormatter {
    fn start_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        self.indent += 1;
        try!(writer.write_all(&[ch, b'\n']));
        indent(writer, self.indent)
    }

    fn end_compound<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
        where W: io::Write
    {
        self.indent -= 1;
        try!(writer.write(b"\n"));
        try!(indent(writer, self.indent));
        writer.write_all(&[ch])
    }

    fn key_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        match *next {
            Value::Dict(_) | Value::List(_) => writer.write_all(b" "),
            _ => writer.write_all(b": "),
        }
    }

    fn item_separator<W>(&mut self, writer: &mut W, next: &Value) -> io::Result<()>
        where W: io::Write
    {
        try!(writer.write(b"\n"));
        indent(writer, self.indent)
    }
}

pub struct Writer<W, F=PrettyFormatter> {
    writer: W,
    format: F,
}

impl<W> Writer<W, CompactFormatter>
    where W: io::Write
{
    #[inline]
    pub fn compact(writer: W) -> Self {
        Writer::with_formatter(writer, CompactFormatter)
    }
}

impl<W> Writer<W>
    where W: io::Write
{
    #[inline]
    pub fn pretty(writer: W) -> Self {
        Writer::with_formatter(writer, PrettyFormatter::new())
    }
}

impl<W, F> Writer<W, F>
    where W: io::Write,
          F: Formatter,
{
    #[inline]
    fn with_formatter(writer: W, formatter: F) -> Self
        where W: io::Write,
              F: Formatter,
    {
        Writer {
            writer: writer,
            format: formatter,
        }
    }

    fn write_value(&mut self, value: &Value) -> io::Result<()> {
        match *value {
            Value::Bool(value) => self.write_bool(value),
            Value::Float(value) => self.write_float(value),
            Value::Integer(value) => self.write_integer(value),
            Value::String(ref value) => self.write_string(value),
            Value::List(ref value) => self.write_list(value),
            Value::Dict(ref value) => self.write_dict(value),
        }
    }

    #[inline]
    fn write_bool(&mut self, value: bool) -> io::Result<()> {
        if value {
            self.writer.write_all(b"True")
        } else {
            self.writer.write_all(b"False")
        }
    }

    #[inline]
    fn write_float(&mut self, value: f64) -> io::Result<()> {
        if value.is_nan() || value.is_infinite() {
            write!(self.writer, "{}", value)
        } else {
            let s = format!("{}", value);
            try!(self.writer.write_all(s.as_bytes()));
            if !s.contains(".") {
                try!(self.writer.write_all(b".0"));
            }
            Ok(())
        }
    }

    #[inline]
    fn write_integer(&mut self, value: i64) -> io::Result<()> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn write_string(&mut self, value: &String) -> io::Result<()> {
        try!(self.writer.write_all(b"\""));
        for ch in value.bytes() {
            try!(match ch {
                0x09 => self.writer.write_all(b"\\t"),
                0x0A => self.writer.write_all(b"\\n"),
                0x0D => self.writer.write_all(b"\\r"),
                0x22 => self.writer.write_all(b"\\\""),
                0x5C => self.writer.write_all(b"\\\\"),
                ch if ch < 0xF => write!(self.writer, "\\0{:X}", ch),
                ch if ch < 0x20 => write!(self.writer, "\\{:X}", ch),
                ch => self.writer.write_all(&[ch]),
            });
        }
        self.writer.write_all(b"\"")
    }

    fn write_list(&mut self, value: &Vec<Value>) -> io::Result<()> {
        if value.is_empty() {
            return self.writer.write_all(b"[]");
        }

        let mut iter = value.iter().peekable();
        try!(self.format.start_compound(&mut self.writer, b'['));
        loop {
            match iter.next() {
                None => break,
                Some(value) => {
                    try!(self.write_value(value));
                    match iter.peek () {
                        Some(_) =>
                            try!(self.format.item_separator(&mut self.writer, value)),
                        None => (),
                    }
                },
            }
        }
        self.format.end_compound(&mut self.writer, b']')
    }

    #[inline]
    fn write_dict(&mut self, dict: &BTreeMap<String, Value>) -> io::Result<()> {
        if dict.is_empty() {
            return self.writer.write_all(b"{}");
        }

        try!(self.format.start_compound(&mut self.writer, b'{'));
        try!(self.write_keyval_items(dict));
        self.format.end_compound(&mut self.writer, b'}')
    }

    fn write_keyval_items(&mut self, dict: &BTreeMap<String, Value>) -> io::Result<()> {
        let mut iter = dict.iter().peekable();
        loop {
            match iter.next() {
                None => break,
                Some((key, value)) => {
                    try!(self.writer.write_all(key.as_bytes()));
                    try!(self.format.key_separator(&mut self.writer, value));
                    try!(self.write_value(value));
                    match iter.peek () {
                        Some(&(_, ref value)) =>
                            try!(self.format.item_separator(&mut self.writer, value)),
                        None => (),
                    }
                },
            }
        }
        Ok(())
    }

    #[inline]
    pub fn write_message(&mut self, value: &BTreeMap<String, Value>) -> io::Result<()> {
        self.write_keyval_items(value)
    }

    #[inline]
    pub fn write_framed_message(&mut self, value: &BTreeMap<String, Value>) -> io::Result<()> {
        self.write_dict(value)
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    use super::super::value::Value;
    use std::io::Cursor;
    use std::collections::BTreeMap;
    use std::f64::{NAN, INFINITY};

    macro_rules! make_write_test {
        ($name:ident, $value:expr, $pretty:expr, $compact:expr) => {
            #[test]
            fn $name() {
                {
                    println!("Pretty");
                    let mut output = Cursor::new(Vec::new());
                    Writer::pretty(&mut output).write_value($value).ok();
                    assert_eq!($pretty, String::from_utf8(output.into_inner()).unwrap());
                }
                {
                    println!("Compact");
                    let mut output = Cursor::new(Vec::new());
                    Writer::compact(&mut output).write_value($value).ok();
                    assert_eq!($compact, String::from_utf8(output.into_inner()).unwrap());
                }
            }
        }
    }

    make_write_test!(bool_true,  &Value::Bool(true),  "True", "True");
    make_write_test!(bool_false, &Value::Bool(false), "False", "False");

    make_write_test!(list_empty, &Value::List(vec![]), "[]", "[]");
    make_write_test!(list_one,   &Value::List(vec![Value::Bool(true)]), "[\n  True\n]", "[True]");
    make_write_test!(list_two,   &Value::List(vec![Value::Bool(true), Value::Bool(false)]),
        "[\n  True\n  False\n]", "[True,False]");
    make_write_test!(list_nested,
                     &Value::List(vec![
                                  Value::Bool(true),
                                  Value::List(vec![Value::Bool(false)])]),
                     "[\n  True\n  [\n    False\n  ]\n]", "[True,[False]]");

    make_write_test!(dict_empty, &Value::Dict(BTreeMap::new()), "{}", "{}");
    make_write_test!(dict_one,   &Value::Dict((|| {
        let mut b = BTreeMap::new();
        b.insert("item".to_string(), Value::Bool(true));
        b
    })()), "{\n  item: True\n}", "{item:True}");
    make_write_test!(dict_two,   &Value::Dict((|| {
        let mut b = BTreeMap::new();
        b.insert("foo".to_string(), Value::Bool(true));
        b.insert("bar".to_string(), Value::Bool(false));
        b
    })()), "{\n  bar: False\n  foo: True\n}", "{bar:False,foo:True}");

    macro_rules! make_write_string_test {
        ($name:ident, $value:expr, $expected:expr) => {
            make_write_test!($name, &Value::String($value.to_string()), $expected, $expected);
        }
    }

    make_write_string_test!(string_empty, "", "\"\"");
    make_write_string_test!(string_non_empty, "foo bar", "\"foo bar\"");
    make_write_string_test!(string_unicode, "☺", "\"☺\"");
    make_write_string_test!(string_escapes, "\n\r\t\\\"", "\"\\n\\r\\t\\\\\\\"\"");
    make_write_string_test!(string_hexcode, "\0", "\"\\00\"");

    macro_rules! make_write_number_test {
        ($t:ident, $name:ident, $value:expr, $expected:expr) => {
            make_write_test!($name, &Value::$t($value), $expected, $expected);
        }
    }

    make_write_number_test!(Integer, integer_zero, 0, "0");
    make_write_number_test!(Integer, integer_negative, -34, "-34");

    make_write_number_test!(Float, float_zero, 0.0, "0.0");
    make_write_number_test!(Float, float_suffix, 1f64, "1.0");
    make_write_number_test!(Float, float_positive, 4.5, "4.5");
    make_write_number_test!(Float, float_negative, -3.2, "-3.2");
    make_write_number_test!(Float, float_nan, NAN, "NaN");
    make_write_number_test!(Float, float_infinite, INFINITY, "inf");
}
<|endoftext|>