<commit_before>use super::Checked;

#[test]
fn readme_example() {
    let x = Checked::from(1_000_000_000_u32) * 3 + 2_000_000_000;
    match *x {
        Some(y) => println!("Didn't overflow: x is {}.", y),
        None => println!("The arithmetic overflowed."),
    }
}

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));

#[test]
fn order() {
    assert!(Checked::from(1_000_u32) <= Checked::from(10_000_u32));
    assert!(!(Checked::from(1_000_u32) <= Checked::from(None)));
    assert!((Checked::from(None) <= Checked::from(1_000_u32)));
}

#[test]
fn new_checked() {
    assert_eq!(Checked::new(100), Checked(Some(100)))
}

#[test]
fn from_checked() {
    assert_eq!(Checked::from(100_u32), Checked(Some(100_u32)));
    assert_eq!(Checked::from(Some(100_u32)), Checked(Some(100_u32)));
    assert_eq!(Checked::<u64>::from(None), Checked::<u64>(None));
}

#[test]
fn consuming_option_methods() {
    let x = Checked::from(1_000_i64);
    assert_eq!(x.expect("AHH!!!"), 1_000);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.unwrap(), 1_000);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.unwrap_or(10), 1_000);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.unwrap_or(10), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.unwrap_or_else(|| 10), 1_000);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.unwrap_or_else(|| 10), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.map(|x| x + 15), Some(1_015));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.map(|x| x + 15), None);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.map_or(10, |x| x + 15), 1_015);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.map_or(10, |x| x + 15), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.map_or_else(|| 10, |x| x + 15), 1_015);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.map_or_else(|| 10, |x| x + 15), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.ok_or(14), Ok(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.ok_or(14), Err(14));

    let x = Checked::from(1_000_i64);
    assert_eq!(x.ok_or_else(|| 14), Ok(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.ok_or_else(|| 14), Err(14));

    let x = Checked::from(1_000_i64);
    assert_eq!(x.and(Some(19)), Some(19));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.and(Some(19)), None);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.and_then(|x| Some(x + 15)), Some(1_015));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.and_then(|x| Some(x + 15)), None);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.or(Some(19)), Some(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.or(Some(19)), Some(19));

    let x = Checked::from(1_000_i64);
    assert_eq!(x.or_else(|| Some(19)), Some(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.or_else(|| Some(19)), Some(19));
}

#[test]
fn ref_option_methods() {
    let x = Checked::from(1_000_i64);
    let y = Checked::<i64>::from(None);

    assert!(x.is_some());
    assert!(!y.is_some());

    assert!(!x.is_none());
    assert!(y.is_none());

    // More thorough testing is done in the docs, this mostly just checks to see if it works at all.
    Option::as_ref(&x);
    Option::as_ref(&y);

    println!("Numbers in x: ");
    for t in x.iter() {
        println!("{:?}", t);
    }

    println!("Numbers in y: ");
    for t in y.iter() {
        println!("{:?}", t);
    }
}

#[test]
fn mut_ref_option_methods() {
    let mut x = Checked::from(1_000_i64);
    let mut y = Checked::<i64>::from(None);

    Option::as_mut(&mut x);
    Option::as_mut(&mut y);

    println!("Numbers in x: ");
    for t in x.iter_mut() {
        println!("{:?}", t);
    }

    println!("Numbers in y: ");
    for t in y.iter_mut() {
        println!("{:?}", t);
    }

    let z = x.take();

    assert_eq!(z, Some(1_000_i64));
    assert_eq!(x, Checked::<i64>::from(None));

    let w = y.take();
    assert_eq!(w, None);
    assert_eq!(y, Checked::<i64>::from(None));
}
<commit_msg>change test to reflect changes to PartialOrd<commit_after>use super::Checked;

#[test]
fn readme_example() {
    let x = Checked::from(1_000_000_000_u32) * 3 + 2_000_000_000;
    match *x {
        Some(y) => println!("Didn't overflow: x is {}.", y),
        None => println!("The arithmetic overflowed."),
    }
}

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));

#[test]
fn order() {
    assert!(Checked::from(1_000_u32) <= Checked::from(10_000_u32));
    assert!(!(Checked::from(1_000_u32) <= Checked::from(None)));
    assert!(!(Checked::from(None) <= Checked::from(1_000_u32)));
}

#[test]
fn new_checked() {
    assert_eq!(Checked::new(100), Checked(Some(100)))
}

#[test]
fn from_checked() {
    assert_eq!(Checked::from(100_u32), Checked(Some(100_u32)));
    assert_eq!(Checked::from(Some(100_u32)), Checked(Some(100_u32)));
    assert_eq!(Checked::<u64>::from(None), Checked::<u64>(None));
}

#[test]
fn consuming_option_methods() {
    let x = Checked::from(1_000_i64);
    assert_eq!(x.expect("AHH!!!"), 1_000);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.unwrap(), 1_000);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.unwrap_or(10), 1_000);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.unwrap_or(10), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.unwrap_or_else(|| 10), 1_000);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.unwrap_or_else(|| 10), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.map(|x| x + 15), Some(1_015));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.map(|x| x + 15), None);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.map_or(10, |x| x + 15), 1_015);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.map_or(10, |x| x + 15), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.map_or_else(|| 10, |x| x + 15), 1_015);

    let x = Checked::<i64>::from(None);
    assert_eq!(x.map_or_else(|| 10, |x| x + 15), 10);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.ok_or(14), Ok(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.ok_or(14), Err(14));

    let x = Checked::from(1_000_i64);
    assert_eq!(x.ok_or_else(|| 14), Ok(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.ok_or_else(|| 14), Err(14));

    let x = Checked::from(1_000_i64);
    assert_eq!(x.and(Some(19)), Some(19));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.and(Some(19)), None);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.and_then(|x| Some(x + 15)), Some(1_015));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.and_then(|x| Some(x + 15)), None);

    let x = Checked::from(1_000_i64);
    assert_eq!(x.or(Some(19)), Some(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.or(Some(19)), Some(19));

    let x = Checked::from(1_000_i64);
    assert_eq!(x.or_else(|| Some(19)), Some(1_000));

    let x = Checked::<i64>::from(None);
    assert_eq!(x.or_else(|| Some(19)), Some(19));
}

#[test]
fn ref_option_methods() {
    let x = Checked::from(1_000_i64);
    let y = Checked::<i64>::from(None);

    assert!(x.is_some());
    assert!(!y.is_some());

    assert!(!x.is_none());
    assert!(y.is_none());

    // More thorough testing is done in the docs, this mostly just checks to see if it works at all.
    Option::as_ref(&x);
    Option::as_ref(&y);

    println!("Numbers in x: ");
    for t in x.iter() {
        println!("{:?}", t);
    }

    println!("Numbers in y: ");
    for t in y.iter() {
        println!("{:?}", t);
    }
}

#[test]
fn mut_ref_option_methods() {
    let mut x = Checked::from(1_000_i64);
    let mut y = Checked::<i64>::from(None);

    Option::as_mut(&mut x);
    Option::as_mut(&mut y);

    println!("Numbers in x: ");
    for t in x.iter_mut() {
        println!("{:?}", t);
    }

    println!("Numbers in y: ");
    for t in y.iter_mut() {
        println!("{:?}", t);
    }

    let z = x.take();

    assert_eq!(z, Some(1_000_i64));
    assert_eq!(x, Checked::<i64>::from(None));

    let w = y.take();
    assert_eq!(w, None);
    assert_eq!(y, Checked::<i64>::from(None));
}
<|endoftext|>


<commit_before>//! Types for Gerber code generation.
//!
//! All types are stateless, meaning that they contain all information in order
//! to render themselves. This means for example that each `Coordinates`
//! instance contains a reference to the coordinate format to be used.

use std::convert::Into;

use ::{CoordinateFormat, CoordinateNumber};

/// Coordinates are part of an operation.
///
/// Coordinates are modal. If an X is omitted, the X coordinate of the
/// current point is used. Similar for Y.
#[derive(Debug, PartialEq, Eq)]
pub struct Coordinates {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl Coordinates {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: None, y: Some(y.into()), format: format }
    }
}

/// Coordinate offsets can be used for interpolate operations in circular
/// interpolation mode.
#[derive(Debug, PartialEq, Eq)]
pub struct CoordinateOffset {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl CoordinateOffset {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: None, y: Some(y.into()), format: format }
    }
}

// Root type

#[derive(Debug)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

// Main categories

#[derive(Debug)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug)]
pub enum ExtendedCode {
    /// FS
    CoordinateFormat(CoordinateFormat),
    /// MO
    Unit(Unit),
    /// AD
    ApertureDefinition(ApertureDefinition),
    /// AM
    ApertureMacro(::macros::ApertureMacro),
    /// LP
    LoadPolarity(Polarity),
    /// SR
    StepAndRepeat(StepAndRepeat),
    /// TF
    FileAttribute(::attributes::FileAttribute),
    /// TA
    ApertureAttribute(::attributes::ApertureAttribute),
    /// TD
    DeleteAttribute(String),
}

// Function codes

#[derive(Debug)]
pub enum DCode {
    Operation(Operation),
    SelectAperture(i32),
}

#[derive(Debug)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

#[derive(Debug)]
pub enum MCode {
    EndOfFile,
}

#[derive(Debug)]
pub enum Operation {
    /// D01 Command
    Interpolate(Coordinates, Option<CoordinateOffset>),
    /// D02 Command
    Move(Coordinates),
    /// D03 Command
    Flash(Coordinates),
}

