<commit_before>use cmp::{Eq, Ord};
use num::Num;

use ncast::*;
use vector::*;

/**
 * Common Functions for all numeric types
 */
pub trait Numeric {
    pure fn min(y: &self) -> self;
    pure fn max(y: &self) -> self;
    pure fn clamp(minv: &self, maxv: &self) -> self;
}

#[inline(always)] pub pure fn min<T:Numeric>(x: &T, y: &T) -> T { x.min(y) }
#[inline(always)] pub pure fn max<T:Numeric>(x: &T, y: &T) -> T { x.max(y) }
#[inline(always)] pub pure fn clamp<T:Numeric>(x: &T, minv: &T, maxv: &T) -> T { x.clamp(minv, maxv) }

pub impl u8: Numeric {
    #[inline(always)] pure fn min(y: &u8) -> u8 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u8) -> u8 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u8, maxv: &u8) -> u8 { min(&max(&self, minv), maxv) }
}

pub impl u16: Numeric {
    #[inline(always)] pure fn min(y: &u16) -> u16 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u16) -> u16 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u16, maxv: &u16) -> u16 { min(&max(&self, minv), maxv) }
}

pub impl u32: Numeric {
    #[inline(always)] pure fn min(y: &u32) -> u32 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u32) -> u32 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u32, maxv: &u32) -> u32 { min(&max(&self, minv), maxv) }
}

pub impl u64: Numeric {
    #[inline(always)] pure fn min(y: &u64) -> u64 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u64) -> u64 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u64, maxv: &u64) -> u64 { min(&max(&self, minv), maxv) }
}

pub impl uint: Numeric {
    #[inline(always)] pure fn min(y: &uint) -> uint { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &uint) -> uint { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &uint, maxv: &uint) -> uint { min(&max(&self, minv), maxv) }
}

pub impl i8: Numeric {
    #[inline(always)] pure fn min(y: &i8) -> i8 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i8) -> i8 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i8, maxv: &i8) -> i8 { min(&max(&self, minv), maxv) }
}

pub impl i16: Numeric {
    #[inline(always)] pure fn min(y: &i16) -> i16 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i16) -> i16 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i16, maxv: &i16) -> i16 { min(&max(&self, minv), maxv) }
}

pub impl i32: Numeric {
    #[inline(always)] pure fn min(y: &i32) -> i32 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i32) -> i32 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i32, maxv: &i32) -> i32 { min(&max(&self, minv), maxv) }
}

pub impl i64: Numeric {
    #[inline(always)] pure fn min(y: &i64) -> i64 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i64) -> i64 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i64, maxv: &i64) -> i64 { min(&max(&self, minv), maxv) }
}

pub impl int: Numeric {
    #[inline(always)] pure fn min(y: &int) -> int { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &int) -> int { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &int, maxv: &int) -> int { min(&max(&self, minv), maxv) }
}

pub impl f32: Numeric {
    #[inline(always)] pure fn min(y: &f32) -> f32 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &f32) -> f32 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &f32, maxv: &f32) -> f32 { min(&max(&self, minv), maxv) }
}

pub impl f64: Numeric {
    #[inline(always)] pure fn min(y: &f64) -> f64 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &f64) -> f64 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &f64, maxv: &f64) -> f64 { min(&max(&self, minv), maxv) }
}

pub impl float: Numeric {
    #[inline(always)] pure fn min(y: &float) -> float { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &float) -> float { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &float, maxv: &float) -> float { min(&max(&self, minv), maxv) }
}

/**
 * Common Functions for signed numeric types
 */
pub trait Signed {
    pure fn abs() -> self;
    pure fn sign() -> self;
    pure fn mod_(y: &self) -> self;
}

#[inline(always)] pub pure fn abs<T:Signed>(x: &T) -> T { x.abs() }
#[inline(always)] pub pure fn sign<T:Signed>(x: &T) -> T { x.sign() }
#[inline(always)] pub pure fn mod_<T:Signed>(x: &T, y: &T) -> T { x.mod_(y) }

pub impl i8: Signed {
    #[inline(always)] pure fn abs() -> i8 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i8 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i8) -> i8 { self % *y }
}

pub impl i16: Signed {
    #[inline(always)] pure fn abs() -> i16 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i16 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i16) -> i16 { self % *y }
}

pub impl i32: Signed {
    #[inline(always)] pure fn abs() -> i32 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i32 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i32) -> i32 { self % *y }
}

pub impl i64: Signed {
    #[inline(always)] pure fn abs() -> i64 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i64 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i64) -> i64 { self % *y }
}

pub impl int: Signed {
    #[inline(always)] pure fn abs() -> int { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> int { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &int) -> int { self % *y }
}

pub impl f32: Signed {
    #[inline(always)] pure fn abs() -> f32 { if self >= 0f32 { self } else {-self } }
    #[inline(always)] pure fn sign() -> f32 { if self > 0f32 { 1f32 } else if self == 0f32 { 0f32 } else { -1f32 } }
    #[inline(always)] pure fn mod_(y: &f32) -> f32 { self % *y }
}

pub impl f64: Signed {
    #[inline(always)] pure fn abs() -> f64 { if self >= 0f64 { self } else {-self } }
    #[inline(always)] pure fn sign() -> f64 { if self > 0f64 { 1f64 } else if self == 0f64 { 0f64 } else { -1f64 } }
    #[inline(always)] pure fn mod_(y: &f64) -> f64 { self % *y }
}

pub impl float: Signed {
    #[inline(always)] pure fn abs() -> float { if self >= 0f { self } else {-self } }
    #[inline(always)] pure fn sign() -> float { if self > 0f { 1f } else if self == 0f { 0f } else { -1f } }
    #[inline(always)] pure fn mod_(y: &float) -> float { self % *y }
}

/**
 * Common Functions for floating point types
 */

pub trait Float<B> {
    pure fn floor() -> self;
    pure fn trunc() -> self;
    pure fn round() -> self;
    // pure fn roundEven() -> self;
    pure fn ceil() -> self;
    // pure fn fract() -> self;
    pure fn mix(y: &self, a: &self) -> self;
    pure fn mixb(y: &self, a: &B) -> self;
}

#[inline(always)] pub pure fn floor<T:Float<B>, B>(x: T) -> T { x.floor() }
#[inline(always)] pub pure fn trunc<T:Float<B>, B>(x: T) -> T { x.trunc() }
#[inline(always)] pub pure fn round<T:Float<B>, B>(x: T) -> T { x.round() }
// #[inline(always)] pub pure fn roundEven<T:Float<B>, B>(x: T) -> T { x.roundEven() }
#[inline(always)] pub pure fn ceil<T:Float<B>, B>(x: T) -> T { x.ceil() }
// #[inline(always)] pub pure fn fract<T:Float<B>, B>(x: T) -> T { x.fract() }
#[inline(always)] pub pure fn mix<T:Float<B>, B>(x: &T, y: &T, a: &T) -> T { x.mix(y, a) }
#[inline(always)] pub pure fn mixb<T:Float<B>, B>(x: &T, y: &T, a: &B) -> T { x.mixb(y, a) }

pub impl f32: Float<bool> {
    #[inline(always)] pure fn floor() -> f32 { f32::floor(self) }
    #[inline(always)] pure fn trunc() -> f32 { f32::trunc(self) }
    #[inline(always)] pure fn round() -> f32 { f32::round(self) }
    // #[inline(always)] pure fn roundEven() -> f32 {}
    #[inline(always)] pure fn ceil() -> f32 { f32::ceil(self) }
    // #[inline(always)] pure fn fract() -> f32 {}
    #[inline(always)] pure fn mix(y: &f32, a: &f32) -> f32 { self * (1f32 - (*a)) + y * (*a) }
    #[inline(always)] pure fn mixb(y: &f32, a: &bool) -> f32 { if *a { *y } else { self } }
}

pub impl f64: Float<bool> {
    #[inline(always)] pure fn floor() -> f64 { f64::floor(self) }
    #[inline(always)] pure fn trunc() -> f64 { f64::trunc(self) }
    #[inline(always)] pure fn round() -> f64 { f64::round(self) }
    // #[inline(always)] pure fn roundEven() -> f64 {}
    #[inline(always)] pure fn ceil() -> f64 { f64::ceil(self) }
    // #[inline(always)] pure fn fract() -> f64 {}
    #[inline(always)] pure fn mix(y: &f64, a: &f64) -> f64 { self * (1f64 - (*a)) + y * (*a) }
    #[inline(always)] pure fn mixb(y: &f64, a: &bool) -> f64 { if *a { *y } else { self } }
}

pub impl float: Float<bool> {
    #[inline(always)] pure fn floor() -> float { cast(float::floor(cast(self))) }
    #[inline(always)] pure fn trunc() -> float { cast(float::trunc(cast(self))) }
    #[inline(always)] pure fn round() -> float { cast(float::round(cast(self))) }
    // #[inline(always)] pure fn roundEven() -> float {}
    #[inline(always)] pure fn ceil() -> float { cast(float::ceil(cast(self))) }
    // #[inline(always)] pure fn fract() -> float {}
    #[inline(always)] pure fn mix(y: &float, a: &float) -> float { self * (1f - (*a)) + y * (*a) }
    #[inline(always)] pure fn mixb(y: &float, a: &bool) -> float { if *a { *y } else { self } }
}<commit_msg>Rename Numeric type to Extent<commit_after>use cmp::{Eq, Ord};
use num::Num;

use ncast::*;
use vector::*;

/**
 * Common Functions for all numeric types
 */
pub trait Extent {
    pure fn min(y: &self) -> self;
    pure fn max(y: &self) -> self;
    pure fn clamp(minv: &self, maxv: &self) -> self;
}

#[inline(always)] pub pure fn min<T:Extent>(x: &T, y: &T) -> T { x.min(y) }
#[inline(always)] pub pure fn max<T:Extent>(x: &T, y: &T) -> T { x.max(y) }
#[inline(always)] pub pure fn clamp<T:Extent>(x: &T, minv: &T, maxv: &T) -> T { x.clamp(minv, maxv) }

pub impl u8: Extent {
    #[inline(always)] pure fn min(y: &u8) -> u8 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u8) -> u8 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u8, maxv: &u8) -> u8 { min(&max(&self, minv), maxv) }
}

