<commit_before>use std::f32::consts;
use std::mem;

pub fn convert(input_lon: f32, input_lat: f32) -> (f32, f32) {
    let pi: f32 = consts::PI;
    //Convert input to degrees
    let lat_1: f32 = input_lat * pi / 180.;
    let lon_1: f32 = input_lon * pi / 180.;
    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a_1: f32 = 6378137.;
    let b_1: f32 = 6356752.3141;
    // The eccentricity (squared) of the GRS80 ellipsoid
    let e2_1: f32 = 1. - (b_1.powf(2.)) / (a_1.powf(2.));
    // Transverse radius of curvature
    let nu_1: f32 = a_1 / (1. - e2_1 * lat_1.sin().powf(2.)).sqrt();
    // Third spherical coordinate is 0, in this case
    let H: f32 = 0.;
    let x_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.cos();
    let y_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.sin();
    let z_1: f32 = ((1. - e2_1) * nu_1 + H) * lat_1.sin();

    // Perform Helmert transform (to go between Airy 1830 (_1) and GRS80 (_2))
    let small: f32 = 10.;
    let cst: f32 = 20.4894;
    let s: f32 =  cst * small.powf(-6.);
    // The translations along x, y, z axes respectively
    let tx: f32 = -446.448;
    let ty: f32 = 125.157;
    let tz: f32 = -542.060;
    // The rotations along x, y, z respectively, in seconds
    let rxs: f32 = -0.1502;
    let rys: f32 = -0.2470;
    let rzs: f32 = -0.8421;
    // In radians
    let rx: f32 = rxs * pi / (180. * 3600.);
    let ry: f32 = rys * pi / (180. * 3600.);
    let rz: f32 = rzs * pi / (180. * 3600.);
    // panic begins on line 46
    let x_2: f32 = tx + (1. + s) * x_1 + -rz * y_1 + ry * z_1;
    let y_2: f32 = ty + rz * x_1 + (1. + s) * y_1 + -rx * z_1;
    let z_2: f32 = tz + -ry * x_1 + rx * y_1 + (1. + s) * z_1;

    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a: f32 = 6377563.396;
    let b: f32 = 6356256.909;
    // The eccentricity of the Airy 1830 ellipsoid
    let e2: f32 = 1. - b.powf(2.) / a.powf(2.);
    let p: f32 = (x_2.powf(2.) + y_2.powf(2.)).sqrt();
    // Initial value
    let mut lat: f32 = z_2.atan2((p * (1. - e2)));
    let mut latold: f32 = 2. * pi;
    // this is cheating, but not sure how else to initialise nu
    let mut nu: f32 = 1.;
    // Latitude is obtained by iterative procedure
    while (lat - latold).abs() > small.powf(-16.) {
        mem::swap(&mut lat, &mut latold);
        nu = a / (1. - e2 * latold.sin().powf(2.)).sqrt();
        lat = (z_2 + e2 * nu * latold.sin()).atan2(p);
    };
    let lon: f32 = y_2.atan2(x_2);
    // Scale factor on the central meridian
    let F0: f32 = 0.9996012717;
    // Latitude of true origin (radians)
    let lat0: f32 = 49. * pi / 180.;
    // Longtitude of true origin and central meridian (radians)
    let lon0: f32 = -2. * pi / 180.;
    // Northing & easting of true origin (m)
    let N0: f32 = -100000.;
    let E0: f32 = 400000.;
    let n: f32 = (a - b) / (a + b);
    // Meridional radius of curvature
    let rho: f32 = a * F0 * (1. - e2) * (1. - e2 * lat.sin().powf(2.)).powf(-1.5);
    let eta2: f32 = nu * F0 / rho - 1.;

    let M1: f32 = (1. + n + (5. / 4.) * n.powf(2.) + (5. / 4.) * n.powf(3.)) * (lat - lat0);
    let M2: f32 = (3. * n + 3. * n.powf(2.) + (21. / 8.) * n.powf(3.)) * (lat - lat0).sin() * (lat + lat0).cos();
    let M3: f32 = ((15. / 8.) * n.powf(2.) + (15. / 8.) * n.powf(3.)) * (2. * (lat-lat0)).sin() * (2. * (lat + lat0)).cos();
    let M4: f32 = (35. / 24.) * n.powf(3.) * (3. * (lat - lat0)).sin() * (3. * (lat + lat0)).cos();
    let M: f32 = b * F0 * (M1 - M2 + M3 - M4);

    let I: f32 = M + N0;
    let II: f32 = nu * F0 * lat.sin() * lat.cos() / 2.;
    let III: f32 = nu * F0 * lat.sin() * lat.cos().powf(3.) * (5. - lat.tan().powf(2.) + 9. * eta2) / 24.;
    let IIIA: f32 = nu * F0 * lat.sin() * lat.cos().powf(5.) * (61. - 58. * lat.tan().powf(2.) + lat.tan().powf(4.)) / 720.;
    let IV: f32 = nu * F0 * lat.cos();
    let V: f32 = nu * F0 * lat.cos().powf(3.) * (nu / rho - lat.tan().powf(2.)) / 6.;
    let VI: f32 = nu * F0 * lat.cos().powf(5.) * (5. - 18. * lat.tan().powf(2.) + lat.tan().powf(4.) + 14. * eta2 - 58. * eta2 * lat.tan().powf(2.)) / 120.;
    let N: f32 = I + II * (lon - lon0).powf(2.) + III * (lon - lon0).powf(4.) + IIIA * (lon - lon0).powf(6.);
    let E: f32 = E0 + IV * (lon - lon0) + V * (lon - lon0).powf(3.) + VI * (lon - lon0).powf(5.);
    return (E, N);
}

#[test]
fn test_conversion() {
    // verified to be correct at http://www.bgs.ac.uk/data/webservices/convertForm.cfm
    assert_eq!((516275.96875, 173141.125), convert(-0.32824866, 51.44533267));
}
<commit_msg>Don't warn on non-snake-case variable names<commit_after>use std::f32::consts;
use std::mem;
#[allow(non_snake_case)]

pub fn convert(input_lon: f32, input_lat: f32) -> (f32, f32) {
    let pi: f32 = consts::PI;
    //Convert input to degrees
    let lat_1: f32 = input_lat * pi / 180.;
    let lon_1: f32 = input_lon * pi / 180.;
    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a_1: f32 = 6378137.;
    let b_1: f32 = 6356752.3141;
    // The eccentricity (squared) of the GRS80 ellipsoid
    let e2_1: f32 = 1. - (b_1.powf(2.)) / (a_1.powf(2.));
    // Transverse radius of curvature
    let nu_1: f32 = a_1 / (1. - e2_1 * lat_1.sin().powf(2.)).sqrt();
    // Third spherical coordinate is 0, in this case
    let H: f32 = 0.;
    let x_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.cos();
    let y_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.sin();
    let z_1: f32 = ((1. - e2_1) * nu_1 + H) * lat_1.sin();

    // Perform Helmert transform (to go between Airy 1830 (_1) and GRS80 (_2))
    let small: f32 = 10.;
    let cst: f32 = 20.4894;
    let s: f32 =  cst * small.powf(-6.);
    // The translations along x, y, z axes respectively
    let tx: f32 = -446.448;
    let ty: f32 = 125.157;
    let tz: f32 = -542.060;
    // The rotations along x, y, z respectively, in seconds
    let rxs: f32 = -0.1502;
    let rys: f32 = -0.2470;
    let rzs: f32 = -0.8421;
    // In radians
    let rx: f32 = rxs * pi / (180. * 3600.);
    let ry: f32 = rys * pi / (180. * 3600.);
    let rz: f32 = rzs * pi / (180. * 3600.);
    // panic begins on line 46
    let x_2: f32 = tx + (1. + s) * x_1 + -rz * y_1 + ry * z_1;
    let y_2: f32 = ty + rz * x_1 + (1. + s) * y_1 + -rx * z_1;
    let z_2: f32 = tz + -ry * x_1 + rx * y_1 + (1. + s) * z_1;

    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a: f32 = 6377563.396;
    let b: f32 = 6356256.909;
    // The eccentricity of the Airy 1830 ellipsoid
    let e2: f32 = 1. - b.powf(2.) / a.powf(2.);
    let p: f32 = (x_2.powf(2.) + y_2.powf(2.)).sqrt();
    // Initial value
    let mut lat: f32 = z_2.atan2((p * (1. - e2)));
    let mut latold: f32 = 2. * pi;
    // this is cheating, but not sure how else to initialise nu
    let mut nu: f32 = 1.;
    // Latitude is obtained by iterative procedure
    while (lat - latold).abs() > small.powf(-16.) {
        mem::swap(&mut lat, &mut latold);
        nu = a / (1. - e2 * latold.sin().powf(2.)).sqrt();
        lat = (z_2 + e2 * nu * latold.sin()).atan2(p);
    };
    let lon: f32 = y_2.atan2(x_2);
    // Scale factor on the central meridian
    let F0: f32 = 0.9996012717;
    // Latitude of true origin (radians)
    let lat0: f32 = 49. * pi / 180.;
    // Longtitude of true origin and central meridian (radians)
    let lon0: f32 = -2. * pi / 180.;
    // Northing & easting of true origin (m)
    let N0: f32 = -100000.;
    let E0: f32 = 400000.;
    let n: f32 = (a - b) / (a + b);
    // Meridional radius of curvature
    let rho: f32 = a * F0 * (1. - e2) * (1. - e2 * lat.sin().powf(2.)).powf(-1.5);
    let eta2: f32 = nu * F0 / rho - 1.;

    let M1: f32 = (1. + n + (5. / 4.) * n.powf(2.) + (5. / 4.) * n.powf(3.)) * (lat - lat0);
    let M2: f32 = (3. * n + 3. * n.powf(2.) + (21. / 8.) * n.powf(3.)) * (lat - lat0).sin() * (lat + lat0).cos();
    let M3: f32 = ((15. / 8.) * n.powf(2.) + (15. / 8.) * n.powf(3.)) * (2. * (lat-lat0)).sin() * (2. * (lat + lat0)).cos();
    let M4: f32 = (35. / 24.) * n.powf(3.) * (3. * (lat - lat0)).sin() * (3. * (lat + lat0)).cos();
    let M: f32 = b * F0 * (M1 - M2 + M3 - M4);

    let I: f32 = M + N0;
    let II: f32 = nu * F0 * lat.sin() * lat.cos() / 2.;
    let III: f32 = nu * F0 * lat.sin() * lat.cos().powf(3.) * (5. - lat.tan().powf(2.) + 9. * eta2) / 24.;
    let IIIA: f32 = nu * F0 * lat.sin() * lat.cos().powf(5.) * (61. - 58. * lat.tan().powf(2.) + lat.tan().powf(4.)) / 720.;
    let IV: f32 = nu * F0 * lat.cos();
    let V: f32 = nu * F0 * lat.cos().powf(3.) * (nu / rho - lat.tan().powf(2.)) / 6.;
    let VI: f32 = nu * F0 * lat.cos().powf(5.) * (5. - 18. * lat.tan().powf(2.) + lat.tan().powf(4.) + 14. * eta2 - 58. * eta2 * lat.tan().powf(2.)) / 120.;
    let N: f32 = I + II * (lon - lon0).powf(2.) + III * (lon - lon0).powf(4.) + IIIA * (lon - lon0).powf(6.);
    let E: f32 = E0 + IV * (lon - lon0) + V * (lon - lon0).powf(3.) + VI * (lon - lon0).powf(5.);
    return (E, N);
}