#[derive(Debug)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug)]
pub enum QuadrantMode {
    Single,
    Multi,
}

// Extended codes

#[derive(Debug)]
pub enum Unit {
    Inches,
    Millimeters,
}

#[derive(Debug)]
pub struct ApertureDefinition {
    pub code: i32,
    pub aperture: Aperture,
}

#[derive(Debug)]
pub enum Aperture {
    Circle(Circle),
    Rectangle(Rectangular),
    Obround(Rectangular),
    Polygon(Polygon),
    Other(String),
}

#[derive(Debug)]
pub struct Circle {
    pub diameter: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Rectangular {
    pub x: f64,
    pub y: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Polygon {
    pub diameter: f64,
    pub vertices: u8, // 3--12
    pub rotation: Option<f64>,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub enum Polarity {
    Clear,
    Dark,
}

#[derive(Debug)]
pub enum StepAndRepeat {
    Open { repeat_x: u32, repeat_y: u32, distance_x: f64, distance_y: f64 },
    Close,
}

#[cfg(test)]
mod test {
    extern crate conv;

    use conv::TryFrom;
    use super::*;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_coordinates_into() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), CoordinateNumber::from(2), cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_coordinates_into_mixed() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), 2, cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

}
<commit_msg>Fix tests on Rust 1.13.0<commit_after>//! Types for Gerber code generation.
//!
//! All types are stateless, meaning that they contain all information in order
//! to render themselves. This means for example that each `Coordinates`
//! instance contains a reference to the coordinate format to be used.

use std::convert::Into;

use ::{CoordinateFormat, CoordinateNumber};

/// Coordinates are part of an operation.
///
/// Coordinates are modal. If an X is omitted, the X coordinate of the
/// current point is used. Similar for Y.
#[derive(Debug, PartialEq, Eq)]
pub struct Coordinates {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl Coordinates {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: None, y: Some(y.into()), format: format }
    }
}

/// Coordinate offsets can be used for interpolate operations in circular
/// interpolation mode.
#[derive(Debug, PartialEq, Eq)]
pub struct CoordinateOffset {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl CoordinateOffset {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: None, y: Some(y.into()), format: format }
    }
}

// Root type

#[derive(Debug)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

// Main categories

#[derive(Debug)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug)]
pub enum ExtendedCode {
    /// FS
    CoordinateFormat(CoordinateFormat),
    /// MO
    Unit(Unit),
    /// AD
    ApertureDefinition(ApertureDefinition),
    /// AM
    ApertureMacro(::macros::ApertureMacro),
    /// LP
    LoadPolarity(Polarity),
    /// SR
    StepAndRepeat(StepAndRepeat),
    /// TF
    FileAttribute(::attributes::FileAttribute),
    /// TA
    ApertureAttribute(::attributes::ApertureAttribute),
    /// TD
    DeleteAttribute(String),
}

// Function codes

#[derive(Debug)]
pub enum DCode {
    Operation(Operation),
    SelectAperture(i32),
}

#[derive(Debug)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

#[derive(Debug)]
pub enum MCode {
    EndOfFile,
}

#[derive(Debug)]
pub enum Operation {
    /// D01 Command
    Interpolate(Coordinates, Option<CoordinateOffset>),
    /// D02 Command
    Move(Coordinates),
    /// D03 Command
    Flash(Coordinates),
}

#[derive(Debug)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug)]
pub enum QuadrantMode {
    Single,
    Multi,
}

// Extended codes

#[derive(Debug)]
pub enum Unit {
    Inches,
    Millimeters,
}

#[derive(Debug)]
pub struct ApertureDefinition {
    pub code: i32,
    pub aperture: Aperture,
}

#[derive(Debug)]
pub enum Aperture {
    Circle(Circle),
    Rectangle(Rectangular),
    Obround(Rectangular),
    Polygon(Polygon),
    Other(String),
}

#[derive(Debug)]
pub struct Circle {
    pub diameter: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Rectangular {
    pub x: f64,
    pub y: f64,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub struct Polygon {
    pub diameter: f64,
    pub vertices: u8, // 3--12
    pub rotation: Option<f64>,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug)]
pub enum Polarity {
    Clear,
    Dark,
}

#[derive(Debug)]
pub enum StepAndRepeat {
    Open { repeat_x: u32, repeat_y: u32, distance_x: f64, distance_y: f64 },
    Close,
}

#[cfg(test)]
mod test {
    extern crate conv;

    use conv::TryFrom;
    use ::{CoordinateNumber, CoordinateFormat};
    use super::*;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_coordinates_into() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), CoordinateNumber::from(2), cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_coordinates_into_mixed() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), 2, cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

}
<|endoftext|>


<commit_before>extern crate euclid;

use euclid::*;

pub struct UniverseSpace;
pub struct ChildSpace;

pub type UVec = TypedVector2D<i32, UniverseSpace>;
pub type UPoint = TypedPoint2D<i32, UniverseSpace>;
pub type ChildVec = TypedVector2D<i32, ChildSpace>;
pub type ChildPoint = TypedPoint2D<i32, ChildSpace>;

// pub type FVec = TypedVector<f32>;

pub const zoom_scale: u32 = 2;
<commit_msg>Some simple helpers converting between vector types<commit_after>// extern crate euclid;

use num::Integer;

use euclid::*;

pub struct UniverseSpace;
pub struct ChildSpace;

pub type UVec = TypedVector2D<i32, UniverseSpace>;
pub type UPoint = TypedPoint2D<i32, UniverseSpace>;
pub type ChildVec = TypedVector2D<i32, ChildSpace>;
pub type ChildPoint = TypedPoint2D<i32, ChildSpace>;

// pub type FVec = TypedVector<f32>;

pub const zoom_scale: u32 = 2;

pub mod vectors {
    use types::*;

    #[inline]
    pub fn coerce_up(v: ChildVec) -> UVec {
        UVec::new(v.x, v.y)
    }

    #[inline]
    pub fn truncate_up(v: ChildVec) -> UVec {
        UVec::new(
            v.x.div_floor(&(zoom_scale as i32)),
            v.y.div_floor(&(zoom_scale as i32)),
        )
    }

    #[inline]
    pub fn mod_up(v: ChildVec) -> ChildVec {
        ChildVec::new(v.x % zoom_scale as i32, v.y % zoom_scale as i32)
    }

    #[inline]
    pub fn split_up(v: ChildVec) -> (UVec, ChildVec) {
        (truncate_up(v), mod_up(v))
    }

    #[inline]
    pub fn shift_down(v: UVec) -> ChildVec {
        ChildVec::new(v.x * (zoom_scale as i32), v.y * (zoom_scale as i32))
    }

    #[inline]
    pub fn coerce_down(v: UVec) -> ChildVec {
        ChildVec::new(v.x, v.y)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use UserDirectory;

pub fn get_application_name() -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_get_application_name())
    }
}

pub fn set_application_name(name: Option<&str>) {
    unsafe {
        ffi::g_set_application_name(name.to_glib_none().0)
    }
}

/// Same as [`get_prgname()`].
///
/// [`get_prgname()`]: fn.get_prgname.html
pub fn get_program_name() -> Option<String> {
    get_prgname()
}

pub fn get_prgname() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_prgname())
    }
}

/// Same as [`set_prgname()`].
///
/// [`set_prgname()`]: fn.set_prgname.html
pub fn set_program_name(name: Option<&str>) {
    set_prgname(name)
}

pub fn set_prgname(name: Option<&str>) {
    unsafe {
        ffi::g_set_prgname(name.to_glib_none().0)
    }
}

pub fn get_environ() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_full(ffi::g_get_environ())
    }
}

pub fn getenv(variable_name: &str) -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_getenv(variable_name.to_glib_none().0))
    }
}

pub fn setenv(variable_name: &str, value: &str, overwrite: bool) -> bool {
    unsafe {
        from_glib(ffi::g_setenv(variable_name.to_glib_none().0,
                                value.to_glib_none().0,
                                overwrite.to_glib()))
    }
}

pub fn unsetenv(variable_name: &str) {
    unsafe {
        ffi::g_unsetenv(variable_name.to_glib_none().0)
    }
}

pub fn listenv() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_none(ffi::g_listenv())
    }
}

pub fn get_user_name() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_name())
    }
}

pub fn get_real_name() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_real_name())
    }
}

pub fn get_user_cache_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_cache_dir())
    }
}

pub fn get_user_data_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_data_dir())
    }
}

pub fn get_user_config_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_config_dir())
    }
}

pub fn get_user_runtime_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_runtime_dir())
    }
}

pub fn get_user_special_dir(directory: UserDirectory) -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_special_dir(directory.to_glib()))
    }
}

pub fn get_system_data_dirs() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_none(ffi::g_get_system_data_dirs())
    }
}

pub fn get_system_config_dirs() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_none(ffi::g_get_system_config_dirs())
    }
}

pub fn reload_user_special_dirs_cache() {
    unsafe {
        ffi::g_reload_user_special_dirs_cache()
    }
}

pub fn get_host_name() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_host_name())
    }
}

pub fn get_home_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_home_dir())
    }
}

pub fn get_tmp_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_tmp_dir())
    }
}

pub fn get_current_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_current_dir())
    }
}

pub fn path_is_absolute(file_name: &str) -> bool {
    unsafe {
        from_glib(ffi::g_path_is_absolute(file_name.to_glib_none().0))
    }
}

pub fn path_skip_root(file_name: &str) -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_path_skip_root(file_name.to_glib_none().0))
    }
}

pub fn path_get_basename(file_name: &str) -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_path_get_basename(file_name.to_glib_none().0))
    }
}