pub impl u16: Extent {
    #[inline(always)] pure fn min(y: &u16) -> u16 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u16) -> u16 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u16, maxv: &u16) -> u16 { min(&max(&self, minv), maxv) }
}

pub impl u32: Extent {
    #[inline(always)] pure fn min(y: &u32) -> u32 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u32) -> u32 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u32, maxv: &u32) -> u32 { min(&max(&self, minv), maxv) }
}

pub impl u64: Extent {
    #[inline(always)] pure fn min(y: &u64) -> u64 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &u64) -> u64 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &u64, maxv: &u64) -> u64 { min(&max(&self, minv), maxv) }
}

pub impl uint: Extent {
    #[inline(always)] pure fn min(y: &uint) -> uint { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &uint) -> uint { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &uint, maxv: &uint) -> uint { min(&max(&self, minv), maxv) }
}

pub impl i8: Extent {
    #[inline(always)] pure fn min(y: &i8) -> i8 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i8) -> i8 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i8, maxv: &i8) -> i8 { min(&max(&self, minv), maxv) }
}

pub impl i16: Extent {
    #[inline(always)] pure fn min(y: &i16) -> i16 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i16) -> i16 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i16, maxv: &i16) -> i16 { min(&max(&self, minv), maxv) }
}

pub impl i32: Extent {
    #[inline(always)] pure fn min(y: &i32) -> i32 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i32) -> i32 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i32, maxv: &i32) -> i32 { min(&max(&self, minv), maxv) }
}

pub impl i64: Extent {
    #[inline(always)] pure fn min(y: &i64) -> i64 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &i64) -> i64 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &i64, maxv: &i64) -> i64 { min(&max(&self, minv), maxv) }
}

pub impl int: Extent {
    #[inline(always)] pure fn min(y: &int) -> int { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &int) -> int { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &int, maxv: &int) -> int { min(&max(&self, minv), maxv) }
}

pub impl f32: Extent {
    #[inline(always)] pure fn min(y: &f32) -> f32 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &f32) -> f32 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &f32, maxv: &f32) -> f32 { min(&max(&self, minv), maxv) }
}

pub impl f64: Extent {
    #[inline(always)] pure fn min(y: &f64) -> f64 { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &f64) -> f64 { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &f64, maxv: &f64) -> f64 { min(&max(&self, minv), maxv) }
}

pub impl float: Extent {
    #[inline(always)] pure fn min(y: &float) -> float { if self < *y { self } else { *y } }
    #[inline(always)] pure fn max(y: &float) -> float { if self > *y { self } else { *y } }
    #[inline(always)] pure fn clamp(minv: &float, maxv: &float) -> float { min(&max(&self, minv), maxv) }
}

/**
 * Common Functions for signed numeric types
 */
pub trait Signed {
    pure fn abs() -> self;
    pure fn sign() -> self;
    pure fn mod_(y: &self) -> self;
}

#[inline(always)] pub pure fn abs<T:Signed>(x: &T) -> T { x.abs() }
#[inline(always)] pub pure fn sign<T:Signed>(x: &T) -> T { x.sign() }
#[inline(always)] pub pure fn mod_<T:Signed>(x: &T, y: &T) -> T { x.mod_(y) }

pub impl i8: Signed {
    #[inline(always)] pure fn abs() -> i8 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i8 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i8) -> i8 { self % *y }
}

pub impl i16: Signed {
    #[inline(always)] pure fn abs() -> i16 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i16 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i16) -> i16 { self % *y }
}

pub impl i32: Signed {
    #[inline(always)] pure fn abs() -> i32 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i32 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i32) -> i32 { self % *y }
}

pub impl i64: Signed {
    #[inline(always)] pure fn abs() -> i64 { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> i64 { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &i64) -> i64 { self % *y }
}

pub impl int: Signed {
    #[inline(always)] pure fn abs() -> int { if self >= 0 { self } else {-self } }
    #[inline(always)] pure fn sign() -> int { if self > 0 { 1 } else if self == 0 { 0 } else { -1 } }
    #[inline(always)] pure fn mod_(y: &int) -> int { self % *y }
}

pub impl f32: Signed {
    #[inline(always)] pure fn abs() -> f32 { if self >= 0f32 { self } else {-self } }
    #[inline(always)] pure fn sign() -> f32 { if self > 0f32 { 1f32 } else if self == 0f32 { 0f32 } else { -1f32 } }
    #[inline(always)] pure fn mod_(y: &f32) -> f32 { self % *y }
}

pub impl f64: Signed {
    #[inline(always)] pure fn abs() -> f64 { if self >= 0f64 { self } else {-self } }
    #[inline(always)] pure fn sign() -> f64 { if self > 0f64 { 1f64 } else if self == 0f64 { 0f64 } else { -1f64 } }
    #[inline(always)] pure fn mod_(y: &f64) -> f64 { self % *y }
}

pub impl float: Signed {
    #[inline(always)] pure fn abs() -> float { if self >= 0f { self } else {-self } }
    #[inline(always)] pure fn sign() -> float { if self > 0f { 1f } else if self == 0f { 0f } else { -1f } }
    #[inline(always)] pure fn mod_(y: &float) -> float { self % *y }
}

/**
 * Common Functions for floating point types
 */

pub trait Float<B> {
    pure fn floor() -> self;
    pure fn trunc() -> self;
    pure fn round() -> self;
    // pure fn roundEven() -> self;
    pure fn ceil() -> self;
    // pure fn fract() -> self;
    pure fn mix(y: &self, a: &self) -> self;
    pure fn mixb(y: &self, a: &B) -> self;
}

#[inline(always)] pub pure fn floor<T:Float<B>, B>(x: T) -> T { x.floor() }
#[inline(always)] pub pure fn trunc<T:Float<B>, B>(x: T) -> T { x.trunc() }
#[inline(always)] pub pure fn round<T:Float<B>, B>(x: T) -> T { x.round() }
// #[inline(always)] pub pure fn roundEven<T:Float<B>, B>(x: T) -> T { x.roundEven() }
#[inline(always)] pub pure fn ceil<T:Float<B>, B>(x: T) -> T { x.ceil() }
// #[inline(always)] pub pure fn fract<T:Float<B>, B>(x: T) -> T { x.fract() }
#[inline(always)] pub pure fn mix<T:Float<B>, B>(x: &T, y: &T, a: &T) -> T { x.mix(y, a) }
#[inline(always)] pub pure fn mixb<T:Float<B>, B>(x: &T, y: &T, a: &B) -> T { x.mixb(y, a) }

pub impl f32: Float<bool> {
    #[inline(always)] pure fn floor() -> f32 { f32::floor(self) }
    #[inline(always)] pure fn trunc() -> f32 { f32::trunc(self) }
    #[inline(always)] pure fn round() -> f32 { f32::round(self) }
    // #[inline(always)] pure fn roundEven() -> f32 {}
    #[inline(always)] pure fn ceil() -> f32 { f32::ceil(self) }
    // #[inline(always)] pure fn fract() -> f32 {}
    #[inline(always)] pure fn mix(y: &f32, a: &f32) -> f32 { self * (1f32 - (*a)) + y * (*a) }
    #[inline(always)] pure fn mixb(y: &f32, a: &bool) -> f32 { if *a { *y } else { self } }
}

pub impl f64: Float<bool> {
    #[inline(always)] pure fn floor() -> f64 { f64::floor(self) }
    #[inline(always)] pure fn trunc() -> f64 { f64::trunc(self) }
    #[inline(always)] pure fn round() -> f64 { f64::round(self) }
    // #[inline(always)] pure fn roundEven() -> f64 {}
    #[inline(always)] pure fn ceil() -> f64 { f64::ceil(self) }
    // #[inline(always)] pure fn fract() -> f64 {}
    #[inline(always)] pure fn mix(y: &f64, a: &f64) -> f64 { self * (1f64 - (*a)) + y * (*a) }
    #[inline(always)] pure fn mixb(y: &f64, a: &bool) -> f64 { if *a { *y } else { self } }
}

pub impl float: Float<bool> {
    #[inline(always)] pure fn floor() -> float { cast(float::floor(cast(self))) }
    #[inline(always)] pure fn trunc() -> float { cast(float::trunc(cast(self))) }
    #[inline(always)] pure fn round() -> float { cast(float::round(cast(self))) }
    // #[inline(always)] pure fn roundEven() -> float {}
    #[inline(always)] pure fn ceil() -> float { cast(float::ceil(cast(self))) }
    // #[inline(always)] pure fn fract() -> float {}
    #[inline(always)] pure fn mix(y: &float, a: &float) -> float { self * (1f - (*a)) + y * (*a) }
    #[inline(always)] pure fn mixb(y: &float, a: &bool) -> float { if *a { *y } else { self } }
}<|endoftext|>


<commit_before>#![warn(missing_docs)]
#![feature(slice_patterns)]

//! rebind
//! =========
//!
//! A library for binding input keys to actions, and modifying mouse behaviour. Keys can be
//! bound to actions, and then translated during runtime. `Keys` are mapped to `Actions` using
//! a `HashMap`, so lookup time is constant.

extern crate input;
extern crate itertools;
extern crate rustc_serialize;
extern crate viewport;
extern crate window;

mod builder;

#[cfg(test)]
mod test;

use input::{Input, Button, Motion};
use itertools::Itertools;
use std::cmp::{PartialEq, Eq, Ord};
use std::collections::HashMap;
use std::default::Default;
use std::fmt::{Debug, Formatter, Result};
use std::hash::Hash;
use viewport::Viewport;
use window::Size;

pub use builder::RebindBuilder;

/// Represents a logical action to be bound to a particular button press, e.g.
/// jump, attack, or move forward. Needs to be hashable, as it is used as a
/// lookup key when rebinding an action to a different button.
pub trait Action: Copy + Eq + Hash + Ord { }

/// A translated action.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Translated<A: Action> {
    /// A keypress event which was bound to an action
    Press(A),

    /// A key release event which was bound to an action
    Release(A),

    /// A translated mouse motion. The logical origin of a translated MouseCursor event
    /// is in the top left corner of the window, and the logical scroll is non-natural.
    /// Relative events are unchanged for now.
    Move(Motion)
}

/// A three-element tuple of Option<Button>. For simplicity, a maximum number of 3
/// buttons can be bound to each action, and this is exposed through the `InputRebind`
/// struct.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ButtonTuple(pub Option<Button>, pub Option<Button>, pub Option<Button>);

