<commit_before>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with two f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2f {
    pub x: f32,
    pub y: f32
}

impl Vec2f {
    /// Create a Vec2f from two components
    pub fn new(x: f32, y: f32) -> Vec2f {
        Vec2f { x: x,
                y: y }
    }

    pub fn cross(&self, other: Vec2f) -> f32 {
        self.x * other.y - self.y * other.x
    }
}

impl Add for Vec2f {
    type Output = Vec2f;
    fn add(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x + v.x, self.y + v.y)
    }
}

impl Sub for Vec2f {
    type Output = Vec2f;
    fn sub(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x - v.x, self.y - v.y)
    }
}

impl Div<f32> for Vec2f {
    type Output = Vec2f;
    fn div(self, s: f32) -> Vec2f {
        Vec2f::new(self.x / s, self.y / s)
    }
}

/// 2D Quadrilateral
///
/// ```
///   p3____p2
///    |    |
///    |____|
///   p0    p1
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Quad2f {
    pub points: (Vec2f, Vec2f, Vec2f, Vec2f)
}

impl Quad2f {
    pub fn new(a: Vec2f, b: Vec2f, c: Vec2f, d: Vec2f) -> Quad2f {
        Quad2f {
            points: (a, b, c, d)
        }
    }

    // Adapted from stackoverflow.com/questions/808441
    pub fn iblerp(&self, point: Vec2f) {
        let a = (self.points.0 - point).cross(self.points.0 - self.points.2);
        let b = ( (self.points.0 - point).cross(self.points.1 - self.points.3) + (self.points.1 - point).cross(self.points.0 - self.points.2) ) / 2;
        let c = (self.points.1 - point).cross(self.points.1 - self.points.3);
    }
}

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }

    /// Projection of `self` into `v`, or None if the magnitude of
    /// `b` is zero.
    pub fn project_onto(&self, v: Vec3f) -> Option<Vec3f> {
        if v == ZERO_3F {
            None
        }
        else {
            Some(v * (dot3(*self, v) / dot3(v, v)))
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for isize { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for usize { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Add<f32> for Vec3f {
    type Output = Vec3f;
    fn add(self, s: f32) -> Vec3f {
        Vec3f::new(self.x + s, self.y + s, self.z + s)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

impl Sub<f32> for Vec3f {
    type Output = Vec3f;
    fn sub(self, s: f32) -> Vec3f {
        Vec3f::new(self.x - s, self.y - s, self.z - s)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_project_onto() {
    let z = vec3f(0, 0, 0);
    let a = vec3f(1, 0, 0);
    let b = vec3f(1, 1, 0);
    assert_eq!(a.project_onto(z), None);
    assert_eq!(a.project_onto(b).unwrap(), vec3f(0.5, 0.5, 0));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<commit_msg>Add vec2f convenience function<commit_after>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with two f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2f {
    pub x: f32,
    pub y: f32
}

impl Vec2f {
    /// Create a Vec2f from two components
    pub fn new(x: f32, y: f32) -> Vec2f {
        Vec2f { x: x,
                y: y }
    }

    pub fn cross(&self, other: Vec2f) -> f32 {
        self.x * other.y - self.y * other.x
    }
}

impl Add for Vec2f {
    type Output = Vec2f;
    fn add(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x + v.x, self.y + v.y)
    }
}

impl Sub for Vec2f {
    type Output = Vec2f;
    fn sub(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x - v.x, self.y - v.y)
    }
}

impl Div<f32> for Vec2f {
    type Output = Vec2f;
    fn div(self, s: f32) -> Vec2f {
        Vec2f::new(self.x / s, self.y / s)
    }
}

/// 2D Quadrilateral
///
/// ```
///   p3____p2
///    |    |
///    |____|
///   p0    p1
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Quad2f {
    pub points: (Vec2f, Vec2f, Vec2f, Vec2f)
}

impl Quad2f {
    pub fn new(a: Vec2f, b: Vec2f, c: Vec2f, d: Vec2f) -> Quad2f {
        Quad2f {
            points: (a, b, c, d)
        }
    }

    // Adapted from stackoverflow.com/questions/808441
    pub fn iblerp(&self, point: Vec2f) {
        let a = (self.points.0 - point).cross(self.points.0 - self.points.2);
        let b = ( (self.points.0 - point).cross(self.points.1 - self.points.3) + (self.points.1 - point).cross(self.points.0 - self.points.2) ) / 2;
        let c = (self.points.1 - point).cross(self.points.1 - self.points.3);
    }
}

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }

    /// Projection of `self` into `v`, or None if the magnitude of
    /// `b` is zero.
    pub fn project_onto(&self, v: Vec3f) -> Option<Vec3f> {
        if v == ZERO_3F {
            None
        }
        else {
            Some(v * (dot3(*self, v) / dot3(v, v)))
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for isize { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for usize { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec2f from x and y inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec2f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec2f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec2f<X: CastF32, Y: CastF32>(x: X, y: Y) -> Vec2f {
    Vec2f { x: x.as_f32(), y: y.as_f32() }
}

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Add<f32> for Vec3f {
    type Output = Vec3f;
    fn add(self, s: f32) -> Vec3f {
        Vec3f::new(self.x + s, self.y + s, self.z + s)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

impl Sub<f32> for Vec3f {
    type Output = Vec3f;
    fn sub(self, s: f32) -> Vec3f {
        Vec3f::new(self.x - s, self.y - s, self.z - s)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_project_onto() {
    let z = vec3f(0, 0, 0);
    let a = vec3f(1, 0, 0);
    let b = vec3f(1, 1, 0);
    assert_eq!(a.project_onto(z), None);
    assert_eq!(a.project_onto(b).unwrap(), vec3f(0.5, 0.5, 0));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<|endoftext|>


<commit_before>use std::result::Result;
use std::collections::HashMap;

use gossyp_base::RetrieveToolError;
use gossyp_base::Environment;
use gossyp_base::Tool;

///
/// Errors that can occur when binding a variable
///
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
pub enum BindingError {
    /// The requested variable name is already in use
    AlreadyInUse,
}

///
/// Result of binding to an environment
///
pub enum BindingResult {
    /// Name maps to a variable
    Variable(u32),

    /// Name maps to a tool in the external environment
    Tool(Box<Tool>),

    /// Got an error while mapping a tool (binding isn't a tool or a variable)
    Error(RetrieveToolError)
}

///
/// A binding environment can be used to allocate variable values that will be used
/// during execution of a script.
///
struct BaseBindingEnvironment<'a> {
    /// The external environment that contains tools we can bind to
    environment: &'a Environment,

    /// The next variable value that will be alllocated
    next_to_allocate: u32,

    /// The current set of binding allocations
    bindings: HashMap<String, u32>
}

///
/// A child environment for a base environment
///
struct ChildBindingEnvironment<'a> {
    /// The base binding environment that this child environment is for
    base_environment: &'a mut BindingEnvironment,

    /// The current set of binding allocations
    bindings: HashMap<String, u32>
}

///
/// Trait implemented by objects that represent a binding environment
///
pub trait BindingEnvironment {
    ///
    /// Allocates a variable location without assigning a name
    ///
    fn allocate_location(&mut self) -> u32;

    ///
    /// Allocates a variable location with an assigned name (which must not
    /// already be in use)
    ///
    fn allocate_variable(&mut self, name: &str) -> Result<u32, BindingError>;

    ///
    /// Looks up a variable location by name
    ///
    fn lookup(&self, name: &str) -> BindingResult;

    ///
    /// Returns the total number of variables allocated for this environment
    ///
    fn get_number_of_variables(&self) -> u32;

    ///
    /// Creates a sub environment
    ///
    /// This allows names to be re-used with new variables, but existing variables
    /// will continue to refer to their current locations
    ///
    fn create_sub_environment<'a>(&'a mut self) -> Box<BindingEnvironment + 'a>;
}

impl BindingEnvironment {
    ///
    /// Creates a new binding environment. New variables will be mapped from 0
    ///
    pub fn new<'a>(environment: &'a Environment) -> Box<BindingEnvironment+'a> {
        Box::new(BaseBindingEnvironment {
            environment:        environment,
            next_to_allocate:   0,
            bindings:           HashMap::new()
        })
    }
}

impl<'a> BindingEnvironment for BaseBindingEnvironment<'a> {
    ///
    /// Creates a new sub-environment, where new variable names can be a
    ///
    fn create_sub_environment<'b>(&'b mut self) -> Box<BindingEnvironment + 'b> {
        Box::new(ChildBindingEnvironment {
            base_environment:   self,
            bindings:           HashMap::new()
        })
    }

    ///
    /// Allocates a new variable location in this binding (without assigning a name to it)
    ///
    fn allocate_location(&mut self) -> u32 {
        // If there's no parent, just allocate directly
        let allocation          = self.next_to_allocate;
        self.next_to_allocate   = allocation + 1;

        allocation
    }

    ///
    /// Allocates a new variable
    ///
    fn allocate_variable(&mut self, name: &str) -> Result<u32, BindingError> {
        if self.bindings.contains_key(name) {
            // Variable name is already taken
            Err(BindingError::AlreadyInUse)
        } else {
            // Can assign this location to value
            let allocation = self.allocate_location();
            self.bindings.insert(String::from(name), allocation);

            Ok(allocation)
        }
    }

    ///
    /// Looks up a name in this binding environment
    ///
    fn lookup(&self, name: &str) -> BindingResult {
        if let Some(variable) = self.bindings.get(name) {
            // Try to retrieve as a variable directly from this environment
            BindingResult::Variable(*variable)
        } else {
            // Try to retrieve from the environment
            let tool_or_error = self.environment.get_json_tool(name);

            match tool_or_error {
                Ok(tool)    => BindingResult::Tool(tool),
                Err(error)  => BindingResult::Error(error)
            }
        }
    }

    ///
    /// Returns the number of variables used in this environment
    ///
    fn get_number_of_variables(&self) -> u32 {
        self.next_to_allocate
    }
}

impl<'a> BindingEnvironment for ChildBindingEnvironment<'a> {
    fn allocate_location(&mut self) -> u32 {
        self.base_environment.allocate_location()
    }

    fn allocate_variable(&mut self, name: &str) -> Result<u32, BindingError> {
        if self.bindings.contains_key(name) {
            // Variable name is already taken
            Err(BindingError::AlreadyInUse)
        } else {
            // Can assign this location to value
            let allocation = self.allocate_location();
            self.bindings.insert(String::from(name), allocation);

            Ok(allocation)
        }
    }

    fn lookup(&self, name: &str) -> BindingResult {
        if let Some(variable) = self.bindings.get(name) {
            BindingResult::Variable(*variable)
        } else {
            self.base_environment.lookup(name)
        }
    }

    fn get_number_of_variables(&self) -> u32 {
        self.base_environment.get_number_of_variables()
    }

    fn create_sub_environment<'b>(&'b mut self) -> Box<BindingEnvironment + 'b> {
        Box::new(ChildBindingEnvironment {
            base_environment:   self,
            bindings:           HashMap::new()
        })
    }
}

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

    #[test]
    fn can_allocate_location() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_location() == 0);
    }

    #[test]
    fn can_allocate_many_locations() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_location() == 0);
        assert!(binding.allocate_location() == 1);
        assert!(binding.allocate_location() == 2);
    }

    #[test]
    fn can_get_number_of_variables() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_location();
        binding.allocate_location();
        binding.allocate_location();

        assert!(binding.get_number_of_variables() == 3);

        binding.allocate_location();

        assert!(binding.get_number_of_variables() == 4);
    }

    #[test]
    fn allocating_locations_in_child_environments_also_does_in_parent() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_location() == 0);

        {
            let mut child_environment = binding.create_sub_environment();

            assert!(child_environment.allocate_location() == 1);
        }

        assert!(binding.allocate_location() == 2);
    }

    #[test]
    fn can_allocate_variable_name() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_variable("test") == Ok(0));
    }

    #[test]
    fn cannot_allocate_variable_name_twice() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_variable("test") == Ok(0));
        assert!(binding.allocate_variable("test") == Err(BindingError::AlreadyInUse));
    }

    #[test]
    fn can_lookup_variable_name() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_variable("test");

        assert!(match binding.lookup("test") { BindingResult::Variable(v) => v == 0, _ => false });
    }

    #[test]
    fn can_lookup_many_variable_names() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_variable("test1");
        binding.allocate_variable("test2");
        binding.allocate_variable("test3");

        assert!(match binding.lookup("test1") { BindingResult::Variable(v) => v == 0, _ => false });
        assert!(match binding.lookup("test2") { BindingResult::Variable(v) => v == 1, _ => false });
        assert!(match binding.lookup("test3") { BindingResult::Variable(v) => v == 2, _ => false });
    }

    #[test]
    fn can_lookup_tool_name() {
        let tool_environment = DynamicEnvironment::new();
        tool_environment.define("test", Box::new(make_pure_tool(|_: ()| "Success")));

        let mut binding = BindingEnvironment::new(&tool_environment);

        assert!(match binding.lookup("test") { BindingResult::Tool(_) => true, _ => false });
    }

    #[test]
    fn variable_name_has_precedence_over_tool() {
        let tool_environment = DynamicEnvironment::new();
        tool_environment.define("test", Box::new(make_pure_tool(|_: ()| "Success")));

        let mut binding = BindingEnvironment::new(&tool_environment);

        binding.allocate_variable("test");

        assert!(match binding.lookup("test") { BindingResult::Variable(v) => v == 0, _ => false });
    }
}
<commit_msg>Add some missing tests for the child environment stuff<commit_after>use std::result::Result;
use std::collections::HashMap;