pub fn path_get_dirname(file_name: &str) -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_path_get_dirname(file_name.to_glib_none().0))
    }
}

pub fn find_program_in_path(program: &str) -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_find_program_in_path(program.to_glib_none().0))
    }
}
<commit_msg>remove some functions from windows platform<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use UserDirectory;

pub fn get_application_name() -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_get_application_name())
    }
}

pub fn set_application_name(name: Option<&str>) {
    unsafe {
        ffi::g_set_application_name(name.to_glib_none().0)
    }
}

/// Same as [`get_prgname()`].
///
/// [`get_prgname()`]: fn.get_prgname.html
pub fn get_program_name() -> Option<String> {
    get_prgname()
}

pub fn get_prgname() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_prgname())
    }
}

/// Same as [`set_prgname()`].
///
/// [`set_prgname()`]: fn.set_prgname.html
pub fn set_program_name(name: Option<&str>) {
    set_prgname(name)
}

pub fn set_prgname(name: Option<&str>) {
    unsafe {
        ffi::g_set_prgname(name.to_glib_none().0)
    }
}

pub fn get_environ() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_full(ffi::g_get_environ())
    }
}

#[cfg(unix)]
pub fn getenv(variable_name: &str) -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_getenv(variable_name.to_glib_none().0))
    }
}

#[cfg(unix)]
pub fn setenv(variable_name: &str, value: &str, overwrite: bool) -> bool {
    unsafe {
        from_glib(ffi::g_setenv(variable_name.to_glib_none().0,
                                value.to_glib_none().0,
                                overwrite.to_glib()))
    }
}

#[cfg(unix)]
pub fn unsetenv(variable_name: &str) {
    unsafe {
        ffi::g_unsetenv(variable_name.to_glib_none().0)
    }
}

pub fn listenv() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_none(ffi::g_listenv())
    }
}

pub fn get_user_name() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_name())
    }
}

pub fn get_real_name() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_real_name())
    }
}

pub fn get_user_cache_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_cache_dir())
    }
}

pub fn get_user_data_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_data_dir())
    }
}

pub fn get_user_config_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_config_dir())
    }
}

pub fn get_user_runtime_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_runtime_dir())
    }
}

pub fn get_user_special_dir(directory: UserDirectory) -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_user_special_dir(directory.to_glib()))
    }
}

pub fn get_system_data_dirs() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_none(ffi::g_get_system_data_dirs())
    }
}

pub fn get_system_config_dirs() -> Vec<String> {
    unsafe {
        FromGlibPtrContainer::from_glib_none(ffi::g_get_system_config_dirs())
    }
}

pub fn reload_user_special_dirs_cache() {
    unsafe {
        ffi::g_reload_user_special_dirs_cache()
    }
}

pub fn get_host_name() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_host_name())
    }
}

pub fn get_home_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_home_dir())
    }
}

pub fn get_tmp_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_tmp_dir())
    }
}

#[cfg(unix)]
pub fn get_current_dir() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_current_dir())
    }
}

pub fn path_is_absolute(file_name: &str) -> bool {
    unsafe {
        from_glib(ffi::g_path_is_absolute(file_name.to_glib_none().0))
    }
}

pub fn path_skip_root(file_name: &str) -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_path_skip_root(file_name.to_glib_none().0))
    }
}

pub fn path_get_basename(file_name: &str) -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_path_get_basename(file_name.to_glib_none().0))
    }
}

pub fn path_get_dirname(file_name: &str) -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_path_get_dirname(file_name.to_glib_none().0))
    }
}

pub fn find_program_in_path(program: &str) -> Option<String> {
    unsafe {
        from_glib_full(ffi::g_find_program_in_path(program.to_glib_none().0))
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::Ordering;

use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_};
use syntax::codemap::{CodeMap, Span, BytePos};

use Indent;
use comment::FindUncommented;
use rewrite::{Rewrite, RewriteContext};

use SKIP_ANNOTATION;

// Computes the length of a string's last line, minus offset.
#[inline]
pub fn extra_offset(text: &str, offset: Indent) -> usize {
    match text.rfind('\n') {
        // 1 for newline character
        Some(idx) => text.len() - idx - 1 - offset.width(),
        None => text.len(),
    }
}

#[inline]
pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos {
    let snippet = codemap.span_to_snippet(original).unwrap();
    let offset = snippet.find_uncommented(needle).unwrap() + needle.len();

    original.lo + BytePos(offset as u32)
}

#[inline]
pub fn format_visibility(vis: Visibility) -> &'static str {
    match vis {
        Visibility::Public => "pub ",
        Visibility::Inherited => "",
    }
}

#[inline]
pub fn format_mutability(mutability: ast::Mutability) -> &'static str {
    match mutability {
        ast::Mutability::MutMutable => "mut ",
        ast::Mutability::MutImmutable => "",
    }
}

// The width of the first line in s.
#[inline]
pub fn first_line_width(s: &str) -> usize {
    match s.find('\n') {
        Some(n) => n,
        None => s.len(),
    }
}

// The width of the last line in s.
#[inline]
pub fn last_line_width(s: &str) -> usize {
    match s.rfind('\n') {
        Some(n) => s.len() - n - 1,
        None => s.len(),
    }
}

#[inline]
fn is_skip(meta_item: &MetaItem) -> bool {
    match meta_item.node {
        MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION,
        _ => false,
    }
}

#[inline]
pub fn contains_skip(attrs: &[Attribute]) -> bool {
    attrs.iter().any(|a| is_skip(&a.node.value))
}

// Find the end of a TyParam
#[inline]
pub fn end_typaram(typaram: &ast::TyParam) -> BytePos {
    typaram.bounds
           .last()
           .map(|bound| {
               match *bound {
                   ast::RegionTyParamBound(ref lt) => lt.span,
                   ast::TraitTyParamBound(ref prt, _) => prt.span,
               }
           })
           .unwrap_or(typaram.span)
           .hi
}

#[inline]
#[cfg(target_pointer_width="64")]
// Based on the trick layed out at
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
pub fn round_up_to_power_of_two(mut x: usize) -> usize {
    x = x.wrapping_sub(1);
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x |= x >> 32;
    x.wrapping_add(1)
}

#[inline]
#[cfg(target_pointer_width="32")]
pub fn round_up_to_power_of_two(mut x: usize) -> usize {
    x = x.wrapping_sub(1);
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x.wrapping_add(1)
}

// Macro for deriving implementations of Decodable for enums
#[macro_export]
macro_rules! impl_enum_decodable {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::rustc_serialize::Decodable for $e {
            fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
                let s = try!(d.read_str());
                match &*s {
                    $(
                        stringify!($x) => Ok($e::$x),
                    )*
                    _ => Err(d.error("Bad variant")),
                }
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                match &*s {
                    $(
                        stringify!($x) => Ok($e::$x),
                    )*
                    _ => Err("Bad variant"),
                }
            }
        }

        impl ::config::ConfigType for $e {
            fn get_variant_names() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

// Same as try!, but for Option
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => (match $expr {
        Some(val) => val,
        None => { return None; }
    })
}

// Wraps string-like values in an Option. Returns Some when the string adheres
// to the Rewrite constraints defined for the Rewrite trait and else otherwise.
pub fn wrap_str<S: AsRef<str>>(s: S, max_width: usize, width: usize, offset: Indent) -> Option<S> {
    {
        let snippet = s.as_ref();

        if !snippet.contains('\n') && snippet.len() > width {
            return None;
        } else {
            let mut lines = snippet.lines();

            // The caller of this function has already placed `offset`
            // characters on the first line.
            let first_line_max_len = try_opt!(max_width.checked_sub(offset.width()));
            if lines.next().unwrap().len() > first_line_max_len {
                return None;
            }

            // The other lines must fit within the maximum width.
            if lines.find(|line| line.len() > max_width).is_some() {
                return None;
            }

            // `width` is the maximum length of the last line, excluding
            // indentation.
            // A special check for the last line, since the caller may
            // place trailing characters on this line.
            if snippet.lines().rev().next().unwrap().len() > offset.width() + width {
                return None;
            }
        }
    }

    Some(s)
}

impl Rewrite for String {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
        wrap_str(self, context.config.max_width, width, offset).map(ToOwned::to_owned)
    }
}

// Binary search in integer range. Returns the first Ok value returned by the
// callback.
// The callback takes an integer and returns either an Ok, or an Err indicating
// whether the `guess' was too high (Ordering::Less), or too low.
// This function is guaranteed to try to the hi value first.
pub fn binary_search<C, T>(mut lo: usize, mut hi: usize, callback: C) -> Option<T>
    where C: Fn(usize) -> Result<T, Ordering>
{
    let mut middle = hi;

    while lo <= hi {
        match callback(middle) {
            Ok(val) => return Some(val),
            Err(Ordering::Less) => {
                hi = middle - 1;
            }
            Err(..) => {
                lo = middle + 1;
            }
        }
        middle = (hi + lo) / 2;
    }

    None
}

#[test]
fn bin_search_test() {
    let closure = |i| {
        match i {
            4 => Ok(()),
            j if j > 4 => Err(Ordering::Less),
            j if j < 4 => Err(Ordering::Greater),
            _ => unreachable!(),
        }
    };

    assert_eq!(Some(()), binary_search(1, 10, &closure));
    assert_eq!(None, binary_search(1, 3, &closure));
    assert_eq!(Some(()), binary_search(0, 44, &closure));
    assert_eq!(Some(()), binary_search(4, 125, &closure));
    assert_eq!(None, binary_search(6, 100, &closure));
}