impl ButtonTuple {
    /// Creates a new tuple with no buttons in it (equivalent to `Default::default()`).
    pub fn new() -> Self { Default::default() }

    /// Check if the button is in the tuple.
    pub fn contains(&self, button: Button) -> bool {
        let sbtn = Some(button);
        self.0 == sbtn || self.1 == sbtn || self.2 == sbtn
    }

    /// Insert a button into the tuple if there is room, searching from left to right.
    /// If the button is inserted, returns true. Otherwise, if the button is not inserted,
    /// this function returns false.
    pub fn insert_inplace(&mut self, button: Button) -> bool {
        let sbtn = Some(button);
        match self {
            &mut ButtonTuple(a, b, c) if a.is_none() => {*self = ButtonTuple(sbtn, b, c); true},
            &mut ButtonTuple(a, b, c) if b.is_none() => {*self = ButtonTuple(a, sbtn, c); true},
            &mut ButtonTuple(a, b, c) if c.is_none() => {*self = ButtonTuple(a, b, sbtn); true}
            _ => false
        }
    }

    /// Returns an iterator over this tuple.
    pub fn iter(&self) -> ButtonTupleIter { (*self).into_iter() }
}

impl Default for ButtonTuple {
    /// Creates a new tuple with no buttons in it.
    fn default() -> Self { ButtonTuple(None, None, None) }
}

impl IntoIterator for ButtonTuple {
    type Item = Option<Button>;
    type IntoIter = ButtonTupleIter;

    fn into_iter(self) -> Self::IntoIter {
        ButtonTupleIter {
            button_tuple: self,
            i: 0
        }
    }
}

/// An iterator over a ButtonTuple.
pub struct ButtonTupleIter {
    button_tuple: ButtonTuple,
    i: usize
}

impl Iterator for ButtonTupleIter {
    type Item = Option<Button>;

    fn next(&mut self) -> Option<Self::Item> {
        let i = self.i;
        self.i += 1;
        match i {
            0 => Some(self.button_tuple.0),
            1 => Some(self.button_tuple.1),
            2 => Some(self.button_tuple.2),
            _ => None
        }
    }
}

/// An object which translates piston::input::Input events into input_map::Translated<A> events
#[derive(Clone, Debug, PartialEq)]
pub struct InputTranslator<A: Action> {
    keymap: HashMap<Button, A>,
    mouse_translator: MouseTranslator
}

impl<A: Action> InputTranslator<A> {
    /// Creates an empty InputTranslator.
    pub fn new(size: Size) -> Self {
        InputTranslator {
            keymap: HashMap::new(),
            mouse_translator: MouseTranslator::new(size)
        }
    }

    /// Translate an Input into a Translated<A> event. Returns `None` if there is no
    /// action associated with the `Input` variant.
    pub fn translate(&self, input: &Input) -> Option<Translated<A>> {
        macro_rules! translate_button(($but_state:ident, $but_var:ident) => (
            match self.keymap.get(&$but_var).cloned() {
                Some(act) => Some(Translated::$but_state(act)),
                None => None
            });
        );

        match input {
            &Input::Press(button) => translate_button!(Press, button),
            &Input::Release(button) => translate_button!(Release, button),
            &Input::Move(motion) =>
                Some(Translated::Move(self.mouse_translator.translate(motion))),
            _ => None
        }
    }

    /// Re-set the mouse bounds size used for calculating mouse events
    pub fn set_size(&mut self, size: Size) {
        self.mouse_translator.data.viewport_size = size
    }

    /// Re-set the mouse bounds size from a viewport
    pub fn set_size_from_viewport(&mut self, vp: Viewport) {
        self.set_size(Size::from(vp.draw_size));
    }

    /// Convert the `InputTranslator` into an `InputRebind`. Consumes the
    /// `InputTranslator`.
    pub fn into_rebind(self) -> InputRebind<A> { self.into() }
}

#[derive(Clone)]
struct MouseTranslationData {
    x_axis_motion_inverted: bool,
    y_axis_motion_inverted: bool,
    x_axis_scroll_inverted: bool,
    y_axis_scroll_inverted: bool,
    _sensitivity: f64,
    viewport_size: Size
}

impl MouseTranslationData {
    fn new(size: Size) -> Self {
        MouseTranslationData {
            x_axis_motion_inverted: false,
            y_axis_motion_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            _sensitivity: 0.0,
            viewport_size: size
        }
    }
}

impl Debug for MouseTranslationData {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}, {}, {}, {}, {}, ({}, {})",
               self.x_axis_motion_inverted,
               self.y_axis_motion_inverted,
               self.x_axis_scroll_inverted,
               self.y_axis_scroll_inverted,
               self._sensitivity,
               self.viewport_size.width,
               self.viewport_size.height)
    }
}

impl PartialEq for MouseTranslationData {
    fn eq(&self, other: &Self) -> bool {
        self.x_axis_motion_inverted == other.x_axis_motion_inverted &&
        self.y_axis_motion_inverted == other.y_axis_motion_inverted &&
        self.x_axis_scroll_inverted == other.x_axis_scroll_inverted &&
        self.y_axis_scroll_inverted == other.y_axis_scroll_inverted &&
        self._sensitivity == other._sensitivity &&
        self.viewport_size.width    == other.viewport_size.width &&
        self.viewport_size.height   == other.viewport_size.height
    }
}

#[derive(Clone, Debug, PartialEq)]
struct MouseTranslator {
    data: MouseTranslationData
}

impl MouseTranslator {
    fn new(size: Size) -> Self {
        MouseTranslator {
            data: MouseTranslationData::new(size)
        }
    }

    fn translate(&self, motion: Motion) -> Motion {
        match motion {
            Motion::MouseCursor(x, y) => {
                let (sw, sh) = {
                    let Size {width, height} = self.data.viewport_size;
                    (width as f64, height as f64)
                };

                let cx = if self.data.x_axis_motion_inverted { sw - x } else { x };
                let cy = if self.data.y_axis_motion_inverted { sh - y } else { y };

                Motion::MouseCursor(cx, cy)
            },
            Motion::MouseScroll(x, y) => {
                let mx = if self.data.x_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                let my = if self.data.y_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                Motion::MouseScroll(x * mx, y * my)
            },
            relative => relative
        }
    }
}

/// An interface for rebinding keys to actions. This is freely convertable to and
/// from an InputTranslator.
#[derive(Clone, Debug, PartialEq)]
pub struct InputRebind<A: Action> {
    keymap: HashMap<A, ButtonTuple>,
    mouse_data: MouseTranslationData
}

impl<A: Action> InputRebind<A> {
    /// Creates a new InputRebind with no stored Action/ButtonTuple pairs.
    pub fn new(size: Size) -> Self {
        InputRebind {
            keymap: HashMap::new(),
            mouse_data: MouseTranslationData::new(size)
        }
    }

    /// Insert an Action into this InputRebind. If the Action is already in the
    /// InputRebind, then its ButtonTuple will be reset to (None, None, None), and
    /// the old ButtonTuple will be returned.
    pub fn insert_action(&mut self, action: A) -> Option<ButtonTuple> {
        self.keymap.insert(action, ButtonTuple::new())
    }

    /// Insert an Action into this InputRebind, and assign it to the ButtonTuple.
    /// If the Action is already in the InputRebind, the old ButtonTuple will be
    /// returned.
    pub fn insert_action_with_buttons(&mut self, action: A, buttons: ButtonTuple) -> Option<ButtonTuple> {
        self.keymap.insert(action, buttons)
    }

    /// Return a reference to the current ButtonTuple stored for an action. If the action
    /// is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings(&self, action: &A) -> Option<&ButtonTuple> {
        self.keymap.get(action)
    }

    /// Returns a mutable reference to the current ButtonTuple stored for an action. If the
    /// action is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings_mut(&mut self, action: &mut A) -> Option<&mut ButtonTuple> {
        self.keymap.get_mut(action)
    }

    /// Returns a reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the x axis is
    /// inverted.
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// x axis is inverted.
    pub fn get_x_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the y axis is
    /// inverted.
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// y axis is inverted.
    pub fn get_y_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a reference to the currently stored viewport size used for calculating the imaginary mouse
    /// position.
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    /// Returns a mutable reference to the currently stored viewport size used for calculating the imaginary
    /// mouse position.
    pub fn get_viewport_size_mut(&mut self) -> &mut Size {
        &mut self.mouse_data.viewport_size
    }

    /// Convert the `InputRebind` into an `InputTranslator`. Consumes the
    /// `InputRebind`.
    pub fn into_translator(self) -> InputTranslator<A> { self.into() }
}

impl<A: Action> Default for InputRebind<A> {
    /// Creates an `InputRebind` with no pairs. In addition, the viewport size is set to [800, 600].
    fn default() -> Self {
        InputRebind::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for InputRebind<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_translator = InputTranslator::new(self.mouse_data.viewport_size);
        input_translator.mouse_translator.data = self.mouse_data;
        let key_vec = self.keymap.values()
                                 .flat_map(|bt| bt.into_iter().filter_map(|x| x))
                                 .collect::<Vec<_>>();

        input_translator.keymap.reserve(key_vec.len());
        for &k in &key_vec {
            for (&a, bt) in self.keymap.iter() {
                if bt.contains(k) {
                    input_translator.keymap.insert(k, a);
                }
            }
        }

        input_translator
    }
}

impl<A: Action> Into<InputRebind<A>> for InputTranslator<A> {
    fn into(self) -> InputRebind<A> {
        let mut input_rebind = InputRebind::new(self.mouse_translator.data.viewport_size);
        input_rebind.mouse_data = self.mouse_translator.data;
        input_rebind.keymap = self.keymap.iter()
                                         .map(|(k, v)| (*v, vec![Some(*k)]))
                                         .sorted_by(|&(v0, _), &(v1, _)| Ord::cmp(&v0, &v1))
                                         .into_iter()
                                         .coalesce(|(k0, v0), (k1, v1)| if k0 == k1 {
                                                 Ok((k0, v0.into_iter().chain(v1).collect()))
                                             } else {
                                                 Err(((k0, v0), (k1, v1)))
                                             })
                                         .map(|(k, v)| if let [b0, b1, b2] = &v.iter()
                                                                               .cloned()
                                                                               .pad_using(3, |_| None)
                                                                               .take(3)
                                                                               .collect::<Vec<_>>()[..] {
                                                  (k, ButtonTuple(b0, b1, b2))
                                             } else {
                                                 unreachable!();
                                             })
                                         .collect();

        input_rebind
    }
}
<commit_msg>Improve documentation, and just derive `Debug` on `ButtonTuple` instead of manually implementing it<commit_after>#![warn(missing_docs)]
#![feature(slice_patterns)]