#[test]
fn test_conversion() {
    // verified to be correct at http://www.bgs.ac.uk/data/webservices/convertForm.cfm
    assert_eq!((516275.96875, 173141.125), convert(-0.32824866, 51.44533267));
}
<|endoftext|>


<commit_before>// Copyright © 2014, Simonas Kazlauskas <git@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.

#![feature(asm)]

extern crate rand;

use rand::Rng;
use std::result::Result;
mod util;

#[derive(Copy, Clone)]
pub enum Error {
    /// The processor does not support the instruction used in the generator.
    UnsupportedProcessor
}

/// A cryptographically secure pseudo-random number generator.
///
/// This generator is a viable replacement to any [std::rand] generator, however, since nobody has
/// audited Intel hardware yet, the usual disclaimers apply.
///
/// It is much faster than `OsRng` (and slower than `StdRng`), but is only supported on more recent
/// (since Ivy Bridge) Intel processors.
///
/// [std::rand]: http://doc.rust-lang.org/std/rand/index.html
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct RdRand(());

impl RdRand {
    /// Build a generator object. The function will only succeed if `rdrand` instruction can be
    /// successfully used.
    pub fn new() -> Result<RdRand, Error> {
        if util::is_intel() && util::has_rdrand() {
            return Ok(RdRand(()));
        } else {
            return Err(Error::UnsupportedProcessor);
        }
    }

    /// Generate a value.
    #[inline]
    fn gen_value<T>(&self) -> T {
        let var;
        unsafe {
            asm!("1: rdrand $0; jnc 1b;" : "=r"(var));
        }
        var
    }

    /// Generate a u16 value.
    pub fn next_u16(&self) -> u16 {
        self.gen_value()
    }
}

impl Rng for RdRand {
    fn next_u32(&mut self) -> u32 {
        self.gen_value()
    }

    fn next_u64(&mut self) -> u64 {
        self.gen_value()
    }
}

/// A random number generator suited to seed other pseudo-random generators.
///
/// This instruction currently is only available in Intel Broadwell processors.
///
/// Note: The implementation has not been tested due to the lack of hardware supporting the feature
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct RdSeed(());

impl RdSeed {
    pub fn new() -> Result<RdSeed, Error> {
        if util::is_intel() && util::has_rdseed() {
            return Ok(RdSeed(()));
        } else {
            return Err(Error::UnsupportedProcessor);
        }
    }

    /// Generate a value.
    #[inline]
    fn gen_value<T>(&self) -> T {
        let var;
        unsafe {
            asm!("1: rdseed $0; jnc 1b;" : "=r"(var));
        }
        var
    }

    /// Generate a u16 value.
    pub fn next_u16(&self) -> u16 {
        self.gen_value()
    }
}

impl Rng for RdSeed {
    fn next_u32(&mut self) -> u32 {
        self.gen_value()
    }

    fn next_u64(&mut self) -> u64 {
        self.gen_value()
    }
}

#[test]
fn rdrand_works() {
    let _ = RdRand::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}

#[test]
fn rdseed_works() {
    let _ = RdSeed::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}
<commit_msg>Add conversion from our Error to io::Error<commit_after>// Copyright © 2014, Simonas Kazlauskas <git@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.

#![feature(asm)]

extern crate rand;

use rand::Rng;
use std::result::Result;
mod util;

#[derive(Copy, Clone, Debug)]
pub enum Error {
    /// The processor does not support the instruction used in the generator.
    UnsupportedProcessor
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::UnsupportedProcessor => "processor does not support the instruction",
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
            &Error::UnsupportedProcessor => write!(f, "processor does not support the instruction")
        }
    }
}

impl From<Error> for ::std::io::Error {
    fn from(e: Error) -> ::std::io::Error {
        ::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))
    }
}

/// A cryptographically secure pseudo-random number generator.
///
/// This generator is a viable replacement to any [std::rand] generator, however, since nobody has
/// audited Intel hardware yet, the usual disclaimers apply.
///
/// It is much faster than `OsRng` (and slower than `StdRng`), but is only supported on more recent
/// (since Ivy Bridge) Intel processors.
///
/// [std::rand]: http://doc.rust-lang.org/std/rand/index.html
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct RdRand(());

impl RdRand {
    /// Build a generator object. The function will only succeed if `rdrand` instruction can be
    /// successfully used.
    pub fn new() -> Result<RdRand, Error> {
        if util::is_intel() && util::has_rdrand() {
            return Ok(RdRand(()));
        } else {
            return Err(Error::UnsupportedProcessor);
        }
    }

    /// Generate a value.
    #[inline]
    fn gen_value<T>(&self) -> T {
        let var;
        unsafe {
            asm!("1: rdrand $0; jnc 1b;" : "=r"(var));
        }
        var
    }

    /// Generate a u16 value.
    pub fn next_u16(&self) -> u16 {
        self.gen_value()
    }
}

impl Rng for RdRand {
    fn next_u32(&mut self) -> u32 {
        self.gen_value()
    }

    fn next_u64(&mut self) -> u64 {
        self.gen_value()
    }
}

/// A random number generator suited to seed other pseudo-random generators.
///
/// This instruction currently is only available in Intel Broadwell processors.
///
/// Note: The implementation has not been tested due to the lack of hardware supporting the feature
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct RdSeed(());

impl RdSeed {
    pub fn new() -> Result<RdSeed, Error> {
        if util::is_intel() && util::has_rdseed() {
            return Ok(RdSeed(()));
        } else {
            return Err(Error::UnsupportedProcessor);
        }
    }

    /// Generate a value.
    #[inline]
    fn gen_value<T>(&self) -> T {
        let var;
        unsafe {
            asm!("1: rdseed $0; jnc 1b;" : "=r"(var));
        }
        var
    }

    /// Generate a u16 value.
    pub fn next_u16(&self) -> u16 {
        self.gen_value()
    }
}

impl Rng for RdSeed {
    fn next_u32(&mut self) -> u32 {
        self.gen_value()
    }

    fn next_u64(&mut self) -> u64 {
        self.gen_value()
    }
}

#[test]
fn rdrand_works() {
    let _ = RdRand::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}

#[test]
fn rdseed_works() {
    let _ = RdSeed::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}
<|endoftext|>


<commit_before>#![feature(asm, core, libc)]
#![allow(dead_code, raw_pointer_derive)]

#[macro_use]
extern crate syscall;
extern crate libc;

mod ffi {
    pub mod clone;
    pub mod futex;

    pub use ffi::clone::clone;
}

mod mutex;
#[macro_use]
mod thread;
mod stack;