#[test]
fn power_rounding() {
    assert_eq!(0, round_up_to_power_of_two(0));
    assert_eq!(1, round_up_to_power_of_two(1));
    assert_eq!(64, round_up_to_power_of_two(33));
    assert_eq!(256, round_up_to_power_of_two(256));
}
<commit_msg>Ignore #[cfg_attr(rustfmt, rustfmt_skip)] functions<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::Ordering;

use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_};
use syntax::codemap::{CodeMap, Span, BytePos};

use Indent;
use comment::FindUncommented;
use rewrite::{Rewrite, RewriteContext};

use SKIP_ANNOTATION;

// Computes the length of a string's last line, minus offset.
#[inline]
pub fn extra_offset(text: &str, offset: Indent) -> usize {
    match text.rfind('\n') {
        // 1 for newline character
        Some(idx) => text.len() - idx - 1 - offset.width(),
        None => text.len(),
    }
}

#[inline]
pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos {
    let snippet = codemap.span_to_snippet(original).unwrap();
    let offset = snippet.find_uncommented(needle).unwrap() + needle.len();

    original.lo + BytePos(offset as u32)
}

#[inline]
pub fn format_visibility(vis: Visibility) -> &'static str {
    match vis {
        Visibility::Public => "pub ",
        Visibility::Inherited => "",
    }
}

#[inline]
pub fn format_mutability(mutability: ast::Mutability) -> &'static str {
    match mutability {
        ast::Mutability::MutMutable => "mut ",
        ast::Mutability::MutImmutable => "",
    }
}

// The width of the first line in s.
#[inline]
pub fn first_line_width(s: &str) -> usize {
    match s.find('\n') {
        Some(n) => n,
        None => s.len(),
    }
}

// The width of the last line in s.
#[inline]
pub fn last_line_width(s: &str) -> usize {
    match s.rfind('\n') {
        Some(n) => s.len() - n - 1,
        None => s.len(),
    }
}

#[inline]
fn is_skip(meta_item: &MetaItem) -> bool {
    match meta_item.node {
        MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION,
        MetaItem_::MetaList(ref s, ref l) => {
            *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1])
        }
        _ => false,
    }
}

#[inline]
pub fn contains_skip(attrs: &[Attribute]) -> bool {
    attrs.iter().any(|a| is_skip(&a.node.value))
}

// Find the end of a TyParam
#[inline]
pub fn end_typaram(typaram: &ast::TyParam) -> BytePos {
    typaram.bounds
           .last()
           .map(|bound| {
               match *bound {
                   ast::RegionTyParamBound(ref lt) => lt.span,
                   ast::TraitTyParamBound(ref prt, _) => prt.span,
               }
           })
           .unwrap_or(typaram.span)
           .hi
}

#[inline]
#[cfg(target_pointer_width="64")]
// Based on the trick layed out at
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
pub fn round_up_to_power_of_two(mut x: usize) -> usize {
    x = x.wrapping_sub(1);
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x |= x >> 32;
    x.wrapping_add(1)
}

#[inline]
#[cfg(target_pointer_width="32")]
pub fn round_up_to_power_of_two(mut x: usize) -> usize {
    x = x.wrapping_sub(1);
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x.wrapping_add(1)
}

// Macro for deriving implementations of Decodable for enums
#[macro_export]
macro_rules! impl_enum_decodable {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::rustc_serialize::Decodable for $e {
            fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
                let s = try!(d.read_str());
                match &*s {
                    $(
                        stringify!($x) => Ok($e::$x),
                    )*
                    _ => Err(d.error("Bad variant")),
                }
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                match &*s {
                    $(
                        stringify!($x) => Ok($e::$x),
                    )*
                    _ => Err("Bad variant"),
                }
            }
        }

        impl ::config::ConfigType for $e {
            fn get_variant_names() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

// Same as try!, but for Option
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => (match $expr {
        Some(val) => val,
        None => { return None; }
    })
}

// Wraps string-like values in an Option. Returns Some when the string adheres
// to the Rewrite constraints defined for the Rewrite trait and else otherwise.
pub fn wrap_str<S: AsRef<str>>(s: S, max_width: usize, width: usize, offset: Indent) -> Option<S> {
    {
        let snippet = s.as_ref();

        if !snippet.contains('\n') && snippet.len() > width {
            return None;
        } else {
            let mut lines = snippet.lines();

            // The caller of this function has already placed `offset`
            // characters on the first line.
            let first_line_max_len = try_opt!(max_width.checked_sub(offset.width()));
            if lines.next().unwrap().len() > first_line_max_len {
                return None;
            }

            // The other lines must fit within the maximum width.
            if lines.find(|line| line.len() > max_width).is_some() {
                return None;
            }

            // `width` is the maximum length of the last line, excluding
            // indentation.
            // A special check for the last line, since the caller may
            // place trailing characters on this line.
            if snippet.lines().rev().next().unwrap().len() > offset.width() + width {
                return None;
            }
        }
    }

    Some(s)
}

impl Rewrite for String {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
        wrap_str(self, context.config.max_width, width, offset).map(ToOwned::to_owned)
    }
}

// Binary search in integer range. Returns the first Ok value returned by the
// callback.
// The callback takes an integer and returns either an Ok, or an Err indicating
// whether the `guess' was too high (Ordering::Less), or too low.
// This function is guaranteed to try to the hi value first.
pub fn binary_search<C, T>(mut lo: usize, mut hi: usize, callback: C) -> Option<T>
    where C: Fn(usize) -> Result<T, Ordering>
{
    let mut middle = hi;

    while lo <= hi {
        match callback(middle) {
            Ok(val) => return Some(val),
            Err(Ordering::Less) => {
                hi = middle - 1;
            }
            Err(..) => {
                lo = middle + 1;
            }
        }
        middle = (hi + lo) / 2;
    }

    None
}

#[test]
fn bin_search_test() {
    let closure = |i| {
        match i {
            4 => Ok(()),
            j if j > 4 => Err(Ordering::Less),
            j if j < 4 => Err(Ordering::Greater),
            _ => unreachable!(),
        }
    };

    assert_eq!(Some(()), binary_search(1, 10, &closure));
    assert_eq!(None, binary_search(1, 3, &closure));
    assert_eq!(Some(()), binary_search(0, 44, &closure));
    assert_eq!(Some(()), binary_search(4, 125, &closure));
    assert_eq!(None, binary_search(6, 100, &closure));
}

#[test]
fn power_rounding() {
    assert_eq!(0, round_up_to_power_of_two(0));
    assert_eq!(1, round_up_to_power_of_two(1));
    assert_eq!(64, round_up_to_power_of_two(33));
    assert_eq!(256, round_up_to_power_of_two(256));
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}
<commit_msg>[Value] Defined value type close to the spec.<commit_after>#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications
    Ext(i8, Vec<u8>),
}
<|endoftext|>


<commit_before>use super::{Result, Error};

use std::io::{Read, Write};
use std::sync::mpsc;
use std::net::UdpSocket;

use websocket::ws::sender::Sender as SenderTrait;
use websocket::client::{Client, Sender, Receiver};
use websocket::stream::WebSocketStream;
use websocket::message::{Message as WsMessage, Type as MessageType};

use serde_json;
use serde_json::builder::ObjectBuilder;

use byteorder::{LittleEndian, BigEndian, WriteBytesExt, ReadBytesExt};

use super::model::*;

/// A websocket connection to the voice servers.
///
/// A VoiceConnection may be active or inactive. Use `voice_connect` and
/// `voice_disconnect` on the `Connection` you are feeding it events from to
/// change what channel it is connected to.
pub struct VoiceConnection {
	user_id: UserId,
	session_id: Option<String>,
	channel: Option<mpsc::Sender<Status>>,
	queue: Vec<AudioSource>,
}

impl VoiceConnection {
	/// Prepare a VoiceConnection for later use.
	pub fn new(user_id: UserId) -> VoiceConnection {
		VoiceConnection {
			user_id: user_id,
			session_id: None,
			channel: None,
			queue: Vec::new(),
		}
	}

	/// Update the voice state based on an event.
	pub fn update(&mut self, event: &Event) {
		match *event {
			Event::VoiceStateUpdate(_, ref voice_state) => {
				if voice_state.user_id == self.user_id {
					self.session_id = Some(voice_state.session_id.clone());
					if !voice_state.channel_id.is_some() {
						self.channel.take(); // drop the connection
					}
				}
			}
			Event::VoiceServerUpdate { ref server_id, ref endpoint, ref token } => {
				self.connect(server_id, endpoint.clone(), token).expect("Voice::connect failure")
			}
			_ => {}
		}
	}

	/// Check whether the voice thread is currently running.
	pub fn is_running(&self) -> bool {
		match self.channel {
			None => false,
			Some(ref channel) => channel.send(Status::NoOp).is_ok(),
		}
	}