use gossyp_base::RetrieveToolError;
use gossyp_base::Environment;
use gossyp_base::Tool;

///
/// Errors that can occur when binding a variable
///
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
pub enum BindingError {
    /// The requested variable name is already in use
    AlreadyInUse,
}

///
/// Result of binding to an environment
///
pub enum BindingResult {
    /// Name maps to a variable
    Variable(u32),

    /// Name maps to a tool in the external environment
    Tool(Box<Tool>),

    /// Got an error while mapping a tool (binding isn't a tool or a variable)
    Error(RetrieveToolError)
}

///
/// A binding environment can be used to allocate variable values that will be used
/// during execution of a script.
///
struct BaseBindingEnvironment<'a> {
    /// The external environment that contains tools we can bind to
    environment: &'a Environment,

    /// The next variable value that will be alllocated
    next_to_allocate: u32,

    /// The current set of binding allocations
    bindings: HashMap<String, u32>
}

///
/// A child environment for a base environment
///
struct ChildBindingEnvironment<'a> {
    /// The base binding environment that this child environment is for
    base_environment: &'a mut BindingEnvironment,

    /// The current set of binding allocations
    bindings: HashMap<String, u32>
}

///
/// Trait implemented by objects that represent a binding environment
///
pub trait BindingEnvironment {
    ///
    /// Allocates a variable location without assigning a name
    ///
    fn allocate_location(&mut self) -> u32;