#[test]
fn it_works() {
    use libc;

    use thread::Thread;
    use stack::Stack;
    use mutex::Mutex;

    extern fn test(arg: *mut libc::c_void) -> libc::c_int {
        unsafe {
            //let thd: *const Thread = std::mem::transmute(arg);
            //println!("Arg to child: 0x{:x}, pid:{}", (*thd).magic, (*thd).pid);
            //println!("Set {:?}", *thd);

            let mutex: *mut Mutex = std::mem::transmute(arg);
            (*mutex).lock();

            println!("child holds the mutex");
            (*mutex).unlock();
        }

        println!("Hello! I am a thread");

        let offset = offset_of!(Thread, tid);
        println!("tid offset = {}", offset);

        unsafe {
            let thd = thread::get_current_thread();
            println!("Child TLS: {:?} ", thd);

            thread::set_tls_mem(offset, 123456);

            let thd = thread::get_current_thread();
            println!("i should have set tid = {:?}", thd.tid );
        }

        0
    }

    let stack = Stack::new();
    let mut thd = stack.install_thread_block();
    let mut mutex = Mutex::new();

    mutex.lock();
    println!("parent holds the mutex");

    let id = unsafe {
        ffi::clone(test,
                   stack.stack_top,
                   ffi::clone::flags::COMMON,
                   &mut mutex as *mut _ as *mut _,
                   &mut thd.pid,
                   std::ptr::null_mut(),
                   &mut thd.tid)
    };

    println!("child id = {}, {}, {}", id, thd.tid, thd.pid);
    println!("stack is valid? {}", stack.is_valid());

    println!("parent releasing mutex...");
    mutex.unlock();

    loop {}
}
<commit_msg>Make sure code only works on supported platform<commit_after>#![feature(asm, core, libc)]
#![allow(dead_code, raw_pointer_derive)]

// We only work on 64 bit linux
#![cfg(all(target_os = "linux", target_pointer_width = "64"))]

#[macro_use]
extern crate syscall;
extern crate libc;

mod ffi {
    pub mod clone;
    pub mod futex;

    pub use ffi::clone::clone;
}

mod mutex;
#[macro_use]
mod thread;
mod stack;

#[test]
fn it_works() {
    use libc;

    use thread::Thread;
    use stack::Stack;
    use mutex::Mutex;

    extern fn test(arg: *mut libc::c_void) -> libc::c_int {
        unsafe {
            //let thd: *const Thread = std::mem::transmute(arg);
            //println!("Arg to child: 0x{:x}, pid:{}", (*thd).magic, (*thd).pid);
            //println!("Set {:?}", *thd);

            let mutex: *mut Mutex = std::mem::transmute(arg);
            (*mutex).lock();

            println!("child holds the mutex");
            (*mutex).unlock();
        }

        println!("Hello! I am a thread");

        let offset = offset_of!(Thread, tid);
        println!("tid offset = {}", offset);

        unsafe {
            let thd = thread::get_current_thread();
            println!("Child TLS: {:?} ", thd);

            thread::set_tls_mem(offset, 123456);

            let thd = thread::get_current_thread();
            println!("i should have set tid = {:?}", thd.tid );
        }

        0
    }

    let stack = Stack::new();
    let mut thd = stack.install_thread_block();
    let mut mutex = Mutex::new();

    mutex.lock();
    println!("parent holds the mutex");

    let id = unsafe {
        ffi::clone(test,
                   stack.stack_top,
                   ffi::clone::flags::COMMON,
                   &mut mutex as *mut _ as *mut _,
                   &mut thd.pid,
                   std::ptr::null_mut(),
                   &mut thd.tid)
    };

    println!("child id = {}, {}, {}", id, thd.tid, thd.pid);
    println!("stack is valid? {}", stack.is_valid());

    println!("parent releasing mutex...");
    mutex.unlock();

    loop {}
}
<|endoftext|>


<commit_before>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate num;

use std::ops::{Add, Index, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<commit_msg>Supress warnings<commit_after>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate num;

use std::ops::{Add, Index, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![allow(unstable)]

//! A table object type for dynamical data

use std::collections::HashMap;
use std::sync::Arc;
use std::ops::{ Deref, DerefMut, Index, IndexMut };
use std::hash::{ Hash, Hasher, Writer };

/// Represents a dynamical typed value
#[derive(Clone, Hash, PartialEq, Eq, Show)]
pub enum Value {
    /// An empty value.
    Null,
    /// A boolean value.
    Bool(bool),
    /// A pointer sized integer.
    Usize(usize),
    /// A 64 bit unsigned integer.
    U64(u64),
    /// A 64 bit signed integer.
    I64(i64),
    /// A 64 bit floating number.
    F64(F64),
    /// A string.
    String(Arc<String>),
    /// A table.
    Table(Arc<Table>),
}

impl Value {
    /// Creates a new f64 value.
    pub fn f64(val: f64) -> Value {
        Value::F64(F64(val))
    }
}

/// Wrapper for f64
#[derive(Copy, Clone, PartialEq, Show)]
pub struct F64(pub f64);

impl Eq for F64 {}

impl<S> Hash<S> for F64
    where
        S: Hasher + Writer
{
    fn hash(&self, state: &mut S) {
        let val = self.0 as u64;
        val.hash(state)
    }
}

impl Deref for F64 {
    type Target = f64;

    fn deref<'a>(&'a self) -> &'a f64 {
        &self.0
    }
}

impl DerefMut for F64 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut f64 {
        &mut self.0
    }
}

/// The table object
#[derive(Clone, PartialEq, Eq, Show)]
pub struct Table(pub HashMap<Value, Value>);

impl<S> Hash<S> for Table
    where
        S: Hasher + Writer
{
    fn hash(&self, state: &mut S) {
        for (key, val) in self.0.iter() {
            key.hash(state);
            val.hash(state);
        }
    }
}

impl Deref for Table {
    type Target = HashMap<Value, Value>;

    fn deref<'a>(&'a self) -> &'a HashMap<Value, Value> {
        &self.0
    }
}

impl DerefMut for Table {
    fn deref_mut<'a>(&'a mut self) -> &'a mut HashMap<Value, Value> {
        &mut self.0
    }
}

impl Index<Value> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &Value) -> &'a Value {
        self.0.get(index).unwrap()
    }
}

impl Index<usize> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &usize) -> &'a Value {
        self.0.get(&Value::Usize(*index)).unwrap()
    }
}

impl IndexMut<Value> for Table {
    type Output = Value;

    fn index_mut<'a>(&'a mut self, index: &Value) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(index.clone()) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(index).unwrap()
    }
}

impl IndexMut<usize> for Table {
    type Output = Value;

    fn index_mut<'a>(&'a mut self, index: &usize) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(Value::Usize(*index)) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(&Value::Usize(*index)).unwrap()
    }
}

impl Table {
    /// Creates new table.
    pub fn new() -> Table {
        Table(HashMap::new())
    }

    /// Creates new table with capacity.
    pub fn with_capacity(capacity: usize) -> Table {
        Table(HashMap::with_capacity(capacity))
    }
}

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

    use super::*;
    use self::test::Bencher;

    #[test]
    fn test_size() {
        use std::mem::size_of;

        // Make sure `Value` is not exceeding 128 bits on 64 bit systems.
        // This is for performance reasons.
        if size_of::<usize>() == 8 {
            assert_eq!(size_of::<Value>(), 16);
        }
    }

    #[test]
    fn test_sync() {
        fn foo<T: Sync>() {}

        // Make sure `Value` can be shared among tasks.
        foo::<Value>();
        foo::<Table>();
    }

    #[test]
    fn test_vec3() {
        let mut vec3 = Table::with_capacity(3);
        vec3[0us] = Value::f64(1.0);
        vec3[1us] = Value::f64(2.0);
        vec3[2us] = Value::f64(3.0);
        assert_eq!(vec3[0us], Value::f64(1.0));
        assert_eq!(vec3[1us], Value::f64(2.0));
        assert_eq!(vec3[2us], Value::f64(3.0));
        vec3.clear();
        assert_eq!(vec3.len(), 0);
    }

    #[test]
    fn test_table_as_key() {
        use std::borrow::ToOwned;
        use std::sync::Arc;

        let a = Value::Table(Arc::new(Table::new()));
        let mut b = Table::new();
        b[a] = Value::String(Arc::new("hello".to_owned()));
    }

    #[bench]
    fn bench_create_empty(bencher: &mut Bencher) {
        bencher.iter(|| {
            let _ = Table::new();
        });
    }

    #[bench]
    fn bench_create_empty_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        bencher.iter(|| {
            let _ = Arc::new(Table::new());
        });
    }

    #[bench]
    fn bench_overwrite(bencher: &mut Bencher) {
        let mut a = Table::new();
        bencher.iter(|| {
            a[0us] = Value::f64(1.0);
        });
    }

    #[bench]
    fn bench_overwrite_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        let mut a = Arc::new(Table::new());
        bencher.iter(|| {
            a.make_unique()[0us] = Value::f64(1.0);
        });
    }
}

<commit_msg>Made string slices work as keys<commit_after>#![deny(missing_docs)]
#![allow(unstable)]

//! A table object type for dynamical data