	/// Push a source of raw PCM data to the queue.
	#[inline]
	pub fn push_pcm<R: Read + Send + 'static>(&mut self, read: R) {
		self.push_internal(Box::new(read));
	}

	/// Push the path to an audio file which ffmpeg can decode.
	pub fn push_file<P: AsRef<::std::path::Path>>(&mut self, path: P) -> Result<()> {
		use std::process::{Command, Stdio};
		let child = try!(Command::new("ffmpeg")
			.args(&[
				"-i", try!(path.as_ref().to_str().ok_or(Error::Other("File path is not utf8 - fixme?"))),
				"-f", "s16le",
				"-ac", "1",
				"-ar", "48000",
				"-acodec", "pcm_s16le",
				"-"])
			.stdin(Stdio::null())
			.stdout(Stdio::piped())
			.stderr(Stdio::null())
			.spawn());
		let stdout = try!(child.stdout.ok_or(Error::Other("Child process missing stdout")));
		self.push_internal(Box::new(stdout));
		Ok(())
	}

	/// Stop any currently playing audio and clear the queue.
	pub fn stop_audio(&mut self) {
		self.channel.as_ref().map(|ch| ch.send(Status::Clear));
		self.queue.clear();
	}

	fn push_internal(&mut self, source: AudioSource) {
		match self.channel {
			None => self.queue.push(source),
			Some(ref channel) => match channel.send(Status::Push(source)) {
				Ok(()) => {},
				Err(mpsc::SendError(Status::Push(source))) => self.queue.push(source),
				Err(_) => unreachable!()
			}
		}
	}

	fn connect(&mut self, server_id: &ServerId, mut endpoint: String, token: &str) -> Result<()> {
		self.channel.take(); // drop any previous connection

		// prepare the URL: drop the :80 and prepend wss://
		if endpoint.ends_with(":80") {
			let len = endpoint.len();
			endpoint.truncate(len - 3);
		}
		// establish the websocket connection
		let url = match ::websocket::client::request::Url::parse(&format!("wss://{}", endpoint)) {
			Ok(url) => url,
			Err(_) => return Err(Error::Other("Invalid URL in Voice::connect()"))
		};
		let response = try!(try!(Client::connect(url)).send());
		try!(response.validate());
		let (mut sender, receiver) = response.begin().split();

		// send the handshake
		let map = ObjectBuilder::new()
			.insert("op", 0)
			.insert_object("d", |object| object
				.insert("server_id", &server_id.0)
				.insert("user_id", &self.user_id.0)
				.insert("session_id", self.session_id.as_ref().expect("no session id"))
				.insert("token", token)
			)
			.unwrap();
		try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

		// spin up the voice thread, where most of the action will take place
		let (tx, rx) = mpsc::channel();
		try!(::std::thread::Builder::new()
			.name("Discord Voice Thread".into())
			.spawn(move || voice_thread(endpoint, sender, receiver, rx).unwrap()));
		for source in ::std::mem::replace(&mut self.queue, Vec::new()) {
			let _ = tx.send(Status::Push(source));
		}
		self.channel = Some(tx);
		Ok(())
	}
}

type AudioSource = Box<::std::io::Read + Send>;

enum Status {
	Push(AudioSource),
	Clear,
	NoOp,
}

fn recv_message(receiver: &mut Receiver<WebSocketStream>) -> Result<VoiceEvent> {
	use websocket::ws::receiver::Receiver;
	let message: WsMessage = try!(receiver.recv_message());
	if message.opcode != MessageType::Text {
		return Err(Error::Other("Got an non-Text frame as voice handshake response"))
	}
	let json: serde_json::Value = try!(serde_json::from_reader(&message.payload[..]));
	let original = format!("{:?}", json);
	VoiceEvent::decode(json).map_err(|err| {
		// If there was a decode failure, print the original json for debugging
		warn!("Error vdecoding: {}", original);
		err
	})
}

fn voice_thread(
	endpoint: String,
	mut sender: Sender<WebSocketStream>,
	mut receiver: Receiver<WebSocketStream>,
	channel: mpsc::Receiver<Status>,
) -> Result<()> {
	use std::io::Cursor;

	// read the first websocket message
	let (interval, port, ssrc, modes) = match try!(recv_message(&mut receiver)) {
		VoiceEvent::Handshake { heartbeat_interval, port, ssrc, modes } => (heartbeat_interval, port, ssrc, modes),
		_ => return Err(Error::Other("First voice message was not 4/handshake"))
	};
	if !modes.iter().find(|&s| s == "plain").is_some() {
		return Err(Error::Other("Plain voice mode is unavailable"))
	}

	// bind a UDP socket and send the ssrc value in a packet as identification
	let udp = try!(UdpSocket::bind("0.0.0.0:0"));
	let mut bytes = [0; 4];
	try!(Cursor::new(&mut bytes[..]).write_u32::<BigEndian>(ssrc));
	try!(udp.send_to(&bytes, (&endpoint[..], port)));

	// receive the response to the identification to get port and address info
	let mut bytes = [0; 256];
	let (len, _remote_addr) = try!(udp.recv_from(&mut bytes));
	let mut cursor = Cursor::new(&bytes[..len]);
	let _ = try!(cursor.read_u32::<LittleEndian>()); // discard padding
	let port_number = try!(cursor.read_u16::<LittleEndian>());

	// send the acknowledgement websocket message
	let map = ObjectBuilder::new()
		.insert("op", 1)
		.insert_object("d", |object| object
			.insert("protocol", "udp")
			.insert_object("data", |object| object
				.insert("address", "")
				.insert("port", port_number)
				.insert("mode", "plain")
			)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	// discard websocket messages until we get the Ready
	loop {
		match try!(recv_message(&mut receiver)) {
			VoiceEvent::Ready { mode, secret_key } => {
				if secret_key.len() != 0 {
					debug!("Secret key: {:?}", secret_key);
				}
				if mode != "plain" {
					return Err(Error::Other("Voice mode in Ready was not 'plain'"))
				}
				break
			}
			VoiceEvent::Unknown(op, value) => debug!("Unknown message type: {}/{:?}", op, value),
			_ => {},
		}
	}

	// start a drain thread for the websocket receiver - without this, eventually
	// the OS buffer will fill and the connection will be dropped
	try!(::std::thread::Builder::new()
		.name("Discord Voice Drain Thread".into())
		.spawn(move || drain_thread(receiver)));

	// prepare buffers for later use
	let mut opus = try!(::utils::OpusEncoder::new());
	let mut audio_queue = ::std::collections::VecDeque::new();
	let mut audio_buffer = vec![0; 960];
	let mut packet = Vec::with_capacity(256);
	let mut sequence = 0;
	let mut timestamp = 0;

	let audio_duration = ::time::Duration::milliseconds(20);
	let keepalive_duration = ::time::Duration::milliseconds(interval as i64);
	let mut audio_timer = ::utils::Timer::new(audio_duration);
	let mut keepalive_timer = ::utils::Timer::new(keepalive_duration);

	// start the main loop
	info!("Voice connected to {}", endpoint);
	'outer: loop {
		::std::thread::sleep_ms(3);

		loop {
			match channel.try_recv() {
				Ok(Status::Push(source)) => {
					if audio_queue.len() == 0 {
						try!(set_speaking(&mut sender, true));
					}
					audio_queue.push_back(source)
				},
				Ok(Status::Clear) => audio_queue.clear(),
				Ok(Status::NoOp) => {},
				Err(mpsc::TryRecvError::Empty) => break,
				Err(mpsc::TryRecvError::Disconnected) => break 'outer,
			}
		}

		if keepalive_timer.check_and_add(keepalive_duration) {
			let map = ObjectBuilder::new()
				.insert("op", 3)
				.insert("d", serde_json::Value::Null)
				.unwrap();
			let json = try!(serde_json::to_string(&map));
			try!(sender.send_message(&WsMessage::text(json)));
		}

		if audio_timer.check_and_add(audio_duration) && audio_queue.len() > 0 {
			const HEADER_LEN: usize = 12;
			// prepare the packet header
			packet.clear();
			try!(packet.write_all(&[0x80, 0x78]));
			try!(packet.write_u16::<BigEndian>(sequence));
			try!(packet.write_u32::<BigEndian>(timestamp));
			try!(packet.write_u32::<BigEndian>(ssrc));
			let zeroes = packet.capacity() - HEADER_LEN;
			packet.extend(::std::iter::repeat(0).take(zeroes));

			// read the audio from the source
			let len = try!(next_frame(&mut audio_queue[0], &mut audio_buffer[..]));
			if len < audio_buffer.len() {
				// zero-fill the buffer and advance to the next audio source
				for value in &mut audio_buffer[len..] {
					*value = 0;
				}
				audio_queue.pop_front();
				if audio_queue.len() == 0 {
					try!(set_speaking(&mut sender, false));
				}
			}

			// encode the audio data and transmit it
			let len = opus.encode(&audio_buffer, &mut packet[HEADER_LEN..]).expect("failed encode");
			try!(udp.send_to(&packet[..len + HEADER_LEN], (&endpoint[..], port)));

			sequence = sequence.wrapping_add(1);
			timestamp = timestamp.wrapping_add(960);
		}
	}

	// shutting down the sender like this will also terminate the drain thread
	try!(sender.get_mut().shutdown(::std::net::Shutdown::Both));
	info!("Voice disconnected");
	Ok(())
}

fn set_speaking(sender: &mut Sender<WebSocketStream>, speaking: bool) -> Result<()> {
	debug!("Speaking: {}", speaking);
	let map = ObjectBuilder::new()
		.insert("op", 5)
		.insert_object("d", |object| object
			.insert("speaking", speaking)
			.insert("delay", 0)
		)
		.unwrap();
	sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))).map_err(From::from)
}

fn next_frame(source: &mut AudioSource, buffer: &mut [i16]) -> Result<usize> {
	for (i, val) in buffer.iter_mut().enumerate() {
		*val = match source.read_i16::<LittleEndian>() {
			Ok(val) => val / 3, // TODO: add volume controls
			Err(::byteorder::Error::UnexpectedEOF) => return Ok(i),
			Err(::byteorder::Error::Io(e)) => return Err(From::from(e))
		};
	}
	Ok(buffer.len())
}