//! rebind
//! =========
//!
//! A library for binding input keys to actions, and modifying mouse behaviour. Keys can be
//! bound to actions, and then translated during runtime. `Keys` are mapped to `Actions` using
//! a `HashMap`, so lookup time is constant.

extern crate input;
extern crate itertools;
extern crate rustc_serialize;
extern crate viewport;
extern crate window;

mod builder;

#[cfg(test)]
mod test;

use input::{Input, Button, Motion};
use itertools::Itertools;
use std::cmp::{PartialEq, Eq, Ord};
use std::collections::HashMap;
use std::default::Default;
use std::fmt::{Debug, Formatter, Result};
use std::hash::Hash;
use viewport::Viewport;
use window::Size;

pub use builder::RebindBuilder;

/// Represents a logical action to be bound to a particular button press, e.g.
/// jump, attack, or move forward. Needs to be hashable, as it is used as a
/// lookup key when rebinding an action to a different button.
pub trait Action: Copy + Eq + Hash + Ord { }

/// A translated action.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Translated<A: Action> {
    /// A keypress event which was bound to an action
    Press(A),

    /// A key release event which was bound to an action
    Release(A),

    /// A translated mouse motion. The logical origin of a translated MouseCursor event
    /// is in the top left corner of the window, and the logical scroll is non-natural.
    /// Relative events are unchanged for now.
    Move(Motion)
}

/// A three-element tuple of `Option<Button>`. For simplicity, a maximum number of 3
/// buttons can be bound to each action, and this is exposed through the `InputRebind`
/// struct.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct ButtonTuple(pub Option<Button>, pub Option<Button>, pub Option<Button>);

impl ButtonTuple {
    /// Creates a new tuple with no buttons in it (equivalent to `Default::default()`).
    pub fn new() -> Self { Default::default() }

    /// Check if the button is in the tuple.
    pub fn contains(&self, button: Button) -> bool {
        let sbtn = Some(button);
        self.0 == sbtn || self.1 == sbtn || self.2 == sbtn
    }

    /// Insert a button into the tuple if there is room, searching from left to right.
    /// If the button is inserted, returns true. Otherwise, if the button is not inserted,
    /// this function returns false.
    pub fn insert_inplace(&mut self, button: Button) -> bool {
        let sbtn = Some(button);
        match self {
            &mut ButtonTuple(a, b, c) if a.is_none() => {*self = ButtonTuple(sbtn, b, c); true},
            &mut ButtonTuple(a, b, c) if b.is_none() => {*self = ButtonTuple(a, sbtn, c); true},
            &mut ButtonTuple(a, b, c) if c.is_none() => {*self = ButtonTuple(a, b, sbtn); true}
            _ => false
        }
    }

    /// Returns an iterator over this tuple.
    pub fn iter(&self) -> ButtonTupleIter { (*self).into_iter() }
}

impl IntoIterator for ButtonTuple {
    type Item = Option<Button>;
    type IntoIter = ButtonTupleIter;

    fn into_iter(self) -> Self::IntoIter {
        ButtonTupleIter {
            button_tuple: self,
            i: 0
        }
    }
}

/// An iterator over a ButtonTuple.
pub struct ButtonTupleIter {
    button_tuple: ButtonTuple,
    i: usize
}

impl Iterator for ButtonTupleIter {
    type Item = Option<Button>;

    fn next(&mut self) -> Option<Self::Item> {
        let i = self.i;
        self.i += 1;
        match i {
            0 => Some(self.button_tuple.0),
            1 => Some(self.button_tuple.1),
            2 => Some(self.button_tuple.2),
            _ => None
        }
    }
}

/// An object which translates piston::input::Input events into input_map::Translated<A> events
#[derive(Clone, Debug, PartialEq)]
pub struct InputTranslator<A: Action> {
    keymap: HashMap<Button, A>,
    mouse_translator: MouseTranslator
}

impl<A: Action> InputTranslator<A> {
    /// Creates an empty InputTranslator.
    pub fn new(size: Size) -> Self {
        InputTranslator {
            keymap: HashMap::new(),
            mouse_translator: MouseTranslator::new(size)
        }
    }

    /// Translate an Input into a Translated<A> event. Returns `None` if there is no
    /// action associated with the `Input` variant.
    pub fn translate(&self, input: &Input) -> Option<Translated<A>> {
        macro_rules! translate_button(($but_state:ident, $but_var:ident) => (
            match self.keymap.get(&$but_var).cloned() {
                Some(act) => Some(Translated::$but_state(act)),
                None => None
            });
        );

        match input {
            &Input::Press(button) => translate_button!(Press, button),
            &Input::Release(button) => translate_button!(Release, button),
            &Input::Move(motion) =>
                Some(Translated::Move(self.mouse_translator.translate(motion))),
            _ => None
        }
    }

    /// Re-set the mouse bounds size used for calculating mouse events
    pub fn set_size(&mut self, size: Size) {
        self.mouse_translator.data.viewport_size = size
    }

    /// Re-set the mouse bounds size from a viewport
    pub fn set_size_from_viewport(&mut self, vp: Viewport) {
        self.set_size(Size::from(vp.draw_size));
    }

    /// Convert the `InputTranslator` into an `InputRebind`. Consumes the
    /// `InputTranslator`.
    pub fn into_rebind(self) -> InputRebind<A> { self.into() }
}

#[derive(Clone)]
struct MouseTranslationData {
    x_axis_motion_inverted: bool,
    y_axis_motion_inverted: bool,
    x_axis_scroll_inverted: bool,
    y_axis_scroll_inverted: bool,
    _sensitivity: f64,
    viewport_size: Size
}

impl MouseTranslationData {
    fn new(size: Size) -> Self {
        MouseTranslationData {
            x_axis_motion_inverted: false,
            y_axis_motion_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            _sensitivity: 0.0,
            viewport_size: size
        }
    }
}

impl Debug for MouseTranslationData {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}, {}, {}, {}, {}, ({}, {})",
               self.x_axis_motion_inverted,
               self.y_axis_motion_inverted,
               self.x_axis_scroll_inverted,
               self.y_axis_scroll_inverted,
               self._sensitivity,
               self.viewport_size.width,
               self.viewport_size.height)
    }
}

impl PartialEq for MouseTranslationData {
    fn eq(&self, other: &Self) -> bool {
        self.x_axis_motion_inverted == other.x_axis_motion_inverted &&
        self.y_axis_motion_inverted == other.y_axis_motion_inverted &&
        self.x_axis_scroll_inverted == other.x_axis_scroll_inverted &&
        self.y_axis_scroll_inverted == other.y_axis_scroll_inverted &&
        self._sensitivity == other._sensitivity &&
        self.viewport_size.width    == other.viewport_size.width &&
        self.viewport_size.height   == other.viewport_size.height
    }
}

#[derive(Clone, Debug, PartialEq)]
struct MouseTranslator {
    data: MouseTranslationData
}

impl MouseTranslator {
    fn new(size: Size) -> Self {
        MouseTranslator {
            data: MouseTranslationData::new(size)
        }
    }

    fn translate(&self, motion: Motion) -> Motion {
        match motion {
            Motion::MouseCursor(x, y) => {
                let (sw, sh) = {
                    let Size {width, height} = self.data.viewport_size;
                    (width as f64, height as f64)
                };

                let cx = if self.data.x_axis_motion_inverted { sw - x } else { x };
                let cy = if self.data.y_axis_motion_inverted { sh - y } else { y };

                Motion::MouseCursor(cx, cy)
            },
            Motion::MouseScroll(x, y) => {
                let mx = if self.data.x_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                let my = if self.data.y_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                Motion::MouseScroll(x * mx, y * my)
            },
            relative => relative
        }
    }
}

/// An interface for rebinding keys to actions. This is freely convertable to and
/// from an InputTranslator.
#[derive(Clone, Debug, PartialEq)]
pub struct InputRebind<A: Action> {
    keymap: HashMap<A, ButtonTuple>,
    mouse_data: MouseTranslationData
}

impl<A: Action> InputRebind<A> {
    /// Creates a new InputRebind with no stored Action/ButtonTuple pairs.
    pub fn new(size: Size) -> Self {
        InputRebind {
            keymap: HashMap::new(),
            mouse_data: MouseTranslationData::new(size)
        }
    }

    /// Insert an Action into this InputRebind. If the Action is already in the
    /// InputRebind, then its ButtonTuple will be reset to (None, None, None), and
    /// the old ButtonTuple will be returned.
    pub fn insert_action(&mut self, action: A) -> Option<ButtonTuple> {
        self.keymap.insert(action, ButtonTuple::new())
    }

    /// Insert an Action into this InputRebind, and assign it to the ButtonTuple.
    /// If the Action is already in the InputRebind, the old ButtonTuple will be
    /// returned.
    pub fn insert_action_with_buttons(&mut self, action: A, buttons: ButtonTuple) -> Option<ButtonTuple> {
        self.keymap.insert(action, buttons)
    }

    /// Return a reference to the current ButtonTuple stored for an action. If the action
    /// is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings(&self, action: &A) -> Option<&ButtonTuple> {
        self.keymap.get(action)
    }

    /// Returns a mutable reference to the current ButtonTuple stored for an action. If the
    /// action is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings_mut(&mut self, action: &mut A) -> Option<&mut ButtonTuple> {
        self.keymap.get_mut(action)
    }

    /// Returns a reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the x axis is
    /// inverted.
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// x axis is inverted.
    pub fn get_x_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the y axis is
    /// inverted.
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// y axis is inverted.
    pub fn get_y_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a reference to the currently stored viewport size used for calculating the imaginary mouse
    /// position.
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    /// Returns a mutable reference to the currently stored viewport size used for calculating the imaginary
    /// mouse position.
    pub fn get_viewport_size_mut(&mut self) -> &mut Size {
        &mut self.mouse_data.viewport_size
    }

    /// Convert the `InputRebind` into an `InputTranslator`. Consumes the
    /// `InputRebind`.
    pub fn into_translator(self) -> InputTranslator<A> { self.into() }
}