    ///
    /// Allocates a variable location with an assigned name (which must not
    /// already be in use)
    ///
    fn allocate_variable(&mut self, name: &str) -> Result<u32, BindingError>;

    ///
    /// Looks up a variable location by name
    ///
    fn lookup(&self, name: &str) -> BindingResult;

    ///
    /// Returns the total number of variables allocated for this environment
    ///
    fn get_number_of_variables(&self) -> u32;

    ///
    /// Creates a sub environment
    ///
    /// This allows names to be re-used with new variables, but existing variables
    /// will continue to refer to their current locations
    ///
    fn create_sub_environment<'a>(&'a mut self) -> Box<BindingEnvironment + 'a>;
}

impl BindingEnvironment {
    ///
    /// Creates a new binding environment. New variables will be mapped from 0
    ///
    pub fn new<'a>(environment: &'a Environment) -> Box<BindingEnvironment+'a> {
        Box::new(BaseBindingEnvironment {
            environment:        environment,
            next_to_allocate:   0,
            bindings:           HashMap::new()
        })
    }
}

impl<'a> BindingEnvironment for BaseBindingEnvironment<'a> {
    ///
    /// Creates a new sub-environment, where new variable names can be a
    ///
    fn create_sub_environment<'b>(&'b mut self) -> Box<BindingEnvironment + 'b> {
        Box::new(ChildBindingEnvironment {
            base_environment:   self,
            bindings:           HashMap::new()
        })
    }

    ///
    /// Allocates a new variable location in this binding (without assigning a name to it)
    ///
    fn allocate_location(&mut self) -> u32 {
        // If there's no parent, just allocate directly
        let allocation          = self.next_to_allocate;
        self.next_to_allocate   = allocation + 1;

        allocation
    }

    ///
    /// Allocates a new variable
    ///
    fn allocate_variable(&mut self, name: &str) -> Result<u32, BindingError> {
        if self.bindings.contains_key(name) {
            // Variable name is already taken
            Err(BindingError::AlreadyInUse)
        } else {
            // Can assign this location to value
            let allocation = self.allocate_location();
            self.bindings.insert(String::from(name), allocation);

            Ok(allocation)
        }
    }

    ///
    /// Looks up a name in this binding environment
    ///
    fn lookup(&self, name: &str) -> BindingResult {
        if let Some(variable) = self.bindings.get(name) {
            // Try to retrieve as a variable directly from this environment
            BindingResult::Variable(*variable)
        } else {
            // Try to retrieve from the environment
            let tool_or_error = self.environment.get_json_tool(name);

            match tool_or_error {
                Ok(tool)    => BindingResult::Tool(tool),
                Err(error)  => BindingResult::Error(error)
            }
        }
    }

    ///
    /// Returns the number of variables used in this environment
    ///
    fn get_number_of_variables(&self) -> u32 {
        self.next_to_allocate
    }
}

impl<'a> BindingEnvironment for ChildBindingEnvironment<'a> {
    fn allocate_location(&mut self) -> u32 {
        self.base_environment.allocate_location()
    }

    fn allocate_variable(&mut self, name: &str) -> Result<u32, BindingError> {
        if self.bindings.contains_key(name) {
            // Variable name is already taken
            Err(BindingError::AlreadyInUse)
        } else {
            // Can assign this location to value
            let allocation = self.allocate_location();
            self.bindings.insert(String::from(name), allocation);

            Ok(allocation)
        }
    }

    fn lookup(&self, name: &str) -> BindingResult {
        if let Some(variable) = self.bindings.get(name) {
            BindingResult::Variable(*variable)
        } else {
            self.base_environment.lookup(name)
        }
    }

    fn get_number_of_variables(&self) -> u32 {
        self.base_environment.get_number_of_variables()
    }

    fn create_sub_environment<'b>(&'b mut self) -> Box<BindingEnvironment + 'b> {
        Box::new(ChildBindingEnvironment {
            base_environment:   self,
            bindings:           HashMap::new()
        })
    }
}

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

    #[test]
    fn can_allocate_location() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_location() == 0);
    }

    #[test]
    fn can_allocate_many_locations() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_location() == 0);
        assert!(binding.allocate_location() == 1);
        assert!(binding.allocate_location() == 2);
    }

    #[test]
    fn can_get_number_of_variables() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_location();
        binding.allocate_location();
        binding.allocate_location();

        assert!(binding.get_number_of_variables() == 3);

        binding.allocate_location();

        assert!(binding.get_number_of_variables() == 4);
    }

    #[test]
    fn allocating_locations_in_child_environments_also_does_in_parent() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_location() == 0);

        {
            let mut child_environment = binding.create_sub_environment();

            assert!(child_environment.allocate_location() == 1);
        }

        assert!(binding.allocate_location() == 2);
    }

    #[test]
    fn can_reallocate_variable_name_in_child_environment() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_variable("test");
        assert!(match binding.lookup("test") { BindingResult::Variable(0) => true, _ => false });

        {
            let mut child_environment = binding.create_sub_environment();
            assert!(child_environment.allocate_variable("test") == Ok(1));
        }

        assert!(match binding.lookup("test") { BindingResult::Variable(0) => true, _ => false });
    }

    #[test]
    fn child_environment_lookup_falls_through_to_parent() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_variable("test1");
        binding.allocate_variable("test2");
        assert!(match binding.lookup("test1") { BindingResult::Variable(0) => true, _ => false });
        assert!(match binding.lookup("test2") { BindingResult::Variable(1) => true, _ => false });

        {
            let mut child_environment = binding.create_sub_environment();
            assert!(child_environment.allocate_variable("test1") == Ok(2));

            assert!(match child_environment.lookup("test1") { BindingResult::Variable(2) => true, _ => false });
            assert!(match child_environment.lookup("test2") { BindingResult::Variable(1) => true, _ => false });
        }

        assert!(match binding.lookup("test1") { BindingResult::Variable(0) => true, _ => false });
        assert!(match binding.lookup("test2") { BindingResult::Variable(1) => true, _ => false });
    }

    #[test]
    fn can_allocate_variable_name() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_variable("test") == Ok(0));
    }

    #[test]
    fn cannot_allocate_variable_name_twice() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        assert!(binding.allocate_variable("test") == Ok(0));
        assert!(binding.allocate_variable("test") == Err(BindingError::AlreadyInUse));
    }

    #[test]
    fn can_lookup_variable_name() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_variable("test");

        assert!(match binding.lookup("test") { BindingResult::Variable(v) => v == 0, _ => false });
    }

    #[test]
    fn can_lookup_many_variable_names() {
        let empty_environment   = EmptyEnvironment::new();
        let mut binding         = BindingEnvironment::new(&empty_environment);

        binding.allocate_variable("test1");
        binding.allocate_variable("test2");
        binding.allocate_variable("test3");

        assert!(match binding.lookup("test1") { BindingResult::Variable(v) => v == 0, _ => false });
        assert!(match binding.lookup("test2") { BindingResult::Variable(v) => v == 1, _ => false });
        assert!(match binding.lookup("test3") { BindingResult::Variable(v) => v == 2, _ => false });
    }

    #[test]
    fn can_lookup_tool_name() {
        let tool_environment = DynamicEnvironment::new();
        tool_environment.define("test", Box::new(make_pure_tool(|_: ()| "Success")));

        let mut binding = BindingEnvironment::new(&tool_environment);

        assert!(match binding.lookup("test") { BindingResult::Tool(_) => true, _ => false });
    }

    #[test]
    fn variable_name_has_precedence_over_tool() {
        let tool_environment = DynamicEnvironment::new();
        tool_environment.define("test", Box::new(make_pure_tool(|_: ()| "Success")));

        let mut binding = BindingEnvironment::new(&tool_environment);

        binding.allocate_variable("test");

        assert!(match binding.lookup("test") { BindingResult::Variable(v) => v == 0, _ => false });
    }
}
<|endoftext|>