use std::collections::HashMap;
use std::sync::Arc;
use std::ops::{ Deref, DerefMut, Index, IndexMut };
use std::hash::{ Hash, Hasher, Writer };
use std::borrow::BorrowFrom;

/// Represents a dynamical typed value
#[derive(Clone, PartialEq, Eq, Show)]
pub enum Value {
    /// An empty value.
    Null,
    /// A boolean value.
    Bool(bool),
    /// A pointer sized integer.
    Usize(usize),
    /// A 64 bit unsigned integer.
    U64(u64),
    /// A 64 bit signed integer.
    I64(i64),
    /// A 64 bit floating number.
    F64(F64),
    /// A string.
    String(Arc<String>),
    /// A table.
    Table(Arc<Table>),
}

impl Value {
    /// Creates a new f64 value.
    pub fn f64(val: f64) -> Value {
        Value::F64(F64(val))
    }
}

impl<S> Hash<S> for Value
    where
        S: Hasher + Writer
{
    fn hash(&self, state: &mut S) {
        match self {
            &Value::String(ref text) => text.hash(state),
            &Value::Null => 0us.hash(state),
            &Value::Bool(val) => val.hash(state),
            &Value::Usize(val) => val.hash(state),
            &Value::U64(val) => val.hash(state),
            &Value::I64(val) => val.hash(state),
            &Value::F64(val) => val.hash(state),
            &Value::Table(ref val) => val.hash(state),
        }
    }
}

impl BorrowFrom<Value> for str {
    fn borrow_from(owned: &Value) -> &str {
        match owned {
            &Value::String(ref text) => {
                &text[]
            }
            _ => ""
        }
    }
}

/// Wrapper for f64
#[derive(Copy, Clone, PartialEq, Show)]
pub struct F64(pub f64);

impl Eq for F64 {}

impl<S> Hash<S> for F64
    where
        S: Hasher + Writer
{
    fn hash(&self, state: &mut S) {
        let val = self.0 as u64;
        val.hash(state)
    }
}

impl Deref for F64 {
    type Target = f64;

    fn deref<'a>(&'a self) -> &'a f64 {
        &self.0
    }
}

impl DerefMut for F64 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut f64 {
        &mut self.0
    }
}

/// The table object
#[derive(Clone, PartialEq, Eq, Show)]
pub struct Table(pub HashMap<Value, Value>);

impl<S> Hash<S> for Table
    where
        S: Hasher + Writer
{
    fn hash(&self, state: &mut S) {
        for (key, val) in self.0.iter() {
            key.hash(state);
            val.hash(state);
        }
    }
}

impl Deref for Table {
    type Target = HashMap<Value, Value>;

    fn deref<'a>(&'a self) -> &'a HashMap<Value, Value> {
        &self.0
    }
}

impl DerefMut for Table {
    fn deref_mut<'a>(&'a mut self) -> &'a mut HashMap<Value, Value> {
        &mut self.0
    }
}

impl Index<Value> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &Value) -> &'a Value {
        self.0.get(index).unwrap()
    }
}

impl Index<usize> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &usize) -> &'a Value {
        self.0.get(&Value::Usize(*index)).unwrap()
    }
}

impl<'b> Index<&'b str> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &&'b str) -> &'a Value {
        self.0.get(*index).unwrap()
    }
}

impl IndexMut<Value> for Table {
    type Output = Value;

    fn index_mut<'a>(&'a mut self, index: &Value) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(index.clone()) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(index).unwrap()
    }
}

impl IndexMut<usize> for Table {
    type Output = Value;

    fn index_mut<'a>(&'a mut self, index: &usize) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(Value::Usize(*index)) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(&Value::Usize(*index)).unwrap()
    }
}

impl<'b> IndexMut<&'b str> for Table {
    type Output = Value;

    fn index_mut<'a>(&'a mut self, index: &&'b str) -> &'a mut Value {
        use std::borrow::ToOwned;

        if !self.0.contains_key(*index) {
            self.insert(Value::String(Arc::new((*index).to_owned())),
                Value::Null);
        }
        self.0.get_mut(*index).unwrap()
    }
}

impl Table {
    /// Creates new table.
    pub fn new() -> Table {
        Table(HashMap::new())
    }

    /// Creates new table with capacity.
    pub fn with_capacity(capacity: usize) -> Table {
        Table(HashMap::with_capacity(capacity))
    }
}

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

    use super::*;
    use self::test::Bencher;
    use std::sync::Arc;

    #[test]
    fn test_size() {
        use std::mem::size_of;

        // Make sure `Value` is not exceeding 128 bits on 64 bit systems.
        // This is for performance reasons.
        if size_of::<usize>() == 8 {
            assert_eq!(size_of::<Value>(), 16);
        }
    }

    #[test]
    fn test_sync() {
        fn foo<T: Sync>() {}

        // Make sure `Value` can be shared among tasks.
        foo::<Value>();
        foo::<Table>();
    }

    #[test]
    fn test_vec3() {
        let mut vec3 = Table::with_capacity(3);
        vec3[0us] = Value::f64(1.0);
        vec3[1us] = Value::f64(2.0);
        vec3[2us] = Value::f64(3.0);
        assert_eq!(vec3[0us], Value::f64(1.0));
        assert_eq!(vec3[1us], Value::f64(2.0));
        assert_eq!(vec3[2us], Value::f64(3.0));
        vec3.clear();
        assert_eq!(vec3.len(), 0);
    }

    #[test]
    fn test_table_as_key() {
        use std::borrow::ToOwned;

        let a = Value::Table(Arc::new(Table::new()));
        let mut b = Table::new();
        b[a] = Value::String(Arc::new("hello".to_owned()));
    }

    #[test]
    fn test_str_as_key() {
        use std::borrow::ToOwned;

        let mut a = Table::new();
        a.insert(Value::String(Arc::new("hello".to_owned())),
            Value::String(Arc::new("world".to_owned())));
        assert!(
            if let Some(&Value::String(_)) = a.get("hello") { true }
            else { false }
        );
        assert_eq!(a["hello"], Value::String(Arc::new("world".to_owned())));
        a["hello2"] = Value::String(Arc::new("world".to_owned()));
        assert_eq!(a["hello"], a["hello2"]);
    }

    #[bench]
    fn bench_create_empty(bencher: &mut Bencher) {
        bencher.iter(|| {
            let _ = Table::new();
        });
    }

    #[bench]
    fn bench_create_empty_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        bencher.iter(|| {
            let _ = Arc::new(Table::new());
        });
    }

    #[bench]
    fn bench_overwrite(bencher: &mut Bencher) {
        let mut a = Table::new();
        bencher.iter(|| {
            a[0us] = Value::f64(1.0);
        });
    }

    #[bench]
    fn bench_overwrite_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        let mut a = Arc::new(Table::new());
        bencher.iter(|| {
            a.make_unique()[0us] = Value::f64(1.0);
        });
    }
}

<|endoftext|>


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

// We disable #[no_mangle] for tests so that we can verify the test results
// against the native compiler-rt implementations of the builtins.

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

#[cfg(test)]
extern crate core;

#[cfg(all(not(windows), not(target_os = "macos")))]
extern crate rlibc;

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

pub mod udiv;
pub mod mul;
pub mod shift;

#[cfg(test)]
mod qc;

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

// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
impl Int for u32 {
    fn bits() -> u32 {
        32
    }
}
impl Int for i32 {
    fn bits() -> u32 {
        32
    }
}
impl Int for u64 {
    fn bits() -> u32 {
        64
    }
}
impl Int for i64 {
    fn bits() -> u32 {
        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)
    }
}
<commit_msg>remove unused feature gates<commit_after>#![feature(asm)]
#![feature(linkage)]
#![feature(naked_functions)]
#![cfg_attr(not(test), no_std)]
#![no_builtins]
// TODO(rust-lang/rust#35021) uncomment when that PR lands
// #![feature(rustc_builtins)]

// We disable #[no_mangle] for tests so that we can verify the test results
// against the native compiler-rt implementations of the builtins.

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

#[cfg(test)]
extern crate core;

#[cfg(all(not(windows), not(target_os = "macos")))]
extern crate rlibc;

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

pub mod udiv;
pub mod mul;
pub mod shift;

#[cfg(test)]
mod qc;

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

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


<commit_before>extern crate json_schema;
extern crate serde_json;

#[macro_use]
extern crate quote;

use std::error::Error;

use json_schema::{Schema, Type};

use quote::{Tokens, ToTokens};

struct Ident<S>(S);

impl<S: AsRef<str>> ToTokens for Ident<S> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.0.as_ref())
    }
}