impl<A: Action> Default for InputRebind<A> {
    /// Creates an `InputRebind` with no pairs. In addition, the viewport size is set to [800, 600].
    fn default() -> Self {
        InputRebind::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for InputRebind<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_translator = InputTranslator::new(self.mouse_data.viewport_size);
        input_translator.mouse_translator.data = self.mouse_data;
        let key_vec = self.keymap.values()
                                 .flat_map(|bt| bt.into_iter().filter_map(|x| x))
                                 .collect::<Vec<_>>();

        input_translator.keymap.reserve(key_vec.len());
        for &k in &key_vec {
            for (&a, bt) in self.keymap.iter() {
                if bt.contains(k) {
                    input_translator.keymap.insert(k, a);
                }
            }
        }

        input_translator
    }
}

impl<A: Action> Into<InputRebind<A>> for InputTranslator<A> {
    fn into(self) -> InputRebind<A> {
        let mut input_rebind = InputRebind::new(self.mouse_translator.data.viewport_size);
        input_rebind.mouse_data = self.mouse_translator.data;
        input_rebind.keymap = self.keymap.iter()
                                         .map(|(k, v)| (*v, vec![Some(*k)]))
                                         .sorted_by(|&(v0, _), &(v1, _)| Ord::cmp(&v0, &v1))
                                         .into_iter()
                                         .coalesce(|(k0, v0), (k1, v1)| if k0 == k1 {
                                                 Ok((k0, v0.into_iter().chain(v1).collect()))
                                             } else {
                                                 Err(((k0, v0), (k1, v1)))
                                             })
                                         .map(|(k, v)| if let [b0, b1, b2] = &v.iter()
                                                                               .cloned()
                                                                               .pad_using(3, |_| None)
                                                                               .take(3)
                                                                               .collect::<Vec<_>>()[..] {
                                                  (k, ButtonTuple(b0, b1, b2))
                                             } else {
                                                 unreachable!();
                                             })
                                         .collect();

        input_rebind
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use]
extern crate log;
#[macro_use]
mod macros;
#[cfg(test)]
mod tests;
use std::fmt;

pub trait Name {
    fn name(&self) -> &'static str;
}

pub trait Initializer {
    fn new() -> Self;
}

pub enum Action<UsrStEnum: fmt::Debug> {
    Ignore,
    Parent,
    Transition(UsrStEnum),
    ClosureTransition(Box<Fn() -> UsrStEnum>)
}
impl<UsrStEnum: fmt::Debug> fmt::Debug for Action<UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Action::Ignore               => try!(fmt::Debug::fmt("Ignore", f)),
            &Action::Parent               => try!(fmt::Debug::fmt("Parent", f)),
            &Action::Transition(ref x)    => try!(fmt::Debug::fmt(&format!("Transition({:?})", x), f)),
            &Action::ClosureTransition(_) => try!(fmt::Debug::fmt("ClosureTransition", f)),
        };
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub enum Event<UsrEvtEnum: Clone> {
    Enter,
    User(UsrEvtEnum),
    Exit
}

pub trait Parent<UsrStEnum> {
    fn get_parent(&self) -> Option<UsrStEnum>;
    fn set_parent(&mut self, newparent: UsrStEnum);
}

pub trait State<UsrEvtEnum, UsrStEnum>
    where Self: Name+Parent<UsrStEnum> {
    fn handle_event(&mut self, evt: Event<UsrEvtEnum>) -> Action<UsrStEnum>;
}
impl<'a, UsrEvtEnum, UsrStEnum> fmt::Debug for &'a State<UsrEvtEnum, UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(fmt::Debug::fmt(self.name(), f));
        Ok(())
    }
}

pub trait StateLookup<UsrStEnum, UsrEvtEnum> {
    fn lookup(&mut self, typ: &UsrStEnum) -> &mut State<UsrEvtEnum, UsrStEnum>;
}

#[derive(Clone)]
struct Task<UsrStEnum, UsrEvtEnum: Clone> {
    state:  UsrStEnum,
    event: Event<UsrEvtEnum>
}
impl<UsrStEnum, UsrEvtEnum: Clone> Task<UsrStEnum, UsrEvtEnum> {
    fn new(state:  UsrStEnum, event: Event<UsrEvtEnum>) -> Self {
        Task { state:  state, event: event }
    }
}

pub struct StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum: Clone> {
    current     : UsrStEnum,
    states      : UsrStStr,
    exit_tasks  : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    enter_tasks : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    _phantom    : ::std::marker::PhantomData<UsrEvtEnum>
}
impl<UsrStStr, UsrStEnum, UsrEvtEnum> StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum>
    where UsrStStr   : Initializer + StateLookup<UsrStEnum, UsrEvtEnum>,
          UsrStEnum  : fmt::Debug+Eq+Clone,
          UsrEvtEnum : fmt::Debug+Clone {

    pub fn new(initial: UsrStEnum) -> Self {
        StateMachine {
            current     : initial,
            states      : UsrStStr::new(),
            exit_tasks  : Vec::new(),
            enter_tasks : Vec::new(),
            _phantom    : ::std::marker::PhantomData
        }
    }

    fn process_exit_tasks(&mut self) {
        for task in self.exit_tasks.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.exit_tasks.clear();
    }

    fn process_enter_tasks(&mut self) {
        self.enter_tasks.reverse();
        for task in self.enter_tasks.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.enter_tasks.clear();
    }

    fn transition(&mut self, from_state: UsrStEnum, to_state: UsrStEnum) {
        let mut parent = Some(from_state);
        while let Some(state) = parent {
            parent = self.states.lookup(&state).get_parent();
            self.exit_tasks.push(Task::new(state, Event::Exit));
        }
        let mut same_idx: Option<usize> = None;
        parent = Some(to_state);
        'outer: while let Some(state) = parent {
            for (i, task) in self.exit_tasks.iter().enumerate() {
                if task.state == state {
                    same_idx = Some(i);
                    break 'outer;
                }
            }
            parent = self.states.lookup(&state).get_parent();
            self.enter_tasks.push(Task::new(state, Event::Enter));
        }
        if let Some(i) = same_idx {
            let drop_num = self.exit_tasks.len() - i;
            for _ in 0..drop_num {
                self.exit_tasks.pop();
            }
        }
        self.process_exit_tasks();
        self.process_enter_tasks();
    }

    pub fn input(&mut self, evt: Event<UsrEvtEnum>) {
        debug!("state:  {:?}", self.current);
        debug!("input:  {:?}", evt);
        let mut action;
        let mut state = self.current.clone();
        loop {
            action = self.states.lookup(&state).handle_event(evt.clone());
            match action {
                Action::Ignore               => {
                    self.exit_tasks.clear();
                    break
                },
                Action::Parent               => {
                    if let Some(parent) = self.states.lookup(&state).get_parent() {
                        self.exit_tasks.push(Task::new(state.clone(), Event::Exit));
                        state = parent;
                    } else {
                        error!("State {:?} responded with Action::Parent to event {:?}, but the state has no parent", state, evt);
                    }
                },
                Action::Transition(x)        => {
                    debug!("send {:?} to {:?}", evt, state);
                    self.process_exit_tasks();  // exit until in the parent that handles the signal
                    self.current = x.clone(); // signal allready handled
                    self.transition(state.clone(), x);
                    break;
                },
                Action::ClosureTransition(x) => {
                    self.process_exit_tasks(); // exit until in the parent that handles the signal
                    debug!("send {:?} to {:?}", evt, state);
                    self.current = x();      // handle the signal
                    let current_state = self.current.clone();
                    self.transition(state.clone(), current_state);
                    break;
                },
            }
        }
    }
}
<commit_msg>require starting the state machine<commit_after>#![allow(dead_code)]

#[macro_use]
extern crate log;
#[macro_use]
mod macros;
#[cfg(test)]
mod tests;
use std::fmt;

pub trait Name {
    fn name(&self) -> &'static str;
}

pub trait Initializer {
    fn new() -> Self;
}

pub enum Action<UsrStEnum: fmt::Debug> {
    Ignore,
    Parent,
    Transition(UsrStEnum),
    ClosureTransition(Box<Fn() -> UsrStEnum>)
}
impl<UsrStEnum: fmt::Debug> fmt::Debug for Action<UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Action::Ignore               => try!(fmt::Debug::fmt("Ignore", f)),
            &Action::Parent               => try!(fmt::Debug::fmt("Parent", f)),
            &Action::Transition(ref x)    => try!(fmt::Debug::fmt(&format!("Transition({:?})", x), f)),
            &Action::ClosureTransition(_) => try!(fmt::Debug::fmt("ClosureTransition", f)),
        };
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub enum Event<UsrEvtEnum: Clone> {
    Enter,
    User(UsrEvtEnum),
    Exit
}

pub trait Parent<UsrStEnum> {
    fn get_parent(&self) -> Option<UsrStEnum>;
    fn set_parent(&mut self, newparent: UsrStEnum);
}

pub trait State<UsrEvtEnum, UsrStEnum>
    where Self: Name+Parent<UsrStEnum> {
    fn handle_event(&mut self, evt: Event<UsrEvtEnum>) -> Action<UsrStEnum>;
}
impl<'a, UsrEvtEnum, UsrStEnum> fmt::Debug for &'a State<UsrEvtEnum, UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(fmt::Debug::fmt(self.name(), f));
        Ok(())
    }
}

pub trait StateLookup<UsrStEnum, UsrEvtEnum> {
    fn lookup(&mut self, typ: &UsrStEnum) -> &mut State<UsrEvtEnum, UsrStEnum>;
}

#[derive(Clone)]
struct Task<UsrStEnum, UsrEvtEnum: Clone> {
    state:  UsrStEnum,
    event: Event<UsrEvtEnum>
}
impl<UsrStEnum, UsrEvtEnum: Clone> Task<UsrStEnum, UsrEvtEnum> {
    fn new(state:  UsrStEnum, event: Event<UsrEvtEnum>) -> Self {
        Task { state:  state, event: event }
    }
}