<commit_before>//! Support for "weak linkage" to symbols on Unix
//!
//! Some I/O operations we do in libstd require newer versions of OSes but we
//! need to maintain binary compatibility with older releases for now. In order
//! to use the new functionality when available we use this module for
//! detection.
//!
//! One option to use here is weak linkage, but that is unfortunately only
//! really workable on Linux. Hence, use dlsym to get the symbol value at
//! runtime. This is also done for compatibility with older versions of glibc,
//! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
//! we've been dynamically linked to the library the symbol comes from, but that
//! is currently always the case for things like libpthread/libc.
//!
//! A long time ago this used weak linkage for the __pthread_get_minstack
//! symbol, but that caused Debian to detect an unnecessarily strict versioned
//! dependency on libc6 (#23628).

use libc;

use ffi::CStr;
use marker;
use mem;
use sync::atomic::{AtomicUsize, Ordering};

macro_rules! weak {
    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
        static $name: ::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
            ::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
    )
}

pub struct Weak<F> {
    name: &'static str,
    addr: AtomicUsize,
    _marker: marker::PhantomData<F>,
}

impl<F> Weak<F> {
    pub const fn new(name: &'static str) -> Weak<F> {
        Weak {
            name,
            addr: AtomicUsize::new(1),
            _marker: marker::PhantomData,
        }
    }

    pub fn get(&self) -> Option<&F> {
        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
        unsafe {
            if self.addr.load(Ordering::SeqCst) == 1 {
                self.addr.store(fetch(self.name), Ordering::SeqCst);
            }
            if self.addr.load(Ordering::SeqCst) == 0 {
                None
            } else {
                mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr)
            }
        }
    }
}

unsafe fn fetch(name: &str) -> usize {
    let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
        Ok(cstr) => cstr,
        Err(..) => return 0,
    };
    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
}

#[cfg(not(target_os = "linux"))]
macro_rules! syscall {
    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
        unsafe fn $name($($arg_name: $t),*) -> $ret {
            use libc;
            use super::os;

            weak! { fn $name($($t),*) -> $ret }

            if let Some(fun) = $name.get() {
                fun($($arg_name),*)
            } else {
                os::set_errno(libc::ENOSYS);
                -1
            }
        }
    )
}

#[cfg(target_os = "linux")]
macro_rules! syscall {
    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
        unsafe fn $name($($arg_name:$t),*) -> $ret {
            // This looks like a hack, but concat_idents only accepts idents
            // (not paths).
            use libc::*;

            syscall(
                concat_idents!(SYS_, $name),
                $($arg_name as c_long),*
            ) as $ret
        }
    )
}
<commit_msg>Return without a reference in unix Weak::get()<commit_after>//! Support for "weak linkage" to symbols on Unix
//!
//! Some I/O operations we do in libstd require newer versions of OSes but we
//! need to maintain binary compatibility with older releases for now. In order
//! to use the new functionality when available we use this module for
//! detection.
//!
//! One option to use here is weak linkage, but that is unfortunately only
//! really workable on Linux. Hence, use dlsym to get the symbol value at
//! runtime. This is also done for compatibility with older versions of glibc,
//! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
//! we've been dynamically linked to the library the symbol comes from, but that
//! is currently always the case for things like libpthread/libc.
//!
//! A long time ago this used weak linkage for the __pthread_get_minstack
//! symbol, but that caused Debian to detect an unnecessarily strict versioned
//! dependency on libc6 (#23628).

use libc;

use ffi::CStr;
use marker;
use mem;
use sync::atomic::{AtomicUsize, Ordering};

macro_rules! weak {
    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
        static $name: ::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
            ::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
    )
}

pub struct Weak<F> {
    name: &'static str,
    addr: AtomicUsize,
    _marker: marker::PhantomData<F>,
}

impl<F> Weak<F> {
    pub const fn new(name: &'static str) -> Weak<F> {
        Weak {
            name,
            addr: AtomicUsize::new(1),
            _marker: marker::PhantomData,
        }
    }

    pub fn get(&self) -> Option<F> {
        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
        unsafe {
            if self.addr.load(Ordering::SeqCst) == 1 {
                self.addr.store(fetch(self.name), Ordering::SeqCst);
            }
            match self.addr.load(Ordering::SeqCst) {
                0 => None,
                addr => Some(mem::transmute_copy::<usize, F>(&addr)),
            }
        }
    }
}

unsafe fn fetch(name: &str) -> usize {
    let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
        Ok(cstr) => cstr,
        Err(..) => return 0,
    };
    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
}

#[cfg(not(target_os = "linux"))]
macro_rules! syscall {
    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
        unsafe fn $name($($arg_name: $t),*) -> $ret {
            use libc;
            use super::os;

            weak! { fn $name($($t),*) -> $ret }

            if let Some(fun) = $name.get() {
                fun($($arg_name),*)
            } else {
                os::set_errno(libc::ENOSYS);
                -1
            }
        }
    )
}

#[cfg(target_os = "linux")]
macro_rules! syscall {
    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
        unsafe fn $name($($arg_name:$t),*) -> $ret {
            // This looks like a hack, but concat_idents only accepts idents
            // (not paths).
            use libc::*;

            syscall(
                concat_idents!(SYS_, $name),
                $($arg_name as c_long),*
            ) as $ret
        }
    )
}
<|endoftext|>


<commit_before>macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);
<commit_msg>Add macro for common command setup<commit_after>macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