fn field(s: &str) -> Tokens {
    if ["type", "struct", "enum"].iter().any(|&keyword| keyword == s) {
        let n = Ident(format!("{}_", s));
        quote!( #n )
    } else {
        let mut snake = String::new();
        let mut chars = s.chars();
        let mut prev_was_upper = false;
        while let Some(c) = chars.next() {
            if c.is_uppercase() {
                if !prev_was_upper {
                    snake.push('_');
                }
                snake.extend(c.to_lowercase());
                prev_was_upper = true;
            } else {
                snake.push(c);
                prev_was_upper = false;
            }
        }
        if snake != s || snake.contains(|c: char| c == '$' || c == '#') {
            let field = Ident(snake.replace('$', "").replace('#', ""));
            quote!{
                #[serde(rename = #s)]
                pub #field
            }
        } else {
            let field = Ident(s);
            quote!( pub #field )
        }
    }
}

fn merge(result: &mut Schema, r: &Schema) {
    use std::collections::hash_map::Entry;

    for (k, v) in &r.properties {
        match result.properties.entry(k.clone()) {
            Entry::Vacant(entry) => {
                entry.insert(v.clone());
            }
            Entry::Occupied(mut entry) => merge(entry.get_mut(), v),
        }
    }
}

struct Expander<'r> {
    root_name: Option<&'r str>,
    root: &'r Schema,
}

impl<'r> Expander<'r> {
    fn type_ref(&self, s: &str) -> String {
        if s == "#" {
            self.root_name.expect("Root name").into()
        } else {
            s.split('/').last().expect("Component").into()
        }
    }

    fn schema(&self, s: &'r Schema) -> &'r Schema {
        if let Some(ref ref_) = s.ref_ {
            self.schema_ref(ref_)
        } else {
            s
        }
    }

    fn schema_ref(&self, s: &str) -> &'r Schema {
        s.split('/').fold(self.root, |schema, comp| {
            if comp == "#" {
                self.root
            } else if comp == "definitions" {
                schema
            } else {
                schema.definitions
                    .get(comp)
                    .unwrap_or_else(|| panic!("Expected definition: `{}` {}", s, comp))
            }
        })
    }

    fn expand_type(&mut self, typ: &Schema) -> String {
        if let Some(ref ref_) = typ.ref_ {
            self.type_ref(ref_)
        } else if typ.type_.len() == 1 {
            match typ.type_[0] {
                Type::String => {
                    if !typ.enum_.is_empty() {
                        "serde_json::Value".into()
                    } else {
                        "String".into()
                    }
                }
                Type::Integer => "i64".into(),
                Type::Boolean => "bool".into(),
                Type::Number => "f64".into(),
                Type::Object => "serde_json::Value".into(),
                Type::Array => {
                    let item_type =
                        typ.items.as_ref().map_or("json_schema::Value".into(),
                                                  |item_schema| self.expand_type(item_schema));
                    format!("Vec<{}>", item_type)
                }
                _ => panic!("Type"),
            }
        } else {
            "serde_json::Value".into()
        }
    }

    fn expand_fields(&mut self, schema: &Schema) -> Vec<Tokens> {
        if let Some(ref ref_) = schema.ref_ {
            let schema = self.schema_ref(ref_);
            self.expand_fields(schema)
        } else if !schema.allOf.is_empty() {
            let first = schema.allOf.first().unwrap().clone();
            let result = schema.allOf
                .iter()
                .skip(1)
                .fold(first, |mut result, def| {
                    merge(&mut result, self.schema(def));
                    result
                });
            self.expand_fields(&result)
        } else {
            schema.properties
                .iter()
                .map(|(key, value)| {
                    let key = field(key);
                    let typ = Ident(self.expand_type(value));
                    quote!( #key : #typ )
                })
                .collect()
        }
    }

    pub fn expand_definitions(&mut self, schema: &Schema) -> Vec<Tokens> {
        let mut types = Vec::new();
        for (name, def) in &schema.definitions {
            types.push(self.expand_schema(name, def));
        }
        types
    }

    pub fn expand_schema(&mut self, name: &str, schema: &Schema) -> Tokens {
        let fields = self.expand_fields(schema);
        let name = Ident(name);
        quote! {
            #[derive(Deserialize, Serialize)]
            pub struct #name {
                #(#fields),*
            }
        }
    }

    pub fn expand(&mut self, schema: &Schema) -> Tokens {
        let mut types = self.expand_definitions(schema);
        if let Some(name) = self.root_name {
            types.push(self.expand_schema(name, schema));
        }

        quote! { #(
            #types
            )*
        }
    }
}

pub fn generate(root_name: Option<&str>, s: &str) -> Result<String, Box<Error>> {
    use std::process::{Command, Stdio};
    use std::io::Write;

    let schema = serde_json::from_str(s).unwrap();
    let mut expander = Expander {
        root_name: root_name,
        root: &schema,
    };
    let output = expander.expand(&schema).to_string();
    let mut child =
        try!(Command::new("rustfmt").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn());
    try!(child.stdin.as_mut().expect("stdin").write_all(output.as_bytes()));
    let output = try!(child.wait_with_output());
    Ok(try!(String::from_utf8(output.stdout)))
}

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

    use std::fs::File;
    use std::io::Write;
    use std::path::PathBuf;
    use std::process::{Command, Stdio};

    #[test]
    fn generate_schema() {
        let s = include_str!("../../json-schema/tests/schema.json");

        let s = generate(Some("Schema"), s).unwrap().to_string();

        assert!(s.contains("pub struct Schema"), "{}", s);
    }

    #[test]
    fn builds_with_rustc() {
        let s = include_str!("../../json-schema/tests/debugserver-schema.json");

        let s = generate(None, s).unwrap().to_string();

        let mut filename = PathBuf::from("target/debug");
        filename.push("test.rs");
        {
            let mut file = File::create(&filename).unwrap();
            let header = r#"
            #![feature(proc_macro)]

            #[macro_use]
            extern crate serde_derive;
            extern crate serde_json;
            "#;
            file.write_all(header.as_bytes()).unwrap();
            file.write_all(s.as_bytes()).unwrap();
        }

        let child = Command::new("rustc")
            .args(&["-L", "target/debug/deps/", "--crate-type=rlib", filename.to_str().unwrap()])
            .stderr(Stdio::piped())
            .spawn()
            .unwrap();

        let output = child.wait_with_output().unwrap();
        let error = String::from_utf8(output.stderr).unwrap();
        assert!(output.status.success(), "{}", error);
    }
}
<commit_msg>fix: Handle generating the json-schema schema<commit_after>extern crate json_schema;
extern crate serde_json;

#[macro_use]
extern crate quote;

use std::error::Error;

use json_schema::{Schema, Type};

use quote::{Tokens, ToTokens};

struct Ident<S>(S);

impl<S: AsRef<str>> ToTokens for Ident<S> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.0.as_ref())
    }
}

fn field(s: &str) -> Tokens {
    if ["type", "struct", "enum"].iter().any(|&keyword| keyword == s) {
        let n = Ident(format!("{}_", s));
        quote!( #n )
    } else {
        let mut snake = String::new();
        let mut chars = s.chars();
        let mut prev_was_upper = false;
        while let Some(c) = chars.next() {
            if c.is_uppercase() {
                if !prev_was_upper {
                    snake.push('_');
                }
                snake.extend(c.to_lowercase());
                prev_was_upper = true;
            } else {
                snake.push(c);
                prev_was_upper = false;
            }
        }
        if snake != s || snake.contains(|c: char| c == '$' || c == '#') {
            let field = Ident(snake.replace('$', "").replace('#', ""));
            quote!{
                #[serde(rename = #s)]
                pub #field
            }
        } else {
            let field = Ident(s);
            quote!( pub #field )
        }
    }
}

fn merge(result: &mut Schema, r: &Schema) {
    use std::collections::hash_map::Entry;

    for (k, v) in &r.properties {
        match result.properties.entry(k.clone()) {
            Entry::Vacant(entry) => {
                entry.insert(v.clone());
            }
            Entry::Occupied(mut entry) => merge(entry.get_mut(), v),
        }
    }
}

struct Expander<'r> {
    root_name: Option<&'r str>,
    root: &'r Schema,
}

impl<'r> Expander<'r> {
    fn type_ref(&self, s: &str) -> String {
        if s == "#" {
            self.root_name.expect("Root name").into()
        } else {
            s.split('/').last().expect("Component").into()
        }
    }

    fn schema(&self, s: &'r Schema) -> &'r Schema {
        if let Some(ref ref_) = s.ref_ {
            self.schema_ref(ref_)
        } else {
            s
        }
    }

    fn schema_ref(&self, s: &str) -> &'r Schema {
        s.split('/').fold(self.root, |schema, comp| {
            if comp == "#" {
                self.root
            } else if comp == "definitions" {
                schema
            } else {
                schema.definitions
                    .get(comp)
                    .unwrap_or_else(|| panic!("Expected definition: `{}` {}", s, comp))
            }
        })
    }

    fn expand_type(&mut self, type_name: &str, typ: &Schema) -> String {
        let result = self.expand_type_(typ);
        if type_name == result {
            format!("Box<{}>", result)
        } else {
            result
        }
    }
    fn expand_type_(&mut self, typ: &Schema) -> String {
        if let Some(ref ref_) = typ.ref_ {
            self.type_ref(ref_)
        } else if typ.type_.len() == 1 {
            match typ.type_[0] {
                Type::String => {
                    if !typ.enum_.is_empty() {
                        "serde_json::Value".into()
                    } else {
                        "String".into()
                    }
                }
                Type::Integer => "i64".into(),
                Type::Boolean => "bool".into(),
                Type::Number => "f64".into(),
                Type::Object => "serde_json::Value".into(),
                Type::Array => {
                    let item_type =
                        typ.items.as_ref().map_or("serde_json::Value".into(),
                                                  |item_schema| self.expand_type_(item_schema));
                    format!("Vec<{}>", item_type)
                }
                _ => panic!("Type"),
            }
        } else {
            "serde_json::Value".into()
        }
    }

    fn expand_fields(&mut self, type_name: &str, schema: &Schema) -> Vec<Tokens> {
        if let Some(ref ref_) = schema.ref_ {
            let schema = self.schema_ref(ref_);
            self.expand_fields(type_name, schema)
        } else if !schema.allOf.is_empty() {
            let first = schema.allOf.first().unwrap().clone();
            let result = schema.allOf
                .iter()
                .skip(1)
                .fold(first, |mut result, def| {
                    merge(&mut result, self.schema(def));
                    result
                });
            self.expand_fields(type_name, &result)
        } else {
            schema.properties
                .iter()
                .map(|(key, value)| {
                    let key = field(key);
                    let typ = Ident(self.expand_type(type_name, value));
                    quote!( #key : #typ )
                })
                .collect()
        }
    }

    pub fn expand_definitions(&mut self, schema: &Schema) -> Vec<Tokens> {
        let mut types = Vec::new();
        for (name, def) in &schema.definitions {
            types.push(self.expand_schema(name, def));
        }
        types
    }

    pub fn expand_schema(&mut self, name: &str, schema: &Schema) -> Tokens {
        let fields = self.expand_fields(name, schema);
        let name = Ident(name);
        quote! {
            #[derive(Deserialize, Serialize)]
            pub struct #name {
                #(#fields),*
            }
        }
    }

    pub fn expand(&mut self, schema: &Schema) -> Tokens {
        let mut types = self.expand_definitions(schema);
        if let Some(name) = self.root_name {
            types.push(self.expand_schema(name, schema));
        }

        quote! { #(
            #types
            )*
        }
    }
}