fn drain_thread(mut receiver: Receiver<WebSocketStream>) -> Receiver<WebSocketStream> {
	while let Ok(_) = recv_message(&mut receiver) {}
	receiver
}
<commit_msg>Resolve voice address once instead of repeatedly<commit_after>use super::{Result, Error};

use std::io::{Read, Write};
use std::sync::mpsc;
use std::net::UdpSocket;

use websocket::ws::sender::Sender as SenderTrait;
use websocket::client::{Client, Sender, Receiver};
use websocket::stream::WebSocketStream;
use websocket::message::{Message as WsMessage, Type as MessageType};

use serde_json;
use serde_json::builder::ObjectBuilder;

use byteorder::{LittleEndian, BigEndian, WriteBytesExt, ReadBytesExt};

use super::model::*;

/// A websocket connection to the voice servers.
///
/// A VoiceConnection may be active or inactive. Use `voice_connect` and
/// `voice_disconnect` on the `Connection` you are feeding it events from to
/// change what channel it is connected to.
pub struct VoiceConnection {
	user_id: UserId,
	session_id: Option<String>,
	channel: Option<mpsc::Sender<Status>>,
	queue: Vec<AudioSource>,
}

impl VoiceConnection {
	/// Prepare a VoiceConnection for later use.
	pub fn new(user_id: UserId) -> VoiceConnection {
		VoiceConnection {
			user_id: user_id,
			session_id: None,
			channel: None,
			queue: Vec::new(),
		}
	}

	/// Update the voice state based on an event.
	pub fn update(&mut self, event: &Event) {
		match *event {
			Event::VoiceStateUpdate(_, ref voice_state) => {
				if voice_state.user_id == self.user_id {
					self.session_id = Some(voice_state.session_id.clone());
					if !voice_state.channel_id.is_some() {
						self.channel.take(); // drop the connection
					}
				}
			}
			Event::VoiceServerUpdate { ref server_id, ref endpoint, ref token } => {
				self.connect(server_id, endpoint.clone(), token).expect("Voice::connect failure")
			}
			_ => {}
		}
	}

	/// Check whether the voice thread is currently running.
	pub fn is_running(&self) -> bool {
		match self.channel {
			None => false,
			Some(ref channel) => channel.send(Status::NoOp).is_ok(),
		}
	}

	/// Push a source of raw PCM data to the queue.
	#[inline]
	pub fn push_pcm<R: Read + Send + 'static>(&mut self, read: R) {
		self.push_internal(Box::new(read));
	}

	/// Push the path to an audio file which ffmpeg can decode.
	pub fn push_file<P: AsRef<::std::path::Path>>(&mut self, path: P) -> Result<()> {
		use std::process::{Command, Stdio};
		let child = try!(Command::new("ffmpeg")
			.args(&[
				"-i", try!(path.as_ref().to_str().ok_or(Error::Other("File path is not utf8 - fixme?"))),
				"-f", "s16le",
				"-ac", "1",
				"-ar", "48000",
				"-acodec", "pcm_s16le",
				"-"])
			.stdin(Stdio::null())
			.stdout(Stdio::piped())
			.stderr(Stdio::null())
			.spawn());
		let stdout = try!(child.stdout.ok_or(Error::Other("Child process missing stdout")));
		self.push_internal(Box::new(stdout));
		Ok(())
	}

	/// Stop any currently playing audio and clear the queue.
	pub fn stop_audio(&mut self) {
		self.channel.as_ref().map(|ch| ch.send(Status::Clear));
		self.queue.clear();
	}

	fn push_internal(&mut self, source: AudioSource) {
		match self.channel {
			None => self.queue.push(source),
			Some(ref channel) => match channel.send(Status::Push(source)) {
				Ok(()) => {},
				Err(mpsc::SendError(Status::Push(source))) => self.queue.push(source),
				Err(_) => unreachable!()
			}
		}
	}

	fn connect(&mut self, server_id: &ServerId, mut endpoint: String, token: &str) -> Result<()> {
		self.channel.take(); // drop any previous connection

		// prepare the URL: drop the :80 and prepend wss://
		if endpoint.ends_with(":80") {
			let len = endpoint.len();
			endpoint.truncate(len - 3);
		}
		// establish the websocket connection
		let url = match ::websocket::client::request::Url::parse(&format!("wss://{}", endpoint)) {
			Ok(url) => url,
			Err(_) => return Err(Error::Other("Invalid URL in Voice::connect()"))
		};
		let response = try!(try!(Client::connect(url)).send());
		try!(response.validate());
		let (mut sender, receiver) = response.begin().split();

		// send the handshake
		let map = ObjectBuilder::new()
			.insert("op", 0)
			.insert_object("d", |object| object
				.insert("server_id", &server_id.0)
				.insert("user_id", &self.user_id.0)
				.insert("session_id", self.session_id.as_ref().expect("no session id"))
				.insert("token", token)
			)
			.unwrap();
		try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

		// spin up the voice thread, where most of the action will take place
		let (tx, rx) = mpsc::channel();
		try!(::std::thread::Builder::new()
			.name("Discord Voice Thread".into())
			.spawn(move || voice_thread(endpoint, sender, receiver, rx).unwrap()));
		for source in ::std::mem::replace(&mut self.queue, Vec::new()) {
			let _ = tx.send(Status::Push(source));
		}
		self.channel = Some(tx);
		Ok(())
	}
}

type AudioSource = Box<::std::io::Read + Send>;

enum Status {
	Push(AudioSource),
	Clear,
	NoOp,
}

fn recv_message(receiver: &mut Receiver<WebSocketStream>) -> Result<VoiceEvent> {
	use websocket::ws::receiver::Receiver;
	let message: WsMessage = try!(receiver.recv_message());
	if message.opcode != MessageType::Text {
		return Err(Error::Other("Got an non-Text frame as voice handshake response"))
	}
	let json: serde_json::Value = try!(serde_json::from_reader(&message.payload[..]));
	let original = format!("{:?}", json);
	VoiceEvent::decode(json).map_err(|err| {
		// If there was a decode failure, print the original json for debugging
		warn!("Error vdecoding: {}", original);
		err
	})
}

fn voice_thread(
	endpoint: String,
	mut sender: Sender<WebSocketStream>,
	mut receiver: Receiver<WebSocketStream>,
	channel: mpsc::Receiver<Status>,
) -> Result<()> {
	use std::io::Cursor;

	// read the first websocket message
	let (interval, port, ssrc, modes) = match try!(recv_message(&mut receiver)) {
		VoiceEvent::Handshake { heartbeat_interval, port, ssrc, modes } => (heartbeat_interval, port, ssrc, modes),
		_ => return Err(Error::Other("First voice message was not 4/handshake"))
	};
	if !modes.iter().find(|&s| s == "plain").is_some() {
		return Err(Error::Other("Plain voice mode is unavailable"))
	}

	// bind a UDP socket and send the ssrc value in a packet as identification
	let udp = try!(UdpSocket::bind("0.0.0.0:0"));
	let mut bytes = [0; 4];
	try!(Cursor::new(&mut bytes[..]).write_u32::<BigEndian>(ssrc));
	let destination = {
		use std::net::ToSocketAddrs;
		try!(try!((&endpoint[..], port).to_socket_addrs())
			.next()
			.ok_or(Error::Other("Failed to resolve voice hostname")))
	};
	try!(udp.send_to(&bytes, destination));

	// receive the response to the identification to get port and address info
	let mut bytes = [0; 256];
	let (len, _remote_addr) = try!(udp.recv_from(&mut bytes));
	let mut cursor = Cursor::new(&bytes[..len]);
	let _ = try!(cursor.read_u32::<LittleEndian>()); // discard padding
	let port_number = try!(cursor.read_u16::<LittleEndian>());

	// send the acknowledgement websocket message
	let map = ObjectBuilder::new()
		.insert("op", 1)
		.insert_object("d", |object| object
			.insert("protocol", "udp")
			.insert_object("data", |object| object
				.insert("address", "")
				.insert("port", port_number)
				.insert("mode", "plain")
			)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	// discard websocket messages until we get the Ready
	loop {
		match try!(recv_message(&mut receiver)) {
			VoiceEvent::Ready { mode, secret_key } => {
				if secret_key.len() != 0 {
					debug!("Secret key: {:?}", secret_key);
				}
				if mode != "plain" {
					return Err(Error::Other("Voice mode in Ready was not 'plain'"))
				}
				break
			}
			VoiceEvent::Unknown(op, value) => debug!("Unknown message type: {}/{:?}", op, value),
			_ => {},
		}
	}

	// start a drain thread for the websocket receiver - without this, eventually
	// the OS buffer will fill and the connection will be dropped
	try!(::std::thread::Builder::new()
		.name("Discord Voice Drain Thread".into())
		.spawn(move || drain_thread(receiver)));

	// prepare buffers for later use
	let mut opus = try!(::utils::OpusEncoder::new());
	let mut audio_queue = ::std::collections::VecDeque::new();
	let mut audio_buffer = vec![0; 960];
	let mut packet = Vec::with_capacity(256);
	let mut sequence = 0;
	let mut timestamp = 0;

	let audio_duration = ::time::Duration::milliseconds(20);
	let keepalive_duration = ::time::Duration::milliseconds(interval as i64);
	let mut audio_timer = ::utils::Timer::new(audio_duration);
	let mut keepalive_timer = ::utils::Timer::new(keepalive_duration);

	// start the main loop
	info!("Voice connected to {}", endpoint);
	'outer: loop {
		::std::thread::sleep_ms(3);

		loop {
			match channel.try_recv() {
				Ok(Status::Push(source)) => {
					if audio_queue.len() == 0 {
						try!(set_speaking(&mut sender, true));
					}
					audio_queue.push_back(source)
				},
				Ok(Status::Clear) => audio_queue.clear(),
				Ok(Status::NoOp) => {},
				Err(mpsc::TryRecvError::Empty) => break,
				Err(mpsc::TryRecvError::Disconnected) => break 'outer,
			}
		}

		if keepalive_timer.check_and_add(keepalive_duration) {
			let map = ObjectBuilder::new()
				.insert("op", 3)
				.insert("d", serde_json::Value::Null)
				.unwrap();
			let json = try!(serde_json::to_string(&map));
			try!(sender.send_message(&WsMessage::text(json)));
		}

		if audio_timer.check_and_add(audio_duration) && audio_queue.len() > 0 {
			const HEADER_LEN: usize = 12;
			// prepare the packet header
			packet.clear();
			try!(packet.write_all(&[0x80, 0x78]));
			try!(packet.write_u16::<BigEndian>(sequence));
			try!(packet.write_u32::<BigEndian>(timestamp));
			try!(packet.write_u32::<BigEndian>(ssrc));
			let zeroes = packet.capacity() - HEADER_LEN;
			packet.extend(::std::iter::repeat(0).take(zeroes));

			// read the audio from the source
			let len = try!(next_frame(&mut audio_queue[0], &mut audio_buffer[..]));
			if len < audio_buffer.len() {
				// zero-fill the buffer and advance to the next audio source
				for value in &mut audio_buffer[len..] {
					*value = 0;
				}
				audio_queue.pop_front();
				if audio_queue.len() == 0 {
					try!(set_speaking(&mut sender, false));
				}
			}

			// encode the audio data and transmit it
			let len = opus.encode(&audio_buffer, &mut packet[HEADER_LEN..]).expect("failed encode");
			try!(udp.send_to(&packet[..len + HEADER_LEN], destination));

			sequence = sequence.wrapping_add(1);
			timestamp = timestamp.wrapping_add(960);
		}
	}

	// shutting down the sender like this will also terminate the drain thread
	try!(sender.get_mut().shutdown(::std::net::Shutdown::Both));
	info!("Voice disconnected");
	Ok(())
}