macro_rules! command (
  ($name: ident) => (
    {
      let args: $name::Arguments = Docopt::new($name::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      $name::run(&args)
    }
  );
);
<|endoftext|>


<commit_before>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::{
    alloc::Layout,
    cmp::min,
    convert::TryFrom,
    io,
    mem::{align_of, size_of},
    os::unix::io::RawFd,
};

use anyhow::anyhow;
use base::LayoutAllocation;

// Allocates a buffer to hold a `libc::cmsghdr` with `cap` bytes of data.
//
// Returns the `LayoutAllocation` for the buffer as well as the size of the allocation, which is
// guaranteed to be at least `size_of::<libc::cmsghdr>() + cap` bytes.
pub fn allocate_cmsg_buffer(cap: u32) -> anyhow::Result<(LayoutAllocation, usize)> {
    // Not sure why this is unsafe.
    let cmsg_cap = usize::try_from(unsafe { libc::CMSG_SPACE(cap) })
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
    let alloc = Layout::from_size_align(cmsg_cap, align_of::<libc::cmsghdr>())
        .map(LayoutAllocation::zeroed)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;

    Ok((alloc, cmsg_cap))
}

// Adds a control message with the file descriptors from `fds` to `msg`.
// Note: this doesn't append but expects no cmsg already set and puts `fds` as a
// single `cmsg` inside passed `msg`
//
// Returns the `LayoutAllocation` backing the control message.
pub fn add_fds_to_message(
    msg: &mut libc::msghdr,
    fds: &[RawFd],
) -> anyhow::Result<LayoutAllocation> {
    let fd_len = fds
        .len()
        .checked_mul(size_of::<RawFd>())
        .and_then(|l| u32::try_from(l).ok())
        .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidInput))?;

    let (cmsg_buffer, cmsg_cap) = allocate_cmsg_buffer(fd_len)?;

    if !msg.msg_control.is_null() {
        anyhow::bail!("msg already contains cmsg");
    }

    msg.msg_control = cmsg_buffer.as_ptr();
    msg.msg_controllen = cmsg_cap;

    unsafe {
        // Safety:
        // * CMSG_FIRSTHDR will either return a null pointer or a pointer to `msg.msg_control`.
        // * `msg.msg_control` is properly aligned because `cmsg_buffer` is properly aligned.
        // * The buffer is zeroed, which is a valid bit-pattern for `libc::cmsghdr`.
        // * The reference does not escape this function.
        let cmsg = libc::CMSG_FIRSTHDR(msg).as_mut().unwrap();
        cmsg.cmsg_len = libc::CMSG_LEN(fd_len) as libc::size_t;
        cmsg.cmsg_level = libc::SOL_SOCKET;
        cmsg.cmsg_type = libc::SCM_RIGHTS;

        // Safety: `libc::CMSG_DATA(cmsg)` and `fds` are valid for `fd_len` bytes of memory.
        libc::memcpy(
            libc::CMSG_DATA(cmsg).cast(),
            fds.as_ptr().cast(),
            fd_len as usize,
        );
    }

    Ok(cmsg_buffer)
}

// Copies file descriptors from the control message in `msg` into `fds`.
//
// Returns the number of file descriptors that were copied from `msg`.
pub fn take_fds_from_message(msg: &libc::msghdr, fds: &mut [RawFd]) -> anyhow::Result<usize> {
    let cap = fds
        .len()
        .checked_mul(size_of::<RawFd>())
        .ok_or_else(|| anyhow!(io::Error::from(io::ErrorKind::InvalidInput)))?;

    let mut rem = cap;
    let mut fd_pos = 0;
    unsafe {
        let mut cmsg = libc::CMSG_FIRSTHDR(msg);

        // Safety:
        // * CMSG_FIRSTHDR will either return a null pointer or a pointer to `msg.msg_control`.
        // * `msg.msg_control` is properly aligned because it was allocated by `allocate_cmsg_buffer`.
        // * The buffer was zero-initialized, which is a valid bit-pattern for `libc::cmsghdr`.
        // * The reference does not escape this function.
        while let Some(current) = cmsg.as_ref() {
            if current.cmsg_level != libc::SOL_SOCKET || current.cmsg_type != libc::SCM_RIGHTS {
                cmsg = libc::CMSG_NXTHDR(msg, cmsg);
                continue;
            }

            let data_len = min(current.cmsg_len - libc::CMSG_LEN(0) as usize, rem);

            // Safety: `fds` and `libc::CMSG_DATA(cmsg)` are valid for `data_len` bytes of memory.
            libc::memcpy(
                fds[fd_pos..].as_mut_ptr().cast(),
                libc::CMSG_DATA(cmsg).cast(),
                data_len,
            );
            rem -= data_len;
            fd_pos += data_len / size_of::<RawFd>();
            if rem == 0 {
                break;
            }

            cmsg = libc::CMSG_NXTHDR(msg, cmsg);
        }
    }

    Ok((cap - rem) / size_of::<RawFd>())
}

#[cfg(test)]
mod tests {
    use std::ptr;

    use super::*;

    #[test]
    #[cfg(not(target_arch = "arm"))]
    fn test_add_fds_to_message() {
        let buf = [0xEAu8, 0xDD, 0xAA, 0xCC];
        let mut iov = libc::iovec {
            iov_base: buf.as_ptr() as *const libc::c_void as *mut libc::c_void,
            iov_len: buf.len() as libc::size_t,
        };

        let fds = [0xDE, 0xAD, 0xBE, 0xEF];
        let mut msg = libc::msghdr {
            msg_name: ptr::null_mut(),
            msg_namelen: 0,
            msg_iov: &mut iov,
            msg_iovlen: 1,
            msg_flags: 0,
            msg_control: ptr::null_mut(),
            msg_controllen: 0,
        };

        let cmsg_buffer = add_fds_to_message(&mut msg, &fds[..]).unwrap();
        let expected_cmsg = [
            32u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0xDE, 0, 0, 0, 0xAD, 0, 0, 0, 0xBE,
            0, 0, 0, 0xEF, 0, 0, 0,
        ];
        assert_eq!(unsafe { cmsg_buffer.as_slice::<u8>(9999) }, &expected_cmsg);
        assert_eq!(msg.msg_controllen, unsafe {
            cmsg_buffer.as_slice::<u8>(9999).len()
        });
        assert_eq!(msg.msg_control, cmsg_buffer.as_ptr());

        let mut extracted_fds = [0x0i32; 4];

        assert_eq!(
            4,
            take_fds_from_message(&msg, &mut extracted_fds[..]).unwrap()
        );

        assert_eq!(extracted_fds, fds);
    }

    #[test]
    #[cfg(not(target_arch = "arm"))]
    fn test_take_fds_from_message() {
        let buf = [0xEAu8, 0xDD, 0xAA, 0xCC];
        let mut iov = libc::iovec {
            iov_base: buf.as_ptr() as *const libc::c_void as *mut libc::c_void,
            iov_len: buf.len() as libc::size_t,
        };

        let mut cmsg = [
            32u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0xDE, 0, 0, 0, 0xAD, 0, 0, 0, 0xBE,
            0, 0, 0, 0xEF, 0, 0, 0, 32u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0xDE, 0, 0,
            0, 0xAD, 0, 0, 0, 0xBE, 0, 0, 0, 0xEF, 0, 0, 0,
        ];

        let msg = libc::msghdr {
            msg_name: ptr::null_mut(),
            msg_namelen: 0,
            msg_iov: &mut iov,
            msg_iovlen: 1,
            msg_flags: 0,
            msg_control: cmsg.as_mut_ptr() as *mut libc::c_void,
            msg_controllen: cmsg.len(),
        };

        let mut extracted_fds = [0x0i32; 9];
        assert_eq!(take_fds_from_message(&msg, &mut extracted_fds).unwrap(), 8);
        assert_eq!(
            extracted_fds,
            [0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00]
        );
    }
}
<commit_msg>Make the mod not-arm only<commit_after>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::{
    alloc::Layout,
    cmp::min,
    convert::TryFrom,
    io,
    mem::{align_of, size_of},
    os::unix::io::RawFd,
};

use anyhow::anyhow;
use base::LayoutAllocation;

// Allocates a buffer to hold a `libc::cmsghdr` with `cap` bytes of data.
//
// Returns the `LayoutAllocation` for the buffer as well as the size of the allocation, which is
// guaranteed to be at least `size_of::<libc::cmsghdr>() + cap` bytes.
pub fn allocate_cmsg_buffer(cap: u32) -> anyhow::Result<(LayoutAllocation, usize)> {
    // Not sure why this is unsafe.
    let cmsg_cap = usize::try_from(unsafe { libc::CMSG_SPACE(cap) })
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
    let alloc = Layout::from_size_align(cmsg_cap, align_of::<libc::cmsghdr>())
        .map(LayoutAllocation::zeroed)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;

    Ok((alloc, cmsg_cap))
}