pub struct StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum: Clone> {
    current     : UsrStEnum,
    started     : bool,
    states      : UsrStStr,
    exit_tasks  : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    enter_tasks : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    _phantom    : ::std::marker::PhantomData<UsrEvtEnum>
}
impl<UsrStStr, UsrStEnum, UsrEvtEnum> StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum>
    where UsrStStr   : Initializer + StateLookup<UsrStEnum, UsrEvtEnum>,
          UsrStEnum  : fmt::Debug+Eq+Clone,
          UsrEvtEnum : fmt::Debug+Clone {

    pub fn new(initial: UsrStEnum) -> Self {
        StateMachine {
            current     : initial,
            started     : false,
            states      : UsrStStr::new(),
            exit_tasks  : Vec::new(),
            enter_tasks : Vec::new(),
            _phantom    : ::std::marker::PhantomData
        }
    }

    pub fn start(&mut self) {
        let mut parent = Some(self.current.clone());
        while let Some(state) = parent {
            parent = self.states.lookup(&state).get_parent();
            self.enter_tasks.push(Task::new(state, Event::Enter));
        }
        self.process_enter_tasks();
        self.started = true;
    }

    fn process_exit_tasks(&mut self) {
        for task in self.exit_tasks.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.exit_tasks.clear();
    }

    fn process_enter_tasks(&mut self) {
        self.enter_tasks.reverse();
        for task in self.enter_tasks.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.enter_tasks.clear();
    }

    fn transition(&mut self, from_state: UsrStEnum, to_state: UsrStEnum) {
        let mut parent = Some(from_state);
        while let Some(state) = parent {
            parent = self.states.lookup(&state).get_parent();
            self.exit_tasks.push(Task::new(state, Event::Exit));
        }
        let mut same_idx: Option<usize> = None;
        parent = Some(to_state);
        'outer: while let Some(state) = parent {
            for (i, task) in self.exit_tasks.iter().enumerate() {
                if task.state == state {
                    same_idx = Some(i);
                    break 'outer;
                }
            }
            parent = self.states.lookup(&state).get_parent();
            self.enter_tasks.push(Task::new(state, Event::Enter));
        }
        if let Some(i) = same_idx {
            let drop_num = self.exit_tasks.len() - i;
            for _ in 0..drop_num {
                self.exit_tasks.pop();
            }
        }
        self.process_exit_tasks();
        self.process_enter_tasks();
    }

    pub fn input(&mut self, evt: Event<UsrEvtEnum>) {
        assert!(self.started, "Can't call input before starting the state machine with start()");
        debug!("state:  {:?}", self.current);
        debug!("input:  {:?}", evt);
        let mut action;
        let mut state = self.current.clone();
        loop {
            action = self.states.lookup(&state).handle_event(evt.clone());
            match action {
                Action::Ignore               => {
                    self.exit_tasks.clear();
                    break
                },
                Action::Parent               => {
                    if let Some(parent) = self.states.lookup(&state).get_parent() {
                        self.exit_tasks.push(Task::new(state.clone(), Event::Exit));
                        state = parent;
                    } else {
                        error!("State {:?} responded with Action::Parent to event {:?}, but the state has no parent", state, evt);
                    }
                },
                Action::Transition(x)        => {
                    debug!("send {:?} to {:?}", evt, state);
                    self.process_exit_tasks();  // exit until in the parent that handles the signal
                    self.current = x.clone(); // signal allready handled
                    self.transition(state.clone(), x);
                    break;
                },
                Action::ClosureTransition(x) => {
                    self.process_exit_tasks(); // exit until in the parent that handles the signal
                    debug!("send {:?} to {:?}", evt, state);
                    self.current = x();      // handle the signal
                    let current_state = self.current.clone();
                    self.transition(state.clone(), current_state);
                    break;
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>use rope::Node;

/// An immutable view into part of a Rope.
pub struct RopeSlice<'a> {
    node: &'a Node,
    start: usize,
    end: usize,
}

impl<'a> RopeSlice<'a> {
    pub(crate) fn new_from_node<'b>(node: &'b Node, start: usize, end: usize) -> RopeSlice<'b> {
        assert!(start <= end);
        assert!(end < node.text_info().chars as usize);

        // Find the deepest node that still contains the full range given.
        let mut n_start = start;
        let mut n_end = end;
        let mut node = node;
        'outer: loop {
            match node as &Node {
                &Node::Empty | &Node::Leaf(_) => break,

                &Node::Internal {
                    ref info,
                    ref children,
                } => {
                    let mut start_char = 0;
                    for (i, inf) in info.iter().enumerate() {
                        if n_start >= start_char && n_end < (start_char + inf.chars as usize) {
                            n_start -= start_char;
                            n_end -= start_char;
                            node = &children[i];
                            continue 'outer;
                        }
                        start_char += inf.chars as usize;
                    }
                    break;
                }
            }
        }

        // Create the slice
        RopeSlice {
            node: node,
            start: n_start,
            end: n_end,
        }
    }

    /// Returns an immutable slice of the RopeSlice in the char range `start..end`.
    pub fn slice(&self, start: usize, end: usize) -> RopeSlice<'a> {
        assert!(start <= end);
        assert!(end < (self.end - self.start));
        RopeSlice::new_from_node(self.node, self.start + start, self.start + end)
    }

    /// Creates an iterator over the bytes of the RopeSlice.
    pub fn bytes<'a>(&'a self) -> RopeBytes<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the chars of the RopeSlice.
    pub fn chars<'a>(&'a self) -> RopeChars<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the lines of the RopeSlice.
    pub fn lines<'a>(&'a self) -> RopeLines<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the chunks of the RopeSlice.
    pub fn chunks<'a>(&'a self) -> RopeChunks<'a> {
        unimplemented!()
    }
}
<commit_msg>Forgot to make sure the previous commit actually compiled.<commit_after>use rope::Node;
use iter::{RopeBytes, RopeChars, RopeLines, RopeChunks};

/// An immutable view into part of a Rope.
pub struct RopeSlice<'a> {
    node: &'a Node,
    start: usize,
    end: usize,
}

impl<'a> RopeSlice<'a> {
    pub(crate) fn new_from_node<'b>(node: &'b Node, start: usize, end: usize) -> RopeSlice<'b> {
        assert!(start <= end);
        assert!(end < node.text_info().chars as usize);

        // Find the deepest node that still contains the full range given.
        let mut n_start = start;
        let mut n_end = end;
        let mut node = node;
        'outer: loop {
            match node as &Node {
                &Node::Empty | &Node::Leaf(_) => break,

                &Node::Internal {
                    ref info,
                    ref children,
                } => {
                    let mut start_char = 0;
                    for (i, inf) in info.iter().enumerate() {
                        if n_start >= start_char && n_end < (start_char + inf.chars as usize) {
                            n_start -= start_char;
                            n_end -= start_char;
                            node = &children[i];
                            continue 'outer;
                        }
                        start_char += inf.chars as usize;
                    }
                    break;
                }
            }
        }

        // Create the slice
        RopeSlice {
            node: node,
            start: n_start,
            end: n_end,
        }
    }

    /// Returns an immutable slice of the RopeSlice in the char range `start..end`.
    pub fn slice(&self, start: usize, end: usize) -> RopeSlice<'a> {
        assert!(start <= end);
        assert!(end < (self.end - self.start));
        RopeSlice::new_from_node(self.node, self.start + start, self.start + end)
    }

    /// Creates an iterator over the bytes of the RopeSlice.
    pub fn bytes(&self) -> RopeBytes<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the chars of the RopeSlice.
    pub fn chars(&self) -> RopeChars<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the lines of the RopeSlice.
    pub fn lines(&self) -> RopeLines<'a> {
        unimplemented!()
    }

    /// Creates an iterator over the chunks of the RopeSlice.
    pub fn chunks(&self) -> RopeChunks<'a> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>#![allow(unused_features)]
#![cfg_attr(not(test), no_std)]
#![feature(asm)]
#![feature(core_intrinsics)]
#![feature(naked_functions)]
// TODO(rust-lang/rust#35021) uncomment when that PR lands
// #![feature(rustc_builtins)]

#[cfg(test)]
extern crate core;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;

#[cfg(target_arch = "arm")]
pub mod arm;

#[cfg(test)]
mod test;

use core::mem;

/// Trait for some basic operations on integers
trait Int {
    fn bits() -> usize;
}

// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
impl Int for u32 {
    fn bits() -> usize { 32 }
}
impl Int for i32 {
    fn bits() -> usize { 32 }
}
impl Int for u64 {
    fn bits() -> usize { 64 }
}
impl Int for i64 {
    fn bits() -> usize { 64 }
}

/// Trait to convert an integer to/from smaller parts
trait LargeInt {
    type LowHalf;
    type HighHalf;

    fn low(self) -> Self::LowHalf;
    fn high(self) -> Self::HighHalf;
    fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
}

// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
impl LargeInt for u64 {
    type LowHalf = u32;
    type HighHalf = u32;

    fn low(self) -> u32 {
        self as u32
    }
    fn high(self) -> u32 {
        (self >> 32) as u32
    }
    fn from_parts(low: u32, high: u32) -> u64 {
        low as u64 | ((high as u64) << 32)
    }
}
impl LargeInt for i64 {
    type LowHalf = u32;
    type HighHalf = i32;

    fn low(self) -> u32 {
        self as u32
    }
    fn high(self) -> i32 {
        (self >> 32) as i32
    }
    fn from_parts(low: u32, high: i32) -> i64 {
        low as i64 | ((high as i64) << 32)
    }
}

macro_rules! absv_i2 {
    ($intrinsic:ident : $ty:ty) => {
        #[no_mangle]
        pub extern "C" fn $intrinsic(x: $ty) -> $ty {
            let n = <$ty>::bits();
            if x == 1 << (n - 1) {
                panic!();
            }
            let y = x >> (n - 1);
            (x ^ y) - y
        }

    }
}

absv_i2!(__absvsi2: i32);
absv_i2!(__absvdi2: i64);
// TODO(rust-lang/35118)?
// absv_i2!(__absvti2, i128);