pub fn generate(root_name: Option<&str>, s: &str) -> Result<String, Box<Error>> {
    use std::process::{Command, Stdio};
    use std::io::Write;

    let schema = serde_json::from_str(s).unwrap();
    let mut expander = Expander {
        root_name: root_name,
        root: &schema,
    };
    let output = expander.expand(&schema).to_string();
    let mut child =
        try!(Command::new("rustfmt").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn());
    try!(child.stdin.as_mut().expect("stdin").write_all(output.as_bytes()));
    let output = try!(child.wait_with_output());
    Ok(try!(String::from_utf8(output.stdout)))
}

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

    use std::fs::File;
    use std::io::Write;
    use std::path::PathBuf;
    use std::process::{Command, Stdio};

    #[test]
    fn generate_schema() {
        let s = include_str!("../../json-schema/tests/schema.json");

        let s = generate(Some("Schema"), s).unwrap().to_string();

        assert!(s.contains("pub struct Schema"), "{}", s);

        verify_compile("schema.rs", &s);
    }

    fn verify_compile(name: &str, s: &str) {

        let mut filename = PathBuf::from("target/debug");
        filename.push(name);
        {
            let mut file = File::create(&filename).unwrap();
            let header = r#"
            #![feature(proc_macro)]

            #[macro_use]
            extern crate serde_derive;
            extern crate serde_json;
            "#;
            file.write_all(header.as_bytes()).unwrap();
            file.write_all(s.as_bytes()).unwrap();
        }

        let child = Command::new("rustc")
            .args(&["-L", "target/debug/deps/", "--crate-type=rlib", filename.to_str().unwrap()])
            .stderr(Stdio::piped())
            .spawn()
            .unwrap();

        let output = child.wait_with_output().unwrap();
        let error = String::from_utf8(output.stderr).unwrap();
        assert!(output.status.success(), "{}", error);
    }

    #[test]
    fn builds_with_rustc() {
        let s = include_str!("../../json-schema/tests/debugserver-schema.json");

        let s = generate(None, s).unwrap().to_string();

        verify_compile("debug-server.rs", &s)
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

#![cfg_attr(feature = "strict", deny(warnings))]
#![cfg_attr(feature = "strict", deny(missing_debug_implementations))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

extern crate bytes;
extern crate hyper;
extern crate tokio_io;
extern crate websocket;

#[macro_use]
extern crate futures;

use bytes::BytesMut;
use futures::{Future, Poll};
use futures::sink::Send;
use hyper::{HttpVersion, Method};
use hyper::header::{self, Headers, Raw};
use std::ascii::AsciiExt;
use std::fmt;
use std::iter::{self, FromIterator};
use std::mem;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::Framed;
use websocket::client::async::{Client, ClientNew};
use websocket::codec::http::HttpServerCodec;
use websocket::result::WebSocketError;
use websocket::server::upgrade::{Request, WsUpgrade};

#[derive(Clone, Debug)]
pub struct WsHandshake {
    key: Vec<u8>,
}

impl WsHandshake {
    pub fn key(&self) -> &[u8] {
        &self.key
    }

    pub fn into_key(self) -> Vec<u8> {
        self.key
    }

    pub fn detect<B>(req: &hyper::Request<B>) -> Option<Self> {
        WsHandshake::detect_from_parts(req.method(), req.version(), req.headers())
    }

    pub fn detect_from_parts(
        method: &Method,
        version: HttpVersion,
        headers: &Headers,
    ) -> Option<Self> {
        if *method != Method::Get {
            return None;
        }

        if version == HttpVersion::Http09 || version == HttpVersion::Http10 {
            return None;
        }

        if let Some(version) = headers.get_raw("sec-websocket-version").and_then(Raw::one) {
            if version != b"13" {
                return None;
            }
        }

        let key = match headers.get_raw("sec-websocket-key").and_then(Raw::one) {
            None => return None,
            Some(key) => key,
        };

        match headers.get::<header::Upgrade>() {
            None => return None,
            Some(&header::Upgrade(ref protocols)) => {
                let contains_websocket = !protocols
                    .iter()
                    .any(|protocol| protocol.name == header::ProtocolName::WebSocket);
                if contains_websocket {
                    return None;
                }
            }
        }

        match headers.get::<header::Connection>() {
            None => return None,
            Some(&header::Connection(ref options)) => {
                let upgrade = options.iter().any(|option| match *option {
                    header::ConnectionOption::ConnectionHeader(ref value)
                        if value.as_ref().eq_ignore_ascii_case("upgrade") =>
                    {
                        true
                    }
                    _ => false,
                });
                if !upgrade {
                    return None;
                }
            }
        }

        Some(WsHandshake {
            key: key.to_owned(),
        })
    }

    pub fn start<T>(self, io: T, read_buf: BytesMut) -> WsStart<T> {
        WsStart::new(self, io, read_buf)
    }

    pub fn accept<T>(self, io: T, read_buf: BytesMut) -> AcceptWsHandshake<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        AcceptWsHandshake(self.build_ws_upgrade(io, read_buf).accept())
    }

    pub fn reject<T>(self, io: T, read_buf: BytesMut) -> RejectWsHandshake<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        RejectWsHandshake(self.build_ws_upgrade(io, read_buf).reject())
    }

    pub fn respond<T>(self, io: T, read_buf: BytesMut, accept: bool) -> SendWsResponse<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        SendWsResponse(if accept {
            Ok(self.accept(io, read_buf))
        } else {
            Err(self.reject(io, read_buf))
        })
    }

    fn build_ws_upgrade<T>(self, io: T, read_buf: BytesMut) -> WsUpgrade<T, BytesMut>
    where
        T: AsyncRead + AsyncWrite,
    {
        let mut request: Request = Request {
            // Justification: see the comment on `OldHttpVersion` below.
            version: unsafe { mem::transmute(OldHttpVersion::Http11) },
            subject: (
                "GET".parse().expect("hyper-websocket: Method parse failed"),
                "*".parse().expect("hyper-websocket: RequestUri parse failed"),
            ),
            headers: FromIterator::from_iter(iter::empty()),
        };
        request.headers.set_raw("sec-websocket-key", vec![self.key]);
        WsUpgrade {
            headers: FromIterator::from_iter(iter::empty()),
            stream: io,
            request: request,
            buffer: read_buf,
        }
    }
}

pub struct AcceptWsHandshake<T>(ClientNew<T>);

impl<T> fmt::Debug for AcceptWsHandshake<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("AcceptWsHandshake").field(&"...").finish()
    }
}

impl<T> Future for AcceptWsHandshake<T> {
    type Item = Client<T>;
    type Error = WebSocketError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let (client, _) = try_ready!(self.0.poll());
        Ok(client.into())
    }
}

pub struct RejectWsHandshake<T: AsyncWrite>(Send<Framed<T, HttpServerCodec>>);

impl<T> fmt::Debug for RejectWsHandshake<T>
where
    T: AsyncWrite,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("RejectWsHandshake").field(&"...").finish()
    }
}