fn set_speaking(sender: &mut Sender<WebSocketStream>, speaking: bool) -> Result<()> {
	debug!("Speaking: {}", speaking);
	let map = ObjectBuilder::new()
		.insert("op", 5)
		.insert_object("d", |object| object
			.insert("speaking", speaking)
			.insert("delay", 0)
		)
		.unwrap();
	sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))).map_err(From::from)
}

fn next_frame(source: &mut AudioSource, buffer: &mut [i16]) -> Result<usize> {
	for (i, val) in buffer.iter_mut().enumerate() {
		*val = match source.read_i16::<LittleEndian>() {
			Ok(val) => val / 3, // TODO: add volume controls
			Err(::byteorder::Error::UnexpectedEOF) => return Ok(i),
			Err(::byteorder::Error::Io(e)) => return Err(From::from(e))
		};
	}
	Ok(buffer.len())
}

fn drain_thread(mut receiver: Receiver<WebSocketStream>) -> Receiver<WebSocketStream> {
	while let Ok(_) = recv_message(&mut receiver) {}
	receiver
}
<|endoftext|>


<commit_before>#![feature(unboxed_closures)]
#![feature(plugin)]
#![feature(box_syntax)]
#[macro_use]
extern crate log;
extern crate getopts;
extern crate rustc_serialize;
extern crate wtftw_core;
extern crate wtftw_xlib;

use std::env;
use getopts::Options;
use rustc_serialize::json;
use wtftw_core::config::Config;
use wtftw_core::window_manager::WindowManager;
use wtftw_core::window_system::*;
use wtftw_xlib::XlibWindowSystem;

pub fn parse_window_ids(ids: &str) -> Vec<(Window, u32)> {
    json::decode(ids).unwrap()
}

fn main() {
    // Parse command line arguments
    let args : Vec<String> = env::args().map(|x| x.to_string()).collect();

    let mut options = Options::new();
    options.optopt("r", "resume", "list of window IDs to capture in resume", "WINDOW");
    let matches = match options.parse(args.into_iter().skip(1).collect::<Vec<_>>()) {
        Ok(m)  => m,
        Err(f) => panic!(f.to_string())
    };

    // Create a default config.generaluration
    let mut config = Config::initialize();
    // Initialize window system. Use xlib here for now
    debug!("initialize window system");
    let window_system = XlibWindowSystem::new();
    // Create the actual window manager
    debug!("create window manager");
    let mut window_manager = WindowManager::new(&window_system, &config.general);

    // If available, compile the config.general file at ~/.wtftw/config.general.rs
    // and call the config.generalure method
    config.compile_and_call(&mut window_manager, &window_system);
    window_manager = WindowManager::new(&window_system, &config.general);

    // Output some initial information
    info!("WTFTW - Window Tiling For The Win");
    info!("Starting wtftw on {} screen(s)", window_system.get_screen_infos().len());

    // Output information about displays
    for (i, &Rectangle(x, y, w, h)) in window_system.get_screen_infos().iter().enumerate() {
        debug!("Display {}: {}x{} ({}, {})", i, w, h, x, y);
    }

    debug!("Size of keyhandlers after config.generaluration: {}", config.internal.key_handlers.len());

    for (command, _) in config.internal.key_handlers.iter() {
        window_system.grab_keys(vec!(command.clone()));
    }

    for (&command, _) in config.internal.mouse_handlers.iter() {
        window_system.grab_button(command);
    }

    let window_ids = if matches.opt_present("r") {
        debug!("trying to manage pre-existing windows");
        debug!("found {}", matches.opt_str("r").unwrap());
        parse_window_ids(&matches.opt_str("r").unwrap())
    } else {
        Vec::new()
    };

    for (window, workspace) in window_ids {
        debug!("re-inserting window {}", window);
        window_manager = window_manager.view(&window_system, workspace, &config.general)
            .manage(&window_system, window, &config.general);
    }

    // Enter the event loop and just listen for events
    while window_manager.running {
        let event = window_system.get_event();
        debug!("Got event {:?}", event);
        match event {
            WindowSystemEvent::ClientMessageEvent(_) => {
            },
            // The X11/Wayland configuration changed, so we need to readjust the
            // screen configurations.
            WindowSystemEvent::ConfigurationNotification(window) => {
                if window_system.get_root() == window {
                    debug!("screen config.generaluration changed. Rescreen");
                    window_manager = window_manager.rescreen(&window_system);
                }
            },
            // A window asked to be reconfigured (i.e. resized, border change, etc.)
            WindowSystemEvent::ConfigurationRequest(window, window_changes, mask) => {
                let floating = window_manager.workspaces.floating.iter().any(|(&x, _)| x == window) ||
                    !window_manager.workspaces.contains(window);
                window_system.configure_window(window, window_changes, mask, floating);
                window_manager = window_manager.windows(&window_system, &config.general, |x| x.clone());
            },
            // A new window was created, so we need to manage
            // it unless it is already managed by us.
            WindowSystemEvent::WindowCreated(window) => {
                if window_manager.is_window_managed(window) || window_system.overrides_redirect(window) {
                    continue;
                }

                window_manager = window_manager.manage(&window_system, window, &config.general)
                                               .windows(&window_system, &config.general,
                                                        |x| (config.internal.manage_hook)(x.clone(),
                                                        &window_system, window));
            },
            WindowSystemEvent::WindowUnmapped(window, synthetic) => {
                if synthetic && window_manager.is_window_managed(window) {
                    window_manager = if synthetic || !window_manager.is_waiting_unmap(window) {
                        window_manager.unmanage(&window_system, window, &config.general)
                    } else {
                        window_manager.update_unmap(window)
                    }
                }
            },
            WindowSystemEvent::WindowDestroyed(window) => {
                if window_manager.is_window_managed(window) {
                    window_manager = window_manager.unmanage(&window_system, window, &config.general)
                        .remove_from_unmap(window);
                }
            },
            // The mouse pointer entered a window's region. If focus following
            // is enabled, we need to set focus to it.
            WindowSystemEvent::Enter(window) => {
                if config.general.focus_follows_mouse && window_manager.is_window_managed(window) {
                    debug!("enter event on {}", window_system.get_window_name(window));
                    window_manager = window_manager.focus(window, &window_system, &config.general);
                }
            },
            WindowSystemEvent::ButtonPressed(window, subwindow, button, _, _) => {
                let is_root = window_system.get_root() == window;
                let is_sub_root = window_system.get_root() == subwindow || subwindow == 0;
                let act = config.internal.mouse_handlers.get(&button);

                match act {
                    Some(ref action) => {
                        // If it's a root window, then it's an event we grabbed
                        if is_root && !is_sub_root {
                            let local_window_manager = window_manager.clone();
                            window_manager = action(local_window_manager, &window_system,
                                                          &config.general, subwindow);
                        }
                    }
                    None => {
                        // Otherwise just clock to focus
                        if !is_root {
                            window_manager = window_manager.focus(window, &window_system, &config.general);
                        }
                    }
                }
            },
            WindowSystemEvent::ButtonReleased => {
                // If we were dragging, release the pointer and
                // reset the dragging closure
                if let Some(_) = window_manager.dragging {
                    window_system.ungrab_pointer();
                    window_manager.dragging = None;
                }
            }
            WindowSystemEvent::KeyPressed(_, key) => {
                if config.internal.key_handlers.contains_key(&key) {
                    let local_window_manager = window_manager.clone();
                    window_manager = config.internal.key_handlers[&key](local_window_manager,
                        &window_system, &config.general);
                }
            },
            WindowSystemEvent::MouseMotion(x, y) => {
                let local_window_manager = window_manager.clone();
                if let Some(drag) = window_manager.dragging {
                    debug!("dragging: {} {}", x, y);
                    window_manager = drag(x, y, local_window_manager, &window_system);
                    window_system.remove_motion_events();
                }
            },
            _ => ()
        };
        debug!("processed {:?}", event);

        if let Some(ref mut loghook) = config.internal.loghook {
            println!("calling loghook!");
            debug!("calling loghook");
            loghook(window_manager.clone(), &window_system);
        } else {
            println!("there is no loghook!");
            debug!("no loghook!");
        }
    }
}
<commit_msg>wtftw: no need to use map<commit_after>#![feature(unboxed_closures)]
#![feature(plugin)]
#![feature(box_syntax)]
#[macro_use]
extern crate log;
extern crate getopts;
extern crate rustc_serialize;
extern crate wtftw_core;
extern crate wtftw_xlib;