#[no_mangle]
pub extern "C" fn __udivmoddi4(a: u64, b: u64, rem: Option<&mut u64>) -> u64 {
    #[cfg(target_endian = "little")]
    #[repr(C)]
    #[derive(Debug)]
    struct words {
        low: u32,
        high: u32,
    }

    #[cfg(target_endian = "big")]
    #[repr(C)]
    #[derive(Debug)]
    struct words {
        high: u32,
        low: u32,
    }

    impl words {
        fn all(&mut self) -> &mut u64 {
            unsafe { mem::transmute(self) }
        }

        fn u64(&self) -> u64 {
            unsafe { *(self as *const _ as *const u64) }
        }
    }

    impl From<u64> for words {
        fn from(x: u64) -> words {
            unsafe { mem::transmute(x) }
        }
    }

    let u32_bits = u32::bits() as u32;
    let u64_bits = u64::bits() as u32;

    let n = words::from(a);
    let d = words::from(b);

    // NOTE X is unknown, K != 0
    if n.high == 0 {
        return if d.high == 0 {
            // 0 X
            // ---
            // 0 X

            if let Some(rem) = rem {
                *rem = u64::from(n.low % d.low);
            }
            u64::from(n.low / d.low)
        } else
               // d.high != 0
               {
            // 0 X
            // ---
            // K X

            if let Some(rem) = rem {
                *rem = u64::from(n.low);
            }
            0
        };
    }

    let mut sr;
    // NOTE IMO it should be possible to leave these "uninitialized" (just declare them here)
    // because these variables get initialized below, but if I do that the compiler complains about
    // them being used before being initialized.
    let mut q = words { low: 0, high: 0 };
    let mut r = words { low: 0, high: 0 };

    // n.high != 0
    if d.low == 0 {
        if d.high == 0 {
            // K X
            // ---
            // 0 0

            // NOTE copied verbatim from compiler-rt, but does division by zero even make sense?
            if let Some(rem) = rem {
                *rem = u64::from(n.high % d.low);
            }
            return u64::from(n.high / d.low);
        }

        // d.high != 0
        if n.low == 0 {
            // K 0
            // ---
            // K 0

            if let Some(rem) = rem {
                *rem = words {
                        low: 0,
                        high: n.high % d.high,
                    }
                    .u64();
            }
            return u64::from(n.high / d.high);
        }

        // n.low != 0
        // K K
        // ---
        // K 0

        if d.high.is_power_of_two() {
            if let Some(rem) = rem {
                *rem = words {
                        low: n.low,
                        high: n.high & (d.high - 1),
                    }
                    .u64()
            }

            return u64::from(n.high >> d.high.trailing_zeros());
        }

        sr = d.high.leading_zeros().wrapping_sub(n.high.leading_zeros());

        // D > N
        if sr > u32_bits - 2 {
            if let Some(rem) = rem {
                *rem = n.u64();
            }
            return 0;
        }

        sr = sr + 1;

        // 1 <= sr <= u32_bits - 1
        // *q.all() = n.u64() << (u64_bits - sr);
        q.low = 0;
        q.high = n.low << (u32_bits - sr);
        // *r.all() = n.u64() >> sr
        r.high = n.high >> sr;
        r.low = (n.high << (u32_bits - sr)) | (n.low >> sr);
    } else
    // d.low != 0
    {
        if d.high == 0 {
            // K X
            // ---
            // 0 K
            if d.low.is_power_of_two() {
                if let Some(rem) = rem {
                    *rem = u64::from(n.low & (d.low - 1));
                }

                return if d.low == 1 {
                    n.u64()
                } else {
                    let sr = d.low.trailing_zeros();
                    words {
                            low: (n.high << (u32_bits - sr)) | (n.low >> sr),
                            high: n.high >> sr,
                        }
                        .u64()
                };
            }

            sr = 1 + u32_bits + d.low.leading_zeros() - n.high.leading_zeros();

            // 2 <= sr <= u64_bits - 1
            // *q.all() = n.u64() << (u64_bits - sr)
            // *r.all() = n.u64() >> sr;
            if sr == u32_bits {
                q.low = 0;
                q.high = n.low;
                r.high = 0;
                r.low = n.high;
            } else if sr < u32_bits
            // 2 <= sr <= u32_bits - 1
            {
                q.low = 0;
                q.high = n.low << (u32_bits - sr);
                r.high = n.high >> sr;
                r.low = (n.high << (u32_bits - sr)) | (n.low >> sr);
            } else
            // u32_bits + 1 <= sr <= u64_bits - 1
            {
                q.low = n.low << (u64_bits - sr);
                q.high = (n.high << (u64_bits - sr)) | (n.low >> (sr - u32_bits));
                r.high = 0;
                r.low = n.high >> (sr - u32_bits);
            }

        } else
        // d.high != 0
        {
            // K X
            // ---
            // K K

            sr = d.high.leading_zeros().wrapping_sub(n.high.leading_zeros());

            // D > N
            if sr > u32_bits - 1 {
                if let Some(rem) = rem {
                    *rem = a;
                    return 0;
                }
            }

            sr += 1;

            // 1 <= sr <= u32_bits
            // *q.all() = n.u64() << (u64_bits - sr)
            q.low = 0;
            if sr == u32_bits {
                q.high = n.low;
                r.high = 0;
                r.low = n.high;
            } else {
                q.high = n.low << (u32_bits - sr);
                r.high = n.high >> sr;
                r.low = (n.high << (u32_bits - sr)) | (n.low >> sr);
            }
        }
    }

    // Not a special case
    // q and r are initialized with
    // *q.all() = n.u64() << (u64_bits - sr)
    // *.r.all() = n.u64() >> sr
    // 1 <= sr <= u64_bits - 1
    let mut carry = 0;

    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r.high = (r.high << 1) | (r.low >> (u32_bits - 1));
        r.low = (r.low << 1) | (q.high >> (u32_bits - 1));
        q.high = (q.high << 1) | (q.low >> (u32_bits - 1));
        q.low = (q.low << 1) | carry;

        // carry = 0
        // if r.u64() >= d.u64() {
        //     *r.all() -= d.u64();
        //     carry = 1;
        // }

        let s = (d.u64().wrapping_sub(r.u64()).wrapping_sub(1)) as i64 >> (u64_bits - 1);
        carry = (s & 1) as u32;
        *r.all() -= d.u64() & s as u64;
    }

    *q.all() = (q.u64() << 1) | carry as u64;
    if let Some(rem) = rem {
        *rem = r.u64();
    }
    q.u64()
}

#[no_mangle]
pub extern "C" fn __udivmodsi4(a: u32, b: u32, rem: Option<&mut u32>) -> u32 {
    let d = __udivsi3(a, b);
    if let Some(rem) = rem {
        *rem = a - (d*b);
    }
    return d;
}

#[no_mangle]
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
    let u32_bits = u32::bits() as u32;

    // Special cases
    if d == 0 {
        return 0; // ?!
    }

    if n == 0 {
        return 0;
    }

    let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());

    // d > n
    if sr > u32_bits - 1 {
        return 0;
    }

    // d == 1
    if sr == u32_bits - 1 {
        return n;
    }

    sr = sr + 1;

    // 1 <= sr <= u32_bits - 1
    let mut q = n << (u32_bits - sr);
    let mut r = n >> sr;

    let mut carry = 0;
    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r = (r << 1) | (q >> (u32_bits - 1));
        q = (q << 1) | carry;

        // carry = 0;
        // if r > d {
        //     r -= d;
        //     carry = 1;
        // }

        let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32_bits - 1);
        carry = (s & 1) as u32;
        r -= d & s as u32;
    }

    q = (q << 1) | carry;
    q
}
<commit_msg>move return into if branches<commit_after>#![allow(unused_features)]
#![cfg_attr(not(test), no_std)]
#![feature(asm)]
#![feature(core_intrinsics)]
#![feature(naked_functions)]
// TODO(rust-lang/rust#35021) uncomment when that PR lands
// #![feature(rustc_builtins)]

#[cfg(test)]
extern crate core;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;

#[cfg(target_arch = "arm")]
pub mod arm;

#[cfg(test)]
mod test;

use core::mem;

/// Trait for some basic operations on integers
trait Int {
    fn bits() -> usize;
}

// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
impl Int for u32 {
    fn bits() -> usize { 32 }
}
impl Int for i32 {
    fn bits() -> usize { 32 }
}
impl Int for u64 {
    fn bits() -> usize { 64 }
}
impl Int for i64 {
    fn bits() -> usize { 64 }
}

/// Trait to convert an integer to/from smaller parts
trait LargeInt {
    type LowHalf;
    type HighHalf;

    fn low(self) -> Self::LowHalf;
    fn high(self) -> Self::HighHalf;
    fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
}

// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
impl LargeInt for u64 {
    type LowHalf = u32;
    type HighHalf = u32;

    fn low(self) -> u32 {
        self as u32
    }
    fn high(self) -> u32 {
        (self >> 32) as u32
    }
    fn from_parts(low: u32, high: u32) -> u64 {
        low as u64 | ((high as u64) << 32)
    }
}
impl LargeInt for i64 {
    type LowHalf = u32;
    type HighHalf = i32;

    fn low(self) -> u32 {
        self as u32
    }
    fn high(self) -> i32 {
        (self >> 32) as i32
    }
    fn from_parts(low: u32, high: i32) -> i64 {
        low as i64 | ((high as i64) << 32)
    }
}

macro_rules! absv_i2 {
    ($intrinsic:ident : $ty:ty) => {
        #[no_mangle]
        pub extern "C" fn $intrinsic(x: $ty) -> $ty {
            let n = <$ty>::bits();
            if x == 1 << (n - 1) {
                panic!();
            }
            let y = x >> (n - 1);
            (x ^ y) - y
        }

    }
}

absv_i2!(__absvsi2: i32);
absv_i2!(__absvdi2: i64);
// TODO(rust-lang/35118)?
// absv_i2!(__absvti2, i128);