impl<T> Future for RejectWsHandshake<T>
where
    T: AsyncWrite,
{
    type Item = T;
    type Error = WebSocketError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let framed = try_ready!(self.0.poll());
        Ok(framed.into_inner().into())
    }
}

#[derive(Clone, Debug)]
pub struct WsResponse {
    pub handshake: WsHandshake,
    pub accept: bool,
}

impl WsResponse {
    pub fn accept(handshake: WsHandshake) -> Self {
        WsResponse {
            handshake: handshake,
            accept: true,
        }
    }

    pub fn reject(handshake: WsHandshake) -> Self {
        WsResponse {
            handshake: handshake,
            accept: false,
        }
    }

    pub fn send<T>(self, io: T, read_buf: BytesMut) -> SendWsResponse<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        self.handshake.respond(io, read_buf, self.accept)
    }
}

pub struct SendWsResponse<T: AsyncWrite>(Result<AcceptWsHandshake<T>, RejectWsHandshake<T>>);

impl<T> fmt::Debug for SendWsResponse<T>
where
    T: AsyncWrite,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("SendWsResponse").field(&self.0.as_ref().map(|_| "...")).finish()
    }
}

impl<T> Future for SendWsResponse<T>
where
    T: AsyncWrite,
{
    type Item = Result<Client<T>, T>;
    type Error = WebSocketError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            Ok(ref mut future) => Ok(Ok(try_ready!(future.poll())).into()),
            Err(ref mut future) => Ok(Err(try_ready!(future.poll())).into()),
        }
    }
}

#[derive(Clone, Debug)]
pub struct WsStart<T> {
    handshake: WsHandshake,
    io: T,
    read_buf: BytesMut,
}

impl<T> WsStart<T> {
    pub fn new(handshake: WsHandshake, io: T, read_buf: BytesMut) -> Self {
        WsStart {
            handshake: handshake,
            io: io,
            read_buf: read_buf,
        }
    }

    pub fn into_parts(self) -> (WsHandshake, T, BytesMut) {
        (self.handshake, self.io, self.read_buf)
    }
}

impl<T> WsStart<T>
where
    T: AsyncRead + AsyncWrite + 'static,
{
    pub fn accept(self, io: T, read_buf: BytesMut) -> AcceptWsHandshake<T> {
        self.handshake.accept(io, read_buf)
    }

    pub fn reject(self, io: T, read_buf: BytesMut) -> RejectWsHandshake<T> {
        self.handshake.reject(io, read_buf)
    }

    pub fn respond(self, io: T, read_buf: BytesMut, accept: bool) -> SendWsResponse<T> {
        self.handshake.respond(io, read_buf, accept)
    }
}

/// This type is structured to match the definition of hyper ^0.10.6's
/// `HttpVersion` type. It is used to translate from post-0.11 hyper's
/// `HttpVersion` type to the one form the older range which rust-websocket
/// depends on. Unfortunately Cargo doesn't give us an easy way to just reach in
/// and access this type from whatever version of hyper is selected for
/// rust-websocket, so we're left doing this hackily.
#[cfg_attr(feature = "clippy", allow(enum_variant_names))]
enum OldHttpVersion {
    #[allow(dead_code)]
    Http09,
    #[allow(dead_code)]
    Http10,
    Http11,
    #[allow(dead_code)]
    Http20,
}
<commit_msg>Remove io and read_buf params from WsStart<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

#![cfg_attr(feature = "strict", deny(warnings))]
#![cfg_attr(feature = "strict", deny(missing_debug_implementations))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

extern crate bytes;
extern crate hyper;
extern crate tokio_io;
extern crate websocket;

#[macro_use]
extern crate futures;

use bytes::BytesMut;
use futures::{Future, Poll};
use futures::sink::Send;
use hyper::{HttpVersion, Method};
use hyper::header::{self, Headers, Raw};
use std::ascii::AsciiExt;
use std::fmt;
use std::iter::{self, FromIterator};
use std::mem;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::Framed;
use websocket::client::async::{Client, ClientNew};
use websocket::codec::http::HttpServerCodec;
use websocket::result::WebSocketError;
use websocket::server::upgrade::{Request, WsUpgrade};

#[derive(Clone, Debug)]
pub struct WsHandshake {
    key: Vec<u8>,
}

impl WsHandshake {
    pub fn key(&self) -> &[u8] {
        &self.key
    }

    pub fn into_key(self) -> Vec<u8> {
        self.key
    }

    pub fn detect<B>(req: &hyper::Request<B>) -> Option<Self> {
        WsHandshake::detect_from_parts(req.method(), req.version(), req.headers())
    }

    pub fn detect_from_parts(
        method: &Method,
        version: HttpVersion,
        headers: &Headers,
    ) -> Option<Self> {
        if *method != Method::Get {
            return None;
        }

        if version == HttpVersion::Http09 || version == HttpVersion::Http10 {
            return None;
        }

        if let Some(version) = headers.get_raw("sec-websocket-version").and_then(Raw::one) {
            if version != b"13" {
                return None;
            }
        }

        let key = match headers.get_raw("sec-websocket-key").and_then(Raw::one) {
            None => return None,
            Some(key) => key,
        };

        match headers.get::<header::Upgrade>() {
            None => return None,
            Some(&header::Upgrade(ref protocols)) => {
                let contains_websocket = !protocols
                    .iter()
                    .any(|protocol| protocol.name == header::ProtocolName::WebSocket);
                if contains_websocket {
                    return None;
                }
            }
        }

        match headers.get::<header::Connection>() {
            None => return None,
            Some(&header::Connection(ref options)) => {
                let upgrade = options.iter().any(|option| match *option {
                    header::ConnectionOption::ConnectionHeader(ref value)
                        if value.as_ref().eq_ignore_ascii_case("upgrade") =>
                    {
                        true
                    }
                    _ => false,
                });
                if !upgrade {
                    return None;
                }
            }
        }

        Some(WsHandshake {
            key: key.to_owned(),
        })
    }

    pub fn start<T>(self, io: T, read_buf: BytesMut) -> WsStart<T> {
        WsStart::new(self, io, read_buf)
    }

    pub fn accept<T>(self, io: T, read_buf: BytesMut) -> AcceptWsHandshake<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        AcceptWsHandshake(self.build_ws_upgrade(io, read_buf).accept())
    }

    pub fn reject<T>(self, io: T, read_buf: BytesMut) -> RejectWsHandshake<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        RejectWsHandshake(self.build_ws_upgrade(io, read_buf).reject())
    }

    pub fn respond<T>(self, io: T, read_buf: BytesMut, accept: bool) -> SendWsResponse<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        SendWsResponse(if accept {
            Ok(self.accept(io, read_buf))
        } else {
            Err(self.reject(io, read_buf))
        })
    }

    fn build_ws_upgrade<T>(self, io: T, read_buf: BytesMut) -> WsUpgrade<T, BytesMut>
    where
        T: AsyncRead + AsyncWrite,
    {
        let mut request: Request = Request {
            // Justification: see the comment on `OldHttpVersion` below.
            version: unsafe { mem::transmute(OldHttpVersion::Http11) },
            subject: (
                "GET".parse().expect("hyper-websocket: Method parse failed"),
                "*".parse().expect("hyper-websocket: RequestUri parse failed"),
            ),
            headers: FromIterator::from_iter(iter::empty()),
        };
        request.headers.set_raw("sec-websocket-key", vec![self.key]);
        WsUpgrade {
            headers: FromIterator::from_iter(iter::empty()),
            stream: io,
            request: request,
            buffer: read_buf,
        }
    }
}

pub struct AcceptWsHandshake<T>(ClientNew<T>);

impl<T> fmt::Debug for AcceptWsHandshake<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("AcceptWsHandshake").field(&"...").finish()
    }
}

impl<T> Future for AcceptWsHandshake<T> {
    type Item = Client<T>;
    type Error = WebSocketError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let (client, _) = try_ready!(self.0.poll());
        Ok(client.into())
    }
}

pub struct RejectWsHandshake<T: AsyncWrite>(Send<Framed<T, HttpServerCodec>>);

impl<T> fmt::Debug for RejectWsHandshake<T>
where
    T: AsyncWrite,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("RejectWsHandshake").field(&"...").finish()
    }
}

impl<T> Future for RejectWsHandshake<T>
where
    T: AsyncWrite,
{
    type Item = T;
    type Error = WebSocketError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let framed = try_ready!(self.0.poll());
        Ok(framed.into_inner().into())
    }
}

#[derive(Clone, Debug)]
pub struct WsResponse {
    pub handshake: WsHandshake,
    pub accept: bool,
}

impl WsResponse {
    pub fn accept(handshake: WsHandshake) -> Self {
        WsResponse {
            handshake: handshake,
            accept: true,
        }
    }

    pub fn reject(handshake: WsHandshake) -> Self {
        WsResponse {
            handshake: handshake,
            accept: false,
        }
    }

    pub fn send<T>(self, io: T, read_buf: BytesMut) -> SendWsResponse<T>
    where
        T: AsyncRead + AsyncWrite + 'static,
    {
        self.handshake.respond(io, read_buf, self.accept)
    }
}