// Adds a control message with the file descriptors from `fds` to `msg`.
// Note: this doesn't append but expects no cmsg already set and puts `fds` as a
// single `cmsg` inside passed `msg`
//
// Returns the `LayoutAllocation` backing the control message.
pub fn add_fds_to_message(
    msg: &mut libc::msghdr,
    fds: &[RawFd],
) -> anyhow::Result<LayoutAllocation> {
    let fd_len = fds
        .len()
        .checked_mul(size_of::<RawFd>())
        .and_then(|l| u32::try_from(l).ok())
        .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidInput))?;

    let (cmsg_buffer, cmsg_cap) = allocate_cmsg_buffer(fd_len)?;

    if !msg.msg_control.is_null() {
        anyhow::bail!("msg already contains cmsg");
    }

    msg.msg_control = cmsg_buffer.as_ptr();
    msg.msg_controllen = cmsg_cap;

    unsafe {
        // Safety:
        // * CMSG_FIRSTHDR will either return a null pointer or a pointer to `msg.msg_control`.
        // * `msg.msg_control` is properly aligned because `cmsg_buffer` is properly aligned.
        // * The buffer is zeroed, which is a valid bit-pattern for `libc::cmsghdr`.
        // * The reference does not escape this function.
        let cmsg = libc::CMSG_FIRSTHDR(msg).as_mut().unwrap();
        cmsg.cmsg_len = libc::CMSG_LEN(fd_len) as libc::size_t;
        cmsg.cmsg_level = libc::SOL_SOCKET;
        cmsg.cmsg_type = libc::SCM_RIGHTS;

        // Safety: `libc::CMSG_DATA(cmsg)` and `fds` are valid for `fd_len` bytes of memory.
        libc::memcpy(
            libc::CMSG_DATA(cmsg).cast(),
            fds.as_ptr().cast(),
            fd_len as usize,
        );
    }

    Ok(cmsg_buffer)
}

// Copies file descriptors from the control message in `msg` into `fds`.
//
// Returns the number of file descriptors that were copied from `msg`.
pub fn take_fds_from_message(msg: &libc::msghdr, fds: &mut [RawFd]) -> anyhow::Result<usize> {
    let cap = fds
        .len()
        .checked_mul(size_of::<RawFd>())
        .ok_or_else(|| anyhow!(io::Error::from(io::ErrorKind::InvalidInput)))?;

    let mut rem = cap;
    let mut fd_pos = 0;
    unsafe {
        let mut cmsg = libc::CMSG_FIRSTHDR(msg);

        // Safety:
        // * CMSG_FIRSTHDR will either return a null pointer or a pointer to `msg.msg_control`.
        // * `msg.msg_control` is properly aligned because it was allocated by `allocate_cmsg_buffer`.
        // * The buffer was zero-initialized, which is a valid bit-pattern for `libc::cmsghdr`.
        // * The reference does not escape this function.
        while let Some(current) = cmsg.as_ref() {
            if current.cmsg_level != libc::SOL_SOCKET || current.cmsg_type != libc::SCM_RIGHTS {
                cmsg = libc::CMSG_NXTHDR(msg, cmsg);
                continue;
            }

            let data_len = min(current.cmsg_len - libc::CMSG_LEN(0) as usize, rem);

            // Safety: `fds` and `libc::CMSG_DATA(cmsg)` are valid for `data_len` bytes of memory.
            libc::memcpy(
                fds[fd_pos..].as_mut_ptr().cast(),
                libc::CMSG_DATA(cmsg).cast(),
                data_len,
            );
            rem -= data_len;
            fd_pos += data_len / size_of::<RawFd>();
            if rem == 0 {
                break;
            }

            cmsg = libc::CMSG_NXTHDR(msg, cmsg);
        }
    }

    Ok((cap - rem) / size_of::<RawFd>())
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
mod tests {
    use std::ptr;

    use super::*;

    #[test]
    fn test_add_fds_to_message() {
        let buf = [0xEAu8, 0xDD, 0xAA, 0xCC];
        let mut iov = libc::iovec {
            iov_base: buf.as_ptr() as *const libc::c_void as *mut libc::c_void,
            iov_len: buf.len() as libc::size_t,
        };

        let fds = [0xDE, 0xAD, 0xBE, 0xEF];
        let mut msg = libc::msghdr {
            msg_name: ptr::null_mut(),
            msg_namelen: 0,
            msg_iov: &mut iov,
            msg_iovlen: 1,
            msg_flags: 0,
            msg_control: ptr::null_mut(),
            msg_controllen: 0,
        };

        let cmsg_buffer = add_fds_to_message(&mut msg, &fds[..]).unwrap();
        let expected_cmsg = [
            32u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0xDE, 0, 0, 0, 0xAD, 0, 0, 0, 0xBE,
            0, 0, 0, 0xEF, 0, 0, 0,
        ];
        assert_eq!(unsafe { cmsg_buffer.as_slice::<u8>(9999) }, &expected_cmsg);
        assert_eq!(msg.msg_controllen, unsafe {
            cmsg_buffer.as_slice::<u8>(9999).len()
        });
        assert_eq!(msg.msg_control, cmsg_buffer.as_ptr());

        let mut extracted_fds = [0x0i32; 4];

        assert_eq!(
            4,
            take_fds_from_message(&msg, &mut extracted_fds[..]).unwrap()
        );

        assert_eq!(extracted_fds, fds);
    }

    #[test]
    fn test_take_fds_from_message() {
        let buf = [0xEAu8, 0xDD, 0xAA, 0xCC];
        let mut iov = libc::iovec {
            iov_base: buf.as_ptr() as *const libc::c_void as *mut libc::c_void,
            iov_len: buf.len() as libc::size_t,
        };

        let mut cmsg = [
            32u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0xDE, 0, 0, 0, 0xAD, 0, 0, 0, 0xBE,
            0, 0, 0, 0xEF, 0, 0, 0, 32u8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0xDE, 0, 0,
            0, 0xAD, 0, 0, 0, 0xBE, 0, 0, 0, 0xEF, 0, 0, 0,
        ];

        let msg = libc::msghdr {
            msg_name: ptr::null_mut(),
            msg_namelen: 0,
            msg_iov: &mut iov,
            msg_iovlen: 1,
            msg_flags: 0,
            msg_control: cmsg.as_mut_ptr() as *mut libc::c_void,
            msg_controllen: cmsg.len(),
        };

        let mut extracted_fds = [0x0i32; 9];
        assert_eq!(take_fds_from_message(&msg, &mut extracted_fds).unwrap(), 8);
        assert_eq!(
            extracted_fds,
            [0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00]
        );
    }
}
<|endoftext|>


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

//! A wrapper around any Reader to treat it as an RNG.

use Rng;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(~[1,2,3,4,5,6,7,8]));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    priv reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read(v) {
            Ok(n) if n == v.len() => return,
            Ok(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \
                            read {} out of {} bytes.", n, v.len()),
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

#[cfg(test)]
mod test {
    use super::ReaderRng;
    use std::io::MemReader;
    use std::cast;
    use Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u64, 2u64, 3u64];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u64(), 1);
        assert_eq!(rng.next_u64(), 2);
        assert_eq!(rng.next_u64(), 3);
    }
    #[test]
    fn test_reader_rng_u32() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u32, 2u32, 3u32];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u32(), 1);
        assert_eq!(rng.next_u32(), 2);
        assert_eq!(rng.next_u32(), 3);
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_owned()));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(~[]));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<commit_msg>auto merge of #13049 : alexcrichton/rust/io-fill, r=huonw<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around any Reader to treat it as an RNG.