use std::env;
use getopts::Options;
use rustc_serialize::json;
use wtftw_core::config::Config;
use wtftw_core::window_manager::WindowManager;
use wtftw_core::window_system::*;
use wtftw_xlib::XlibWindowSystem;

pub fn parse_window_ids(ids: &str) -> Vec<(Window, u32)> {
    json::decode(ids).unwrap()
}

fn main() {
    // Parse command line arguments
    let args : Vec<String> = env::args().collect();

    let mut options = Options::new();
    options.optopt("r", "resume", "list of window IDs to capture in resume", "WINDOW");
    let matches = match options.parse(args.into_iter().skip(1).collect::<Vec<_>>()) {
        Ok(m)  => m,
        Err(f) => panic!(f.to_string())
    };

    // Create a default config.generaluration
    let mut config = Config::initialize();
    // Initialize window system. Use xlib here for now
    debug!("initialize window system");
    let window_system = XlibWindowSystem::new();
    // Create the actual window manager
    debug!("create window manager");
    let mut window_manager = WindowManager::new(&window_system, &config.general);

    // If available, compile the config.general file at ~/.wtftw/config.general.rs
    // and call the config.generalure method
    config.compile_and_call(&mut window_manager, &window_system);
    window_manager = WindowManager::new(&window_system, &config.general);

    // Output some initial information
    info!("WTFTW - Window Tiling For The Win");
    info!("Starting wtftw on {} screen(s)", window_system.get_screen_infos().len());

    // Output information about displays
    for (i, &Rectangle(x, y, w, h)) in window_system.get_screen_infos().iter().enumerate() {
        debug!("Display {}: {}x{} ({}, {})", i, w, h, x, y);
    }

    debug!("Size of keyhandlers after config.generaluration: {}", config.internal.key_handlers.len());

    for (command, _) in config.internal.key_handlers.iter() {
        window_system.grab_keys(vec!(command.clone()));
    }

    for (&command, _) in config.internal.mouse_handlers.iter() {
        window_system.grab_button(command);
    }

    let window_ids = if matches.opt_present("r") {
        debug!("trying to manage pre-existing windows");
        debug!("found {}", matches.opt_str("r").unwrap());
        parse_window_ids(&matches.opt_str("r").unwrap())
    } else {
        Vec::new()
    };

    for (window, workspace) in window_ids {
        debug!("re-inserting window {}", window);
        window_manager = window_manager.view(&window_system, workspace, &config.general)
            .manage(&window_system, window, &config.general);
    }

    // Enter the event loop and just listen for events
    while window_manager.running {
        let event = window_system.get_event();
        debug!("Got event {:?}", event);
        match event {
            WindowSystemEvent::ClientMessageEvent(_) => {
            },
            // The X11/Wayland configuration changed, so we need to readjust the
            // screen configurations.
            WindowSystemEvent::ConfigurationNotification(window) => {
                if window_system.get_root() == window {
                    debug!("screen config.generaluration changed. Rescreen");
                    window_manager = window_manager.rescreen(&window_system);
                }
            },
            // A window asked to be reconfigured (i.e. resized, border change, etc.)
            WindowSystemEvent::ConfigurationRequest(window, window_changes, mask) => {
                let floating = window_manager.workspaces.floating.iter().any(|(&x, _)| x == window) ||
                    !window_manager.workspaces.contains(window);
                window_system.configure_window(window, window_changes, mask, floating);
                window_manager = window_manager.windows(&window_system, &config.general, |x| x.clone());
            },
            // A new window was created, so we need to manage
            // it unless it is already managed by us.
            WindowSystemEvent::WindowCreated(window) => {
                if window_manager.is_window_managed(window) || window_system.overrides_redirect(window) {
                    continue;
                }

                window_manager = window_manager.manage(&window_system, window, &config.general)
                                               .windows(&window_system, &config.general,
                                                        |x| (config.internal.manage_hook)(x.clone(),
                                                        &window_system, window));
            },
            WindowSystemEvent::WindowUnmapped(window, synthetic) => {
                if synthetic && window_manager.is_window_managed(window) {
                    window_manager = if synthetic || !window_manager.is_waiting_unmap(window) {
                        window_manager.unmanage(&window_system, window, &config.general)
                    } else {
                        window_manager.update_unmap(window)
                    }
                }
            },
            WindowSystemEvent::WindowDestroyed(window) => {
                if window_manager.is_window_managed(window) {
                    window_manager = window_manager.unmanage(&window_system, window, &config.general)
                        .remove_from_unmap(window);
                }
            },
            // The mouse pointer entered a window's region. If focus following
            // is enabled, we need to set focus to it.
            WindowSystemEvent::Enter(window) => {
                if config.general.focus_follows_mouse && window_manager.is_window_managed(window) {
                    debug!("enter event on {}", window_system.get_window_name(window));
                    window_manager = window_manager.focus(window, &window_system, &config.general);
                }
            },
            WindowSystemEvent::ButtonPressed(window, subwindow, button, _, _) => {
                let is_root = window_system.get_root() == window;
                let is_sub_root = window_system.get_root() == subwindow || subwindow == 0;
                let act = config.internal.mouse_handlers.get(&button);

                match act {
                    Some(ref action) => {
                        // If it's a root window, then it's an event we grabbed
                        if is_root && !is_sub_root {
                            let local_window_manager = window_manager.clone();
                            window_manager = action(local_window_manager, &window_system,
                                                          &config.general, subwindow);
                        }
                    }
                    None => {
                        // Otherwise just clock to focus
                        if !is_root {
                            window_manager = window_manager.focus(window, &window_system, &config.general);
                        }
                    }
                }
            },
            WindowSystemEvent::ButtonReleased => {
                // If we were dragging, release the pointer and
                // reset the dragging closure
                if let Some(_) = window_manager.dragging {
                    window_system.ungrab_pointer();
                    window_manager.dragging = None;
                }
            }
            WindowSystemEvent::KeyPressed(_, key) => {
                if config.internal.key_handlers.contains_key(&key) {
                    let local_window_manager = window_manager.clone();
                    window_manager = config.internal.key_handlers[&key](local_window_manager,
                        &window_system, &config.general);
                }
            },
            WindowSystemEvent::MouseMotion(x, y) => {
                let local_window_manager = window_manager.clone();
                if let Some(drag) = window_manager.dragging {
                    debug!("dragging: {} {}", x, y);
                    window_manager = drag(x, y, local_window_manager, &window_system);
                    window_system.remove_motion_events();
                }
            },
            _ => ()
        };
        debug!("processed {:?}", event);

        if let Some(ref mut loghook) = config.internal.loghook {
            println!("calling loghook!");
            debug!("calling loghook");
            loghook(window_manager.clone(), &window_system);
        } else {
            println!("there is no loghook!");
            debug!("no loghook!");
        }
    }
}
<|endoftext|>


<commit_before>//! Extracted from the unicode-xid exhaustive test all_valid_chars_do_not_panic_for_is_xid_continue

use unicode_xid::UnicodeXID;

/// A `char` in Rust is a Unicode Scalar Value
///
/// See: http://www.unicode.org/glossary/#unicode_scalar_value
fn all_valid_chars() -> impl Iterator<Item = char> {
    (0u32..=0xD7FF).chain(0xE000u32..=0x10FFFF).map(|u| {
        core::convert::TryFrom::try_from(u)
            .expect("The selected range should be infallible if the docs match impl")
    })
}

fn main() {
    // Take only the first few chars because we don't want to wait all day
    for c in all_valid_chars().take(2_000) {
        let _ = UnicodeXID::is_xid_continue(c);
    }
}
<commit_msg>make unicode benchmark not take 20s<commit_after>//! Extracted from the unicode-xid exhaustive test all_valid_chars_do_not_panic_for_is_xid_continue

use unicode_xid::UnicodeXID;

/// A `char` in Rust is a Unicode Scalar Value
///
/// See: http://www.unicode.org/glossary/#unicode_scalar_value
fn all_valid_chars() -> impl Iterator<Item = char> {
    (0u32..=0xD7FF).chain(0xE000u32..=0x10FFFF).map(|u| {
        core::convert::TryFrom::try_from(u)
            .expect("The selected range should be infallible if the docs match impl")
    })
}

fn main() {
    // Take only the first few chars because we don't want to wait all day
    for c in all_valid_chars().take(1_500) {
        let _ = UnicodeXID::is_xid_continue(c);
    }
}
<|endoftext|>