#[no_mangle]
pub extern "C" fn __udivmoddi4(a: u64, b: u64, rem: Option<&mut u64>) -> u64 {
    #[cfg(target_endian = "little")]
    #[repr(C)]
    #[derive(Debug)]
    struct words {
        low: u32,
        high: u32,
    }

    #[cfg(target_endian = "big")]
    #[repr(C)]
    #[derive(Debug)]
    struct words {
        high: u32,
        low: u32,
    }

    impl words {
        fn all(&mut self) -> &mut u64 {
            unsafe { mem::transmute(self) }
        }

        fn u64(&self) -> u64 {
            unsafe { *(self as *const _ as *const u64) }
        }
    }

    impl From<u64> for words {
        fn from(x: u64) -> words {
            unsafe { mem::transmute(x) }
        }
    }

    let u32_bits = u32::bits() as u32;
    let u64_bits = u64::bits() as u32;

    let n = words::from(a);
    let d = words::from(b);

    // NOTE X is unknown, K != 0
    if n.high == 0 {
        if d.high == 0 {
            // 0 X
            // ---
            // 0 X

            if let Some(rem) = rem {
                *rem = u64::from(n.low % d.low);
            }
            return u64::from(n.low / d.low);
        } else
               // d.high != 0
               {
            // 0 X
            // ---
            // K X

            if let Some(rem) = rem {
                *rem = u64::from(n.low);
            }
            return 0;
        };
    }

    let mut sr;
    // NOTE IMO it should be possible to leave these "uninitialized" (just declare them here)
    // because these variables get initialized below, but if I do that the compiler complains about
    // them being used before being initialized.
    let mut q = words { low: 0, high: 0 };
    let mut r = words { low: 0, high: 0 };

    // n.high != 0
    if d.low == 0 {
        if d.high == 0 {
            // K X
            // ---
            // 0 0

            // NOTE copied verbatim from compiler-rt, but does division by zero even make sense?
            if let Some(rem) = rem {
                *rem = u64::from(n.high % d.low);
            }
            return u64::from(n.high / d.low);
        }

        // d.high != 0
        if n.low == 0 {
            // K 0
            // ---
            // K 0

            if let Some(rem) = rem {
                *rem = words {
                        low: 0,
                        high: n.high % d.high,
                    }
                    .u64();
            }
            return u64::from(n.high / d.high);
        }

        // n.low != 0
        // K K
        // ---
        // K 0

        if d.high.is_power_of_two() {
            if let Some(rem) = rem {
                *rem = words {
                        low: n.low,
                        high: n.high & (d.high - 1),
                    }
                    .u64()
            }

            return u64::from(n.high >> d.high.trailing_zeros());
        }

        sr = d.high.leading_zeros().wrapping_sub(n.high.leading_zeros());

        // D > N
        if sr > u32_bits - 2 {
            if let Some(rem) = rem {
                *rem = n.u64();
            }
            return 0;
        }

        sr = sr + 1;

        // 1 <= sr <= u32_bits - 1
        // *q.all() = n.u64() << (u64_bits - sr);
        q.low = 0;
        q.high = n.low << (u32_bits - sr);
        // *r.all() = n.u64() >> sr
        r.high = n.high >> sr;
        r.low = (n.high << (u32_bits - sr)) | (n.low >> sr);
    } else
    // d.low != 0
    {
        if d.high == 0 {
            // K X
            // ---
            // 0 K
            if d.low.is_power_of_two() {
                if let Some(rem) = rem {
                    *rem = u64::from(n.low & (d.low - 1));
                }

                return if d.low == 1 {
                    n.u64()
                } else {
                    let sr = d.low.trailing_zeros();
                    words {
                            low: (n.high << (u32_bits - sr)) | (n.low >> sr),
                            high: n.high >> sr,
                        }
                        .u64()
                };
            }

            sr = 1 + u32_bits + d.low.leading_zeros() - n.high.leading_zeros();

            // 2 <= sr <= u64_bits - 1
            // *q.all() = n.u64() << (u64_bits - sr)
            // *r.all() = n.u64() >> sr;
            if sr == u32_bits {
                q.low = 0;
                q.high = n.low;
                r.high = 0;
                r.low = n.high;
            } else if sr < u32_bits
            // 2 <= sr <= u32_bits - 1
            {
                q.low = 0;
                q.high = n.low << (u32_bits - sr);
                r.high = n.high >> sr;
                r.low = (n.high << (u32_bits - sr)) | (n.low >> sr);
            } else
            // u32_bits + 1 <= sr <= u64_bits - 1
            {
                q.low = n.low << (u64_bits - sr);
                q.high = (n.high << (u64_bits - sr)) | (n.low >> (sr - u32_bits));
                r.high = 0;
                r.low = n.high >> (sr - u32_bits);
            }

        } else
        // d.high != 0
        {
            // K X
            // ---
            // K K

            sr = d.high.leading_zeros().wrapping_sub(n.high.leading_zeros());

            // D > N
            if sr > u32_bits - 1 {
                if let Some(rem) = rem {
                    *rem = a;
                    return 0;
                }
            }

            sr += 1;

            // 1 <= sr <= u32_bits
            // *q.all() = n.u64() << (u64_bits - sr)
            q.low = 0;
            if sr == u32_bits {
                q.high = n.low;
                r.high = 0;
                r.low = n.high;
            } else {
                q.high = n.low << (u32_bits - sr);
                r.high = n.high >> sr;
                r.low = (n.high << (u32_bits - sr)) | (n.low >> sr);
            }
        }
    }

    // Not a special case
    // q and r are initialized with
    // *q.all() = n.u64() << (u64_bits - sr)
    // *.r.all() = n.u64() >> sr
    // 1 <= sr <= u64_bits - 1
    let mut carry = 0;

    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r.high = (r.high << 1) | (r.low >> (u32_bits - 1));
        r.low = (r.low << 1) | (q.high >> (u32_bits - 1));
        q.high = (q.high << 1) | (q.low >> (u32_bits - 1));
        q.low = (q.low << 1) | carry;

        // carry = 0
        // if r.u64() >= d.u64() {
        //     *r.all() -= d.u64();
        //     carry = 1;
        // }

        let s = (d.u64().wrapping_sub(r.u64()).wrapping_sub(1)) as i64 >> (u64_bits - 1);
        carry = (s & 1) as u32;
        *r.all() -= d.u64() & s as u64;
    }

    *q.all() = (q.u64() << 1) | carry as u64;
    if let Some(rem) = rem {
        *rem = r.u64();
    }
    q.u64()
}

#[no_mangle]
pub extern "C" fn __udivmodsi4(a: u32, b: u32, rem: Option<&mut u32>) -> u32 {
    let d = __udivsi3(a, b);
    if let Some(rem) = rem {
        *rem = a - (d*b);
    }
    return d;
}

#[no_mangle]
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
    let u32_bits = u32::bits() as u32;

    // Special cases
    if d == 0 {
        return 0; // ?!
    }

    if n == 0 {
        return 0;
    }

    let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());

    // d > n
    if sr > u32_bits - 1 {
        return 0;
    }

    // d == 1
    if sr == u32_bits - 1 {
        return n;
    }

    sr = sr + 1;

    // 1 <= sr <= u32_bits - 1
    let mut q = n << (u32_bits - sr);
    let mut r = n >> sr;

    let mut carry = 0;
    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r = (r << 1) | (q >> (u32_bits - 1));
        q = (q << 1) | carry;

        // carry = 0;
        // if r > d {
        //     r -= d;
        //     carry = 1;
        // }

        let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32_bits - 1);
        carry = (s & 1) as u32;
        r -= d & s as u32;
    }

    q = (q << 1) | carry;
    q
}
<|endoftext|>


<commit_before>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1;
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.update("Hello World!".as_bytes());
//! assert_eq!(m.hexdigest().as_slice(),
//!            "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(core, collections, old_io)]
#![unstable]

use std::old_io::BufWriter;
use std::num::Int;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&format!("{:02x}", *b));
    }
    return s;
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);
            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Resets the hash object to it's initial state.
    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    /// Update hash with input data.
    pub fn update(&mut self, data: &[u8]) {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(data);

        for chunk in d.chunks(64) {
            self.len += chunk.len() as u64;

            if chunk.len() == 64 {
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w : Vec<u8> = Vec::new();
        w.write_all(&self.data);
        w.write_u8(0x80 as u8);
        let padding = (((56 - self.len as isize - 1) % 64) + 64) % 64;
        for _ in range(0, padding) {
            w.write_u8(0u8);
        }

        w.write_be_u64(self.len * 8);
        for chunk in w.chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_be_u32(n);
        }
    }

    /// Shortcut for getting `output` into a new vector.
    pub fn digest(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut buf);
        buf
    }

    /// Shortcut for getting a hex output of the vector.
    pub fn hexdigest(&self) -> String {
        to_hex(&self.digest())
    }
}

#[test]
fn test_simple() {
    let mut m = Sha1::new();

    let tests = [
        ("The quick brown fox jumps over the lazy dog",
         "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
        ("The quick brown fox jumps over the lazy cog",
         "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
        ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
        ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
        ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
    ];

    for &(s, ref h) in tests.iter() {
        let data = s.as_bytes();

        m.reset();
        m.update(data);
        let hh = m.hexdigest();

        assert_eq!(hh.len(), h.len());
		assert_eq!(hh, *h);
    }
}
<commit_msg>Fix invalid message length calculation<commit_after>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1;
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.update("Hello World!".as_bytes());
//! assert_eq!(m.hexdigest().as_slice(),
//!            "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(core, collections, old_io)]
#![unstable]

use std::old_io::BufWriter;
use std::num::Int;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&format!("{:02x}", *b));
    }
    return s;
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);
            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Resets the hash object to it's initial state.
    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    /// Update hash with input data.
    pub fn update(&mut self, data: &[u8]) {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(data);

        for chunk in d.chunks(64) {
            if chunk.len() == 64 {
                self.len += chunk.len() as u64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w : Vec<u8> = Vec::new();
        w.write_all(&self.data);
        w.write_u8(0x80 as u8);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in range(0, padding) {
            w.write_u8(0u8);
        }

        w.write_be_u64((self.data.len() as u64 + self.len) * 8);
        for chunk in w.chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_be_u32(n);
        }
    }

    /// Shortcut for getting `output` into a new vector.
    pub fn digest(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut buf);
        buf
    }

    /// Shortcut for getting a hex output of the vector.
    pub fn hexdigest(&self) -> String {
        to_hex(&self.digest())
    }
}

#[test]
fn test_simple() {
    let mut m = Sha1::new();

    let tests = [
        ("The quick brown fox jumps over the lazy dog",
         "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
        ("The quick brown fox jumps over the lazy cog",
         "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
        ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
        ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
        ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
    ];

    for &(s, ref h) in tests.iter() {
        let data = s.as_bytes();

        m.reset();
        m.update(data);
        let hh = m.hexdigest();

        assert_eq!(hh.len(), h.len());
		assert_eq!(hh, *h);
    }
}
<|endoftext|>