pub struct SendWsResponse<T: AsyncWrite>(Result<AcceptWsHandshake<T>, RejectWsHandshake<T>>);

impl<T> fmt::Debug for SendWsResponse<T>
where
    T: AsyncWrite,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("SendWsResponse").field(&self.0.as_ref().map(|_| "...")).finish()
    }
}

impl<T> Future for SendWsResponse<T>
where
    T: AsyncWrite,
{
    type Item = Result<Client<T>, T>;
    type Error = WebSocketError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            Ok(ref mut future) => Ok(Ok(try_ready!(future.poll())).into()),
            Err(ref mut future) => Ok(Err(try_ready!(future.poll())).into()),
        }
    }
}

#[derive(Clone, Debug)]
pub struct WsStart<T> {
    handshake: WsHandshake,
    io: T,
    read_buf: BytesMut,
}

impl<T> WsStart<T> {
    pub fn new(handshake: WsHandshake, io: T, read_buf: BytesMut) -> Self {
        WsStart {
            handshake: handshake,
            io: io,
            read_buf: read_buf,
        }
    }

    pub fn into_parts(self) -> (WsHandshake, T, BytesMut) {
        (self.handshake, self.io, self.read_buf)
    }
}

impl<T> WsStart<T>
where
    T: AsyncRead + AsyncWrite + 'static,
{
    pub fn accept(self) -> AcceptWsHandshake<T> {
        self.handshake.accept(self.io, self.read_buf)
    }

    pub fn reject(self) -> RejectWsHandshake<T> {
        self.handshake.reject(self.io, self.read_buf)
    }

    pub fn respond(self, accept: bool) -> SendWsResponse<T> {
        self.handshake.respond(self.io, self.read_buf, accept)
    }
}

/// This type is structured to match the definition of hyper ^0.10.6's
/// `HttpVersion` type. It is used to translate from post-0.11 hyper's
/// `HttpVersion` type to the one form the older range which rust-websocket
/// depends on. Unfortunately Cargo doesn't give us an easy way to just reach in
/// and access this type from whatever version of hyper is selected for
/// rust-websocket, so we're left doing this hackily.
#[cfg_attr(feature = "clippy", allow(enum_variant_names))]
enum OldHttpVersion {
    #[allow(dead_code)]
    Http09,
    #[allow(dead_code)]
    Http10,
    Http11,
    #[allow(dead_code)]
    Http20,
}
<|endoftext|>


<commit_before>extern crate chrono;

use chrono::UTC;
use std::net::UdpSocket;

mod error;
use self::error::DogstatsdError;

mod metrics;
use self::metrics::*;

#[derive(Debug, PartialEq)]
pub struct DogstatsdOptions {
    pub host: String,
    pub port: i32,
}

impl DogstatsdOptions {
    pub fn default() -> Self {
        DogstatsdOptions{
            host: "127.0.0.1".into(),
            port: 8125,
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Dogstatsd {
    udp_socket: String,
}

impl Dogstatsd {
    /// Spawn a new Dogstatsd handle
    pub fn new(options: DogstatsdOptions) -> Self {
        let socket_addr = format!("{}:{}", options.host, options.port);

        Dogstatsd {
            udp_socket: socket_addr,
        }
    }

    /// Increment a counter
    pub fn incr(&self, stat: &str) -> Result<(), DogstatsdError> {
        self.send(CountMetric::Incr(stat.into()))
    }

    /// Decrement a counter
    pub fn decr(&self, stat: &str) -> Result<(), DogstatsdError> {
        self.send(CountMetric::Decr(stat.into()))
    }

    /// Time a block of code
    pub fn time<F: FnOnce()>(&self, stat: &str, block: F) -> Result<(), DogstatsdError> {
        let start_time = UTC::now();
        block();
        let end_time = UTC::now();

        self.send(TimeMetric::new(stat, start_time, end_time))
    }

    /// Send a timing metric
    pub fn timing(&self, stat: &str, ms: i64) -> Result<(), DogstatsdError> {
        self.send(TimingMetric::new(stat, ms))
    }

    /// Report an arbitrary value (a gauge)
    pub fn gauge(&self, stat: &str, val: &str) -> Result<(), DogstatsdError> {
        self.send(GaugeMetric::new(stat, val))
    }

    /// Report a value in a histogram
    pub fn histogram(&self, stat: &str, val: &str) -> Result<(), DogstatsdError> {
        self.send(HistogramMetric::new(stat, val))
    }

    /// Report a value in a set
    pub fn set(&self, stat: &str, val: &str) -> Result<(), DogstatsdError> {
        self.send(SetMetric::new(stat, val))
    }

    /// Send a custom event
    pub fn event(&self, title: &str, text: &str) -> Result<(), DogstatsdError> {
        self.send(Event::new(title, text))
    }

    fn send<M: Metric>(&self, metric: M) -> Result<(), DogstatsdError> {
        let socket = try!(self.socket());
        try!(socket.send_to(metric.format_for_send().as_bytes(), try!(socket.local_addr())));
        Ok(())
    }

    fn socket(&self) -> Result<UdpSocket, DogstatsdError> {
        let socket = try!(UdpSocket::bind(&self.udp_socket[..]));
        Ok(socket)
    }
}

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

    #[test]
    fn test_options_default() {
        let options = DogstatsdOptions::default();
        let expected_options = DogstatsdOptions {
            host: "127.0.0.1".into(),
            port: 8125,
        };

        assert_eq!(expected_options, options)
    }

    #[test]
    fn test_new() {
        let client = Dogstatsd::new(DogstatsdOptions::default());

        assert_eq!(Dogstatsd { udp_socket: "127.0.0.1:8125".into() }, client)
    }
}
<commit_msg>to and from<commit_after>extern crate chrono;

use chrono::UTC;
use std::net::UdpSocket;

mod error;
use self::error::DogstatsdError;

mod metrics;
use self::metrics::*;

#[derive(Debug, PartialEq)]
pub struct DogstatsdOptions {
    pub from_addr: String,
    pub to_addr: String,
}

impl DogstatsdOptions {
    pub fn default() -> Self {
        DogstatsdOptions {
            from_addr: "127.0.0.1:8126".into(),
            to_addr: "127.0.0.1:8125".into(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Dogstatsd {
    from_addr: String,
    to_addr: String,
}

impl Dogstatsd {
    /// Spawn a new Dogstatsd handle
    pub fn new(options: DogstatsdOptions) -> Self {
        Dogstatsd {
            from_addr: options.from_addr,
            to_addr: options.to_addr,
        }
    }

    /// Increment a counter
    pub fn incr(&self, stat: &str) -> Result<(), DogstatsdError> {
        self.send(CountMetric::Incr(stat.into()))
    }

    /// Decrement a counter
    pub fn decr(&self, stat: &str) -> Result<(), DogstatsdError> {
        self.send(CountMetric::Decr(stat.into()))
    }

    /// Time a block of code
    pub fn time<F: FnOnce()>(&self, stat: &str, block: F) -> Result<(), DogstatsdError> {
        let start_time = UTC::now();
        block();
        let end_time = UTC::now();

        self.send(TimeMetric::new(stat, start_time, end_time))
    }

    /// Send a timing metric
    pub fn timing(&self, stat: &str, ms: i64) -> Result<(), DogstatsdError> {
        self.send(TimingMetric::new(stat, ms))
    }

    /// Report an arbitrary value (a gauge)
    pub fn gauge(&self, stat: &str, val: &str) -> Result<(), DogstatsdError> {
        self.send(GaugeMetric::new(stat, val))
    }

    /// Report a value in a histogram
    pub fn histogram(&self, stat: &str, val: &str) -> Result<(), DogstatsdError> {
        self.send(HistogramMetric::new(stat, val))
    }

    /// Report a value in a set
    pub fn set(&self, stat: &str, val: &str) -> Result<(), DogstatsdError> {
        self.send(SetMetric::new(stat, val))
    }

    /// Send a custom event
    pub fn event(&self, title: &str, text: &str) -> Result<(), DogstatsdError> {
        self.send(Event::new(title, text))
    }

    fn send<M: Metric>(&self, metric: M) -> Result<(), DogstatsdError> {
        let socket = try!(self.socket());
        try!(socket.send_to(metric.format_for_send().as_bytes(), &self.to_addr[..]));
        Ok(())
    }

    fn socket(&self) -> Result<UdpSocket, DogstatsdError> {
        let socket = try!(UdpSocket::bind(&self.from_addr[..]));
        Ok(socket)
    }
}

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

    #[test]
    fn test_options_default() {
        let options = DogstatsdOptions::default();
        let expected_options = DogstatsdOptions {
            from_addr: "127.0.0.1:8126".into(),
            to_addr: "127.0.0.1:8125".into(),
        };

        assert_eq!(expected_options, options)
    }

    #[test]
    fn test_new() {
        let client = Dogstatsd::new(DogstatsdOptions::default());
        let expected_client = Dogstatsd {
            from_addr: "127.0.0.1:8126".into(),
            to_addr: "127.0.0.1:8125".into(),
        };

        assert_eq!(expected_client, client)
    }
}
<|endoftext|>