use Rng;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(~[1,2,3,4,5,6,7,8]));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    priv reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.fill(v) {
            Ok(()) => {}
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

#[cfg(test)]
mod test {
    use super::ReaderRng;
    use std::io::MemReader;
    use std::cast;
    use Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u64, 2u64, 3u64];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u64(), 1);
        assert_eq!(rng.next_u64(), 2);
        assert_eq!(rng.next_u64(), 3);
    }
    #[test]
    fn test_reader_rng_u32() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u32, 2u32, 3u32];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u32(), 1);
        assert_eq!(rng.next_u32(), 2);
        assert_eq!(rng.next_u32(), 3);
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_owned()));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(~[]));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<|endoftext|>


<commit_before>use crypto::md5::Md5;
use crypto::digest::Digest;

const INPUT: &'static str = "bgvyzdsv";

fn first_n_zeroes(zeroes: usize) -> usize {
    let mut md5hasher = Md5::new();
    (0..)
        .find(|&i| {
            md5hasher.reset();
            md5hasher.input_str(&format!("{}{}", INPUT, i));
            md5hasher.result_str().chars().take(zeroes).all(|c| c == '0')
        })
        .unwrap()
}

pub fn main() {
    println!("Part 1: {}", first_n_zeroes(5));
    println!("Part 2: {}", first_n_zeroes(6));
}
<commit_msg>add test to rust day4<commit_after>use crypto::md5::Md5;
use crypto::digest::Digest;

const INPUT: &'static str = "bgvyzdsv";

fn first_n_zeroes(zeroes: usize) -> usize {
    let mut md5hasher = Md5::new();
    (0..)
        .find(|&i| {
            md5hasher.reset();
            md5hasher.input_str(&format!("{}{}", INPUT, i));
            md5hasher.result_str().chars().take(zeroes).all(|c| c == '0')
        })
        .unwrap()
}

pub fn main() {
    println!("Part 1: {}", first_n_zeroes(5));
    println!("Part 2: {}", first_n_zeroes(6));
}

#[test]
fn test() {
    assert_eq!(first_n_zeroes(5), 254575);
    assert_eq!(first_n_zeroes(6), 1038736);
}
<|endoftext|>


<commit_before>#![feature(unboxed_closures)]
#![feature(globs)]
#![feature(phase)]
#![feature(macro_rules)]
#[phase(plugin, link)]
extern crate log;
#[phase(plugin)]
extern crate wtftw_core;

extern crate wtftw_core;

use wtftw_core::window_system::*;
use wtftw_core::window_manager::*;
use wtftw_core::handlers::default::*;
use wtftw_core::config::*;
use wtftw_core::util::*;
use wtftw_core::layout::*;
use wtftw_core::layout::Direction::*;
use wtftw_core::layout::LayoutMessage::*;

#[no_mangle]
pub extern fn configure(_: &mut WindowManager, w: &WindowSystem, config: &mut Config) {
    let modm = MOD1MASK;

    config.general.mod_mask = modm;
    config.general.spacing = 0;
    config.general.border_color = 0x3f3f4c;
    config.general.focus_border_color = 0x525263;
    config.general.terminal = (String::from_str("urxvt"), String::from_str(""));
    config.general.layout = LayoutCollection::new(vec!(
        GapLayout::new(16, AvoidStrutsLayout::new(vec!(Direction::Up), ResizableTallLayout::new())),
        GapLayout::new(16, AvoidStrutsLayout::new(vec!(Direction::Up), MirrorLayout::new(ResizableTallLayout::new()))),
        box FullLayout));

    config.general.tags = (vec!("1: term", "2: web", "3: code",
                                "4: media", "5: steam", "6: latex",
                                "7: music", "8: im", "9: rest"))
        .into_iter().map(String::from_str).collect();

    // Register key handlers

    // Some standard key handlers for starting, restarting, etc.
    add_key_handler_str!(config, w, "q",      modm | SHIFTMASK, exit);
    add_key_handler_str!(config, w, "q",      modm,             restart);
    add_key_handler_str!(config, w, "Return", modm | SHIFTMASK, start_terminal);
    add_key_handler_str!(config, w, "p",      modm,             start_launcher);

    // Focus and window movement
    add_key_handler_str!(config, w, "j", modm, |&: m, w, c| m.windows(w, c, |x| x.focus_down()));
    add_key_handler_str!(config, w, "k", modm, |&: m, w, c| m.windows(w, c, |x| x.focus_up()));
    add_key_handler_str!(config, w, "j", modm | SHIFTMASK, |&: m, w, c| m.windows(w, c, |x| x.swap_down()));
    add_key_handler_str!(config, w, "k", modm | SHIFTMASK, |&: m, w, c| m.windows(w, c, |x| x.swap_up()));
    add_key_handler_str!(config, w, "Return", modm, |&: m, w, c| m.windows(w, c, |x| x.swap_master()));

    // Layout messages
    add_key_handler_str!(config, w, "h", modm,
            |&: m, w, c| { m.send_layout_message(LayoutMessage::Decrease).reapply_layout(w, c) });
    add_key_handler_str!(config, w, "l", modm,
            |&: m, w, c| { m.send_layout_message(LayoutMessage::Increase).reapply_layout(w, c) });
    add_key_handler_str!(config, w, "comma", modm,
            |&: m, w, c| { m.send_layout_message(LayoutMessage::IncreaseMaster).reapply_layout(w, c) });
    add_key_handler_str!(config, w, "period", modm,
            |&: m, w, c| m.send_layout_message(LayoutMessage::DecreaseMaster).reapply_layout(w, c));
    add_key_handler_str!(config, w, "space", modm,
            |&: m, w, c| m.send_layout_message(LayoutMessage::Next).reapply_layout(w, c));

    // Workspace switching and moving
    for i in range(1u, 10) {
        add_key_handler_str!(config, w, i.to_string().as_slice(), modm,
            move |&: m, w, c| switch_to_workspace(m, w, c, i - 1));

        add_key_handler_str!(config, w, i.to_string().as_slice(), modm | SHIFTMASK,
            move |&: m, w, c| move_window_to_workspace(m, w, c, i - 1));
    }

    // Media keys
    add_key_handler_str!(config, w, "j", modm | CONTROLMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%-")); w });
    add_key_handler_str!(config, w, "k", modm | CONTROLMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%+")); w });

    add_key_handler_code!(config, 0x1008ff11, NONEMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%-")); w });
    add_key_handler_code!(config, 0x1008ff13, NONEMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%+")); w });

    add_key_handler_code!(config, 0x1008ff02, NONEMASK,
            |&: w, _, _| { run("xbacklight", Some("+10")); w });
    add_key_handler_code!(config, 0x1008ff03, NONEMASK,
            |&: w, _, _| { run("xbacklight", Some("-10")); w });

    // Place specific applications on specific workspaces
    config.set_manage_hook(box |&: workspaces, window_system, window| {
                match window_system.get_class_name(window).as_slice() {
                    "MPlayer" => spawn_on(workspaces, window_system, window, 3),
                    "vlc"     => spawn_on(workspaces, window_system, window, 3),
                    _         => workspaces.clone()
                }
            });

    // Xmobar handling and formatting
    let mut xmobar = spawn_pipe(config, String::from_str("xmobar"),
                                Some(String::from_str("/home/wollwage/.xmonad/xmobar1.hs")));
    let tags = config.general.tags.clone();
    config.set_log_hook(box move |&mut: m, _| {
        let p = &mut xmobar;
        let tags = &tags;
        let workspaces = tags.clone().iter()
            .enumerate()
            .map(|(i, x)| if i as u32 == m.workspaces.current.workspace.id {
                format!("[<fc=#3279a8>{}</fc>] ", x)
            } else {
                format!("[{}] ", x)
            })
            .fold(String::from_str(""), |a, x| {
                let mut r = a.clone();
                r.push_str(x.as_slice());
                r
            });

        let content = format!("{} {}", workspaces, m.workspaces.current.workspace.layout.description());
        p.stdin.as_mut().unwrap().write_line(content.as_slice()).unwrap();
    });
}

<commit_msg>should fix issue Kintaro/wtftw#20<commit_after>#![feature(unboxed_closures)]
#![feature(globs)]
#![feature(phase)]
#![feature(macro_rules)]
#[phase(plugin, link)]
extern crate log;
#[phase(plugin)]
extern crate wtftw_core;

extern crate wtftw_core;

use wtftw_core::window_system::*;
use wtftw_core::window_manager::*;
use wtftw_core::handlers::default::*;
use wtftw_core::config::*;
use wtftw_core::util::*;
use wtftw_core::layout::*;
use wtftw_core::layout::Direction::*;
use wtftw_core::layout::LayoutMessage::*;

#[no_mangle]
pub extern fn configure(_: &mut WindowManager, w: &WindowSystem, config: &mut Config) {
    let modm = MOD1MASK;

    config.general.mod_mask = modm;
    config.general.spacing = 0;
    config.general.border_color = 0x3f3f4c;
    config.general.focus_border_color = 0x525263;
    config.general.terminal = (String::from_str("urxvt"), String::from_str(""));
    config.general.layout = LayoutCollection::new(vec!(
        GapLayout::new(16, AvoidStrutsLayout::new(vec!(Direction::Up), ResizableTallLayout::new())),
        GapLayout::new(16, AvoidStrutsLayout::new(vec!(Direction::Up),
MirrorLayout::new(ResizableTallLayout::new()))),
        box FullLayout));

    config.general.tags = (vec!("1: term", "2: web", "3: code",
                                "4: media", "5: steam", "6: latex",
                                "7: music", "8: im", "9: rest"))
        .into_iter().map(String::from_str).collect();

    // Register key handlers

    // Some standard key handlers for starting, restarting, etc.
    add_key_handler_str!(config, w, "q",      modm | SHIFTMASK, exit);
    add_key_handler_str!(config, w, "q",      modm,             restart);
    add_key_handler_str!(config, w, "Return", modm | SHIFTMASK, start_terminal);
    add_key_handler_str!(config, w, "p",      modm,             start_launcher);

    // Focus and window movement
    add_key_handler_str!(config, w, "j", modm, |&: m, w, c| m.windows(w, c, |x| x.focus_down()));
    add_key_handler_str!(config, w, "k", modm, |&: m, w, c| m.windows(w, c, |x| x.focus_up()));
    add_key_handler_str!(config, w, "j", modm | SHIFTMASK, |&: m, w, c| m.windows(w, c, |x|
x.swap_down()));
    add_key_handler_str!(config, w, "k", modm | SHIFTMASK, |&: m, w, c| m.windows(w, c, |x| x.swap_up()));
    add_key_handler_str!(config, w, "Return", modm, |&: m, w, c| m.windows(w, c, |x| x.swap_master()));

    // Layout messages
    add_key_handler_str!(config, w, "h", modm,
            |&: m, w, c| { m.send_layout_message(LayoutMessage::Decrease).reapply_layout(w, c) });
    add_key_handler_str!(config, w, "l", modm,
            |&: m, w, c| { m.send_layout_message(LayoutMessage::Increase).reapply_layout(w, c) });
    add_key_handler_str!(config, w, "comma", modm,
            |&: m, w, c| { m.send_layout_message(LayoutMessage::IncreaseMaster).reapply_layout(w, c) });
    add_key_handler_str!(config, w, "period", modm,
            |&: m, w, c| m.send_layout_message(LayoutMessage::DecreaseMaster).reapply_layout(w, c));
    add_key_handler_str!(config, w, "space", modm,
            |&: m, w, c| m.send_layout_message(LayoutMessage::Next).reapply_layout(w, c));

    // Workspace switching and moving
    for i in range(1u, 10) {
        add_key_handler_str!(config, w, i.to_string().as_slice(), modm,
            move |&: m, w, c| switch_to_workspace(m, w, c, i - 1));

        add_key_handler_str!(config, w, i.to_string().as_slice(), modm | SHIFTMASK,
            move |&: m, w, c| move_window_to_workspace(m, w, c, i - 1));
    }

    // Media keys
    add_key_handler_str!(config, w, "j", modm | CONTROLMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%-")); w });
    add_key_handler_str!(config, w, "k", modm | CONTROLMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%+")); w });

    add_key_handler_code!(config, 0x1008ff11, NONEMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%-")); w });
    add_key_handler_code!(config, 0x1008ff13, NONEMASK,
            |&: w, _, _| { run("amixer", Some("-q set Master 5%+")); w });

    add_key_handler_code!(config, 0x1008ff02, NONEMASK,
            |&: w, _, _| { run("xbacklight", Some("+10")); w });
    add_key_handler_code!(config, 0x1008ff03, NONEMASK,
            |&: w, _, _| { run("xbacklight", Some("-10")); w });

    // Place specific applications on specific workspaces
    config.set_manage_hook(box |&: workspaces, window_system, window| {
                match window_system.get_class_name(window).as_slice() {
                    "MPlayer" => spawn_on(workspaces, window_system, window, 3),
                    "vlc"     => spawn_on(workspaces, window_system, window, 3),
                    _         => workspaces.clone()
                }
            });

    // Xmobar handling and formatting
    let mut xmobar = spawn_pipe(config, String::from_str("xmobar"),
                                Some(String::from_str("/home/wollwage/.xmonad/xmobar1.hs")));
    let tags = config.general.tags.clone();
    config.set_log_hook(box move |&mut: m, _| {
        let p = &mut xmobar;
        let tags = &tags;
        let workspaces = tags.clone().iter()
            .enumerate()
            .map(|(i, x)| if i as u32 == m.workspaces.current.workspace.id {
                format!("[<fc=#3279a8>{}</fc>] ", x)
            } else {
                format!("[{}] ", x)
            })
            .fold(String::from_str(""), |a, x| {
                let mut r = a.clone();
                r.push_str(x.as_slice());
                r
            });

        let content = format!("{} {}", workspaces, m.workspaces.current.workspace.layout.description());
        match p.stdin.as_mut() {
            Some(pin) => match pin.write_line(content.as_slice()) {
                _ => ()
            },
            _ => ()
        }
    });
}

<|endoftext|>


<commit_before>use buffer::Buffer;
use buffer::gap_buffer::GapBuffer;
pub use self::group::OperationGroup;

pub mod group;

pub trait Operation {
    fn run(&mut self, &mut GapBuffer);
    fn reverse(&mut self, &mut GapBuffer);
}
<commit_msg>Add clone method to Operation trait.<commit_after>use buffer::Buffer;
use buffer::gap_buffer::GapBuffer;
pub use self::group::OperationGroup;

pub mod group;

pub trait Operation {
    fn run(&mut self, &mut GapBuffer);
    fn reverse(&mut self, &mut GapBuffer);
    fn clone(&self) -> Box<Operation>;
}
<|endoftext|>