<commit_before>//! `simd` offers a basic interface to the SIMD functionality of CPUs.
//!
//! # Installation
//!
//! Via git:
//!
//! ```toml
//! simd = { git = "https://github.com/huonw/simd" }
//! ```
//!
//! This is **not** currently the `simd` crate on crates.io.

#![cfg_attr(feature = "serde", feature(plugin, custom_derive))]
#![cfg_attr(feature = "serde", plugin(serde_macros))]

#![feature(cfg_target_feature, repr_simd, platform_intrinsics)]
#![allow(non_camel_case_types)]

#[cfg(feature = "serde")]
extern crate serde;

/// Boolean type for 8-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool8i(i8);
/// Boolean type for 16-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool16i(i16);
/// Boolean type for 32-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool32i(i32);
/// Boolean type for 32-bit floats.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool32f(i32);

/// Types that are SIMD vectors.
pub unsafe trait Simd {
    /// The corresponding boolean vector type.
    type Bool: Simd;
    /// The element that this vector stores.
    type Elem;
}

/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u32x4(u32, u32, u32, u32);
/// A SIMD vector of 4 `i32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i32x4(i32, i32, i32, i32);
/// A SIMD vector of 4 `f32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct f32x4(f32, f32, f32, f32);
/// A SIMD boolean vector for length-4 vectors of 32-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32ix4(i32, i32, i32, i32);
/// A SIMD boolean vector for length-4 vectors of 32-bit floats.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32fx4(i32, i32, i32, i32);

#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct u32x2(u32, u32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct i32x2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct f32x2(f32, f32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32ix2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32fx2(i32, i32);

/// A SIMD vector of 8 `u16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u16x8(u16, u16, u16, u16,
                 u16, u16, u16, u16);
/// A SIMD vector of 8 `i16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i16x8(i16, i16, i16, i16,
                 i16, i16, i16, i16);
/// A SIMD boolean vector for length-8 vectors of 16-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool16ix8(i16, i16, i16, i16,
                     i16, i16, i16, i16);

/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8,
                 u8, u8, u8, u8, u8, u8, u8, u8);
/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
                 i8, i8, i8, i8, i8, i8, i8, i8);
/// A SIMD boolean vector for length-16 vectors of 8-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool8ix16(i8, i8, i8, i8, i8, i8, i8, i8,
                     i8, i8, i8, i8, i8, i8, i8, i8);

macro_rules! simd {
    ($($bool: ty: $($ty: ty = $elem: ty),*;)*) => {
        $($(unsafe impl Simd for $ty {
            type Bool = $bool;
            type Elem = $elem;
        }
            impl Clone for $ty { fn clone(&self) -> Self { *self } }
            )*)*}
}
simd! {
    bool8ix16: i8x16 = i8, u8x16 = u8, bool8ix16 = bool8i;
    bool16ix8: i16x8 = i16, u16x8 = u16, bool16ix8 = bool16i;
    bool32ix4: i32x4 = i32, u32x4 = u32, bool32ix4 = bool32i;
    bool32fx4: f32x4 = f32, bool32fx4 = bool32f;

    bool32ix2: i32x2 = i32, u32x2 = u32, bool32ix2 = bool32i;
    bool32fx2: f32x2 = f32, bool32fx2 = bool32f;
}

#[allow(dead_code)]
#[inline]
fn bitcast<T: Simd, U: Simd>(x: T) -> U {
    assert_eq!(std::mem::size_of::<T>(),
               std::mem::size_of::<U>());
    unsafe {std::mem::transmute_copy(&x)}
}

#[allow(dead_code)]
extern "platform-intrinsic" {
    fn simd_eq<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ne<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_lt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_le<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_gt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ge<T: Simd<Bool = U>, U>(x: T, y: T) -> U;

    fn simd_shuffle2<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 2]) -> U;
    fn simd_shuffle4<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 4]) -> U;
    fn simd_shuffle8<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 8]) -> U;
    fn simd_shuffle16<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 16]) -> U;

    fn simd_insert<T: Simd<Elem = U>, U>(x: T, idx: u32, val: U) -> T;
    fn simd_extract<T: Simd<Elem = U>, U>(x: T, idx: u32) -> U;

    fn simd_cast<T: Simd, U: Simd>(x: T) -> U;

    fn simd_add<T: Simd>(x: T, y: T) -> T;
    fn simd_sub<T: Simd>(x: T, y: T) -> T;
    fn simd_mul<T: Simd>(x: T, y: T) -> T;
    fn simd_div<T: Simd>(x: T, y: T) -> T;
    fn simd_shl<T: Simd>(x: T, y: T) -> T;
    fn simd_shr<T: Simd>(x: T, y: T) -> T;
    fn simd_and<T: Simd>(x: T, y: T) -> T;
    fn simd_or<T: Simd>(x: T, y: T) -> T;
    fn simd_xor<T: Simd>(x: T, y: T) -> T;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone)]
struct Unalign<T>(T);

#[macro_use]
mod common;
mod sixty_four;

#[cfg(any(feature = "doc",
          target_arch = "x86",
          target_arch = "x86_64"))]
pub mod x86;
#[cfg(any(feature = "doc", target_arch = "arm"))]
pub mod arm;
#[cfg(any(feature = "doc", target_arch = "aarch64"))]
pub mod aarch64;
<commit_msg>Note breakage.<commit_after>//! `simd` offers a basic interface to the SIMD functionality of CPUs.
//!
//! **Warning** This is an actively developed work-in-progress, and
//! may/will break from commit to commit.
//!
//! # Installation
//!
//! Via git:
//!
//! ```toml
//! simd = { git = "https://github.com/huonw/simd" }
//! ```
//!
//! This is **not** currently the `simd` crate on crates.io.

#![cfg_attr(feature = "serde", feature(plugin, custom_derive))]
#![cfg_attr(feature = "serde", plugin(serde_macros))]

#![feature(cfg_target_feature, repr_simd, platform_intrinsics)]
#![allow(non_camel_case_types)]

#[cfg(feature = "serde")]
extern crate serde;

/// Boolean type for 8-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool8i(i8);
/// Boolean type for 16-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool16i(i16);
/// Boolean type for 32-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool32i(i32);
/// Boolean type for 32-bit floats.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
pub struct bool32f(i32);

/// Types that are SIMD vectors.
pub unsafe trait Simd {
    /// The corresponding boolean vector type.
    type Bool: Simd;
    /// The element that this vector stores.
    type Elem;
}

/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u32x4(u32, u32, u32, u32);
/// A SIMD vector of 4 `i32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i32x4(i32, i32, i32, i32);
/// A SIMD vector of 4 `f32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct f32x4(f32, f32, f32, f32);
/// A SIMD boolean vector for length-4 vectors of 32-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32ix4(i32, i32, i32, i32);
/// A SIMD boolean vector for length-4 vectors of 32-bit floats.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32fx4(i32, i32, i32, i32);

#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct u32x2(u32, u32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct i32x2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct f32x2(f32, f32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32ix2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32fx2(i32, i32);

/// A SIMD vector of 8 `u16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u16x8(u16, u16, u16, u16,
                 u16, u16, u16, u16);
/// A SIMD vector of 8 `i16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i16x8(i16, i16, i16, i16,
                 i16, i16, i16, i16);
/// A SIMD boolean vector for length-8 vectors of 16-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool16ix8(i16, i16, i16, i16,
                     i16, i16, i16, i16);

/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8,
                 u8, u8, u8, u8, u8, u8, u8, u8);
/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
                 i8, i8, i8, i8, i8, i8, i8, i8);
/// A SIMD boolean vector for length-16 vectors of 8-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool8ix16(i8, i8, i8, i8, i8, i8, i8, i8,
                     i8, i8, i8, i8, i8, i8, i8, i8);

macro_rules! simd {
    ($($bool: ty: $($ty: ty = $elem: ty),*;)*) => {
        $($(unsafe impl Simd for $ty {
            type Bool = $bool;
            type Elem = $elem;
        }
            impl Clone for $ty { fn clone(&self) -> Self { *self } }
            )*)*}
}
simd! {
    bool8ix16: i8x16 = i8, u8x16 = u8, bool8ix16 = bool8i;
    bool16ix8: i16x8 = i16, u16x8 = u16, bool16ix8 = bool16i;
    bool32ix4: i32x4 = i32, u32x4 = u32, bool32ix4 = bool32i;
    bool32fx4: f32x4 = f32, bool32fx4 = bool32f;

    bool32ix2: i32x2 = i32, u32x2 = u32, bool32ix2 = bool32i;
    bool32fx2: f32x2 = f32, bool32fx2 = bool32f;
}

#[allow(dead_code)]
#[inline]
fn bitcast<T: Simd, U: Simd>(x: T) -> U {
    assert_eq!(std::mem::size_of::<T>(),
               std::mem::size_of::<U>());
    unsafe {std::mem::transmute_copy(&x)}
}

#[allow(dead_code)]
extern "platform-intrinsic" {
    fn simd_eq<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ne<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_lt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_le<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_gt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ge<T: Simd<Bool = U>, U>(x: T, y: T) -> U;

    fn simd_shuffle2<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 2]) -> U;
    fn simd_shuffle4<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 4]) -> U;
    fn simd_shuffle8<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 8]) -> U;
    fn simd_shuffle16<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 16]) -> U;

    fn simd_insert<T: Simd<Elem = U>, U>(x: T, idx: u32, val: U) -> T;
    fn simd_extract<T: Simd<Elem = U>, U>(x: T, idx: u32) -> U;

    fn simd_cast<T: Simd, U: Simd>(x: T) -> U;

    fn simd_add<T: Simd>(x: T, y: T) -> T;
    fn simd_sub<T: Simd>(x: T, y: T) -> T;
    fn simd_mul<T: Simd>(x: T, y: T) -> T;
    fn simd_div<T: Simd>(x: T, y: T) -> T;
    fn simd_shl<T: Simd>(x: T, y: T) -> T;
    fn simd_shr<T: Simd>(x: T, y: T) -> T;
    fn simd_and<T: Simd>(x: T, y: T) -> T;
    fn simd_or<T: Simd>(x: T, y: T) -> T;
    fn simd_xor<T: Simd>(x: T, y: T) -> T;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone)]
struct Unalign<T>(T);

#[macro_use]
mod common;
mod sixty_four;

#[cfg(any(feature = "doc",
          target_arch = "x86",
          target_arch = "x86_64"))]
pub mod x86;
#[cfg(any(feature = "doc", target_arch = "arm"))]
pub mod arm;
#[cfg(any(feature = "doc", target_arch = "aarch64"))]
pub mod aarch64;
<|endoftext|>


<commit_before>#![feature(io)]
#![feature(path)]
#![feature(fs)]
#![feature(collections)]
#![feature(core)]

use std::fs::{File};
use std::string::String;
use std::str::StrExt;
use std::path::AsPath;
use std::error::FromError;
use std::io::{Read, BufReader, Write};
use std::vec::Vec;
use std::num::ParseIntError;
use std::mem;

#[derive(Debug)]
pub enum Error {
    IO,
    Parse,
    DataType,
    FieldType,
    Malformed,
    NotImplemented
}

impl FromError<std::io::Error> for Error {
    fn from_error(_: std::io::Error) -> Error {
        Error::IO
    }
}

impl FromError<ParseIntError> for Error {
    fn from_error(_: ParseIntError) -> Error {
        Error::Parse
    }
}

#[derive(Debug)]
pub enum DataType {
    XDRFloat,
    FloatLE,
}

impl DataType {
    fn from_str(s: &str) -> Result<DataType, Error> {
        match s {
            "float_le" => Ok(DataType::FloatLE),
//            "xdr_float" => Ok(DataType::XDRFloat),
            _ => Err(Error::DataType)
        }
    }
}

#[derive(Debug)]
pub enum FieldType {
    Uniform
}

impl FieldType {
    fn from_str(s: &str) -> Result<FieldType, Error> {
        match s {
            "uniform" => Ok(FieldType::Uniform),
            _ => Err(Error::FieldType)
        }
    }
}

pub struct AVSFile<'a> {
    pub ndim: usize,
    pub sizes: Vec<usize>,
    pub data_type: DataType,
    pub field_type: FieldType,
    reader: Box<Read + 'a>
}

impl<'a> AVSFile<'a> {
    pub fn write<W: Write, T>(
                writer: &mut W, ndim: usize, dims: &[usize], data: &[T])
                    -> Result<(), Error> {
        // header
        try!(writer.write_fmt(format_args!("# AVS FLD file (written by avsfldrs github.com/greyhill/avsfldrs)\n")));
        try!(writer.write_fmt(format_args!("ndim={}\n", ndim)));
        try!(writer.write_fmt(format_args!("veclen=1\n")));
        try!(writer.write_fmt(format_args!("nspace={}\n", ndim)));
        try!(writer.write_fmt(format_args!("field=uniform\n")));
        try!(writer.write_fmt(format_args!("data=float_le\n"))); // TODO
        for (id, size) in dims.iter().enumerate() {
            try!(writer.write_fmt(format_args!("dim{}={}\n", id+1, size)));
        }
        try!(writer.write_fmt(format_args!("{}{}", 12 as char, 12 as char)));
        let b: &[u8] = unsafe {
            std::slice::from_raw_parts(data.as_ptr() as *const u8,
                                       data.len()*mem::size_of::<T>())
        };
        try!(writer.write_all(b));
        Ok(())
    }

    pub fn read<T>(self: &mut Self) -> Result<Vec<T>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(mem::size_of::<T>()*size);
        try!(self.reader.read_to_end(&mut buf_u8));
        let buf: Vec<T> = unsafe {
            let ptr = buf_u8.as_mut_ptr();
            let cap = buf_u8.capacity();
            mem::forget(buf_u8);
            Vec::<T>::from_raw_parts(
                mem::transmute(ptr),
                size,
                cap / mem::size_of::<T>())
        };
        Ok(buf)
    }

    pub fn open<P: AsPath>(path: &P) -> Result<AVSFile, Error> {
        let mut reader = BufReader::new(try!(File::open(path)));

        let mut ndim: Option<usize> = None;
        let mut sizes = Vec::<Option<usize>>::new();
        let mut data_type: Option<DataType> = None;
        let mut field_type: Option<FieldType> = None;
        let mut external: Option<String> = None;

        let mut line = String::new();
        let mut last_char: u8 = 0;
        loop {
            let mut new_char_buf: [u8;1] = [ 0u8 ];
            try!(reader.read(&mut new_char_buf));

            // break on two chr 14s
            let new_char = new_char_buf[0];
            if (new_char, last_char) == (12u8, 12u8) {
                break;
            }
            last_char = new_char;

            line.push(new_char as char);

            // new line; process the line and discard
            if new_char == 10 {
                let tokens: Vec<&str> = line.split('=')
                    .map(|s| s.trim()).collect();
                match &tokens[..] {
                    ["ndim", s] => {
                        let nd = try!(s.parse::<usize>());
                        ndim = Some(nd);
                        for _ in 0..nd {
                            sizes.push(None);
                        }
                    },
                    ["dim1", s] => sizes[0] = Some(try!(s.parse::<usize>())),
                    ["dim2", s] => sizes[1] = Some(try!(s.parse::<usize>())),
                    ["dim3", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim4", s] => sizes[3] = Some(try!(s.parse::<usize>())),
                    ["dim5", s] => sizes[4] = Some(try!(s.parse::<usize>())),
                    ["dim6", s] => sizes[5] = Some(try!(s.parse::<usize>())),
                    ["dim7", s] => sizes[6] = Some(try!(s.parse::<usize>())),
                    ["data", s] =>
                        data_type = Some(try!(DataType::from_str(s))),
                    ["field", s] =>
                        field_type = Some(try!(FieldType::from_str(s))),
                    ["variable 1 file", s] =>
                        external = Some(String::from_str(s)),
                    _ => {}
                }
            }
            // hack?  code smell?  need borrow in previous block to expire
            if new_char == 10 {
                line.clear();
            }
        }

        match external {
            None => {
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
            Some(path) => {
                let new_reader = BufReader::new(try!(File::open(&path)));
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(new_reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
        }
    }
}

<commit_msg>removed ndim argument to write<commit_after>#![feature(io)]
#![feature(path)]
#![feature(fs)]
#![feature(collections)]
#![feature(core)]

use std::fs::{File};
use std::string::String;
use std::str::StrExt;
use std::path::AsPath;
use std::error::FromError;
use std::io::{Read, BufReader, Write};
use std::vec::Vec;
use std::num::ParseIntError;
use std::mem;

#[derive(Debug)]
pub enum Error {
    IO,
    Parse,
    DataType,
    FieldType,
    Malformed,
    NotImplemented
}

impl FromError<std::io::Error> for Error {
    fn from_error(_: std::io::Error) -> Error {
        Error::IO
    }
}

impl FromError<ParseIntError> for Error {
    fn from_error(_: ParseIntError) -> Error {
        Error::Parse
    }
}

#[derive(Debug)]
pub enum DataType {
    XDRFloat,
    FloatLE,
}

impl DataType {
    fn from_str(s: &str) -> Result<DataType, Error> {
        match s {
            "float_le" => Ok(DataType::FloatLE),
//            "xdr_float" => Ok(DataType::XDRFloat),
            _ => Err(Error::DataType)
        }
    }
}

#[derive(Debug)]
pub enum FieldType {
    Uniform
}

impl FieldType {
    fn from_str(s: &str) -> Result<FieldType, Error> {
        match s {
            "uniform" => Ok(FieldType::Uniform),
            _ => Err(Error::FieldType)
        }
    }
}

pub struct AVSFile<'a> {
    pub ndim: usize,
    pub sizes: Vec<usize>,
    pub data_type: DataType,
    pub field_type: FieldType,
    reader: Box<Read + 'a>
}

impl<'a> AVSFile<'a> {
    pub fn write<W: Write, T>(
                writer: &mut W, dims: &[usize], data: &[T])
                    -> Result<(), Error> {
        // header
        let ndim = dims.len();
        try!(writer.write_fmt(format_args!("# AVS FLD file (written by avsfldrs github.com/greyhill/avsfldrs)\n")));
        try!(writer.write_fmt(format_args!("ndim={}\n", ndim)));
        try!(writer.write_fmt(format_args!("veclen=1\n")));
        try!(writer.write_fmt(format_args!("nspace={}\n", ndim)));
        try!(writer.write_fmt(format_args!("field=uniform\n")));
        try!(writer.write_fmt(format_args!("data=float_le\n"))); // TODO
        for (id, size) in dims.iter().enumerate() {
            try!(writer.write_fmt(format_args!("dim{}={}\n", id+1, size)));
        }
        try!(writer.write_fmt(format_args!("{}{}", 12 as char, 12 as char)));
        let b: &[u8] = unsafe {
            std::slice::from_raw_parts(data.as_ptr() as *const u8,
                                       data.len()*mem::size_of::<T>())
        };
        try!(writer.write_all(b));
        Ok(())
    }

    pub fn read<T>(self: &mut Self) -> Result<Vec<T>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(mem::size_of::<T>()*size);
        try!(self.reader.read_to_end(&mut buf_u8));
        let buf: Vec<T> = unsafe {
            let ptr = buf_u8.as_mut_ptr();
            let cap = buf_u8.capacity();
            mem::forget(buf_u8);
            Vec::<T>::from_raw_parts(
                mem::transmute(ptr),
                size,
                cap / mem::size_of::<T>())
        };
        Ok(buf)
    }

    pub fn open<P: AsPath>(path: &P) -> Result<AVSFile, Error> {
        let mut reader = BufReader::new(try!(File::open(path)));

        let mut ndim: Option<usize> = None;
        let mut sizes = Vec::<Option<usize>>::new();
        let mut data_type: Option<DataType> = None;
        let mut field_type: Option<FieldType> = None;
        let mut external: Option<String> = None;

        let mut line = String::new();
        let mut last_char: u8 = 0;
        loop {
            let mut new_char_buf: [u8;1] = [ 0u8 ];
            try!(reader.read(&mut new_char_buf));

            // break on two chr 14s
            let new_char = new_char_buf[0];
            if (new_char, last_char) == (12u8, 12u8) {
                break;
            }
            last_char = new_char;

            line.push(new_char as char);

            // new line; process the line and discard
            if new_char == 10 {
                let tokens: Vec<&str> = line.split('=')
                    .map(|s| s.trim()).collect();
                match &tokens[..] {
                    ["ndim", s] => {
                        let nd = try!(s.parse::<usize>());
                        ndim = Some(nd);
                        for _ in 0..nd {
                            sizes.push(None);
                        }
                    },
                    ["dim1", s] => sizes[0] = Some(try!(s.parse::<usize>())),
                    ["dim2", s] => sizes[1] = Some(try!(s.parse::<usize>())),
                    ["dim3", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim4", s] => sizes[3] = Some(try!(s.parse::<usize>())),
                    ["dim5", s] => sizes[4] = Some(try!(s.parse::<usize>())),
                    ["dim6", s] => sizes[5] = Some(try!(s.parse::<usize>())),
                    ["dim7", s] => sizes[6] = Some(try!(s.parse::<usize>())),
                    ["data", s] =>
                        data_type = Some(try!(DataType::from_str(s))),
                    ["field", s] =>
                        field_type = Some(try!(FieldType::from_str(s))),
                    ["variable 1 file", s] =>
                        external = Some(String::from_str(s)),
                    _ => {}
                }
            }
            // hack?  code smell?  need borrow in previous block to expire
            if new_char == 10 {
                line.clear();
            }
        }

        match external {
            None => {
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
            Some(path) => {
                let new_reader = BufReader::new(try!(File::open(&path)));
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(new_reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
        }
    }
}

<|endoftext|>


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

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<commit_msg>Publicize Crate::versions vec<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    /// Published versions of this crate sorted chronologically by date published
    pub versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<|endoftext|>


<commit_before>macro_rules! delegate_method {
    ( $fld:ident as $fldty:ty : ) => {

    };

    ( $fld:ident : $($rest:tt)*) => {
        delegate_method!($fld as () : $($rest)*)
    };

    ( $fld_last:ident as $fldty_last:ty : $fld:ident : $($rest:tt)*) => {
        delegate_method!($fld : $($rest)*);
    };

    ( $fld_last:ident as $fldty_last:ty : $fld:ident as $fldty:ty: $($rest:tt)*) => {
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (self) $(-> $r:ty)* ; $($rest:tt)* ) => {
        fn $fcn ( self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (self) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&self) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&self) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&mut self) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &mut self ) $(-> $r)* {
            (self.$fld).$fcn()
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&mut self) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &mut self ) $(-> $r)* {
            (self.$fld).$fcn()
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&mut self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &mut self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&mut self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &mut self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident ($( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( $( $a : $at ),* ) $(-> $r)* {
            <$fldty>::$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident ($( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( $( $a : $at ),* ) $(-> $r)* {
            <$fldty>::$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

}

#[cfg(test)]
mod tests {
    #[derive(Copy, Clone)]
    struct Inner {
        data: usize,
    }

    impl Inner {
        pub fn new_inner() -> Self {
            Inner { data: 42 }
        }

        pub fn new_inner_add(val: usize) -> Self {
            Inner { data: 42 + val }
        }

        pub fn noop(&self) {}

        pub fn get(&self) -> usize {
            self.data
        }

        pub fn get_add(&self, val: usize) -> usize {
            self.data + val
        }

        pub fn reset(&mut self) -> usize {
            self.data = 0;
            self.data
        }

        pub fn set(&mut self, val: usize) -> usize {
            self.data = val;
            self.data
        }

        pub fn to_data(self) -> usize {
            self.data
        }

        pub fn to_data_add(self, val: usize) -> usize {
            self.data + val
        }
    }

    #[test]
    fn test_delegate() {
        #[derive(Copy, Clone)]
        struct Outer {
            inner: Inner,
        }

        impl Outer {
            delegate_method! {
                inner as Inner:
                pub fn new_inner() -> Inner;
                pub fn new_inner_add(val: usize) -> Inner;
                pub fn noop(&self);
                pub fn get(&self) -> usize;
                pub fn get_add(&self, val: usize) -> usize;
                pub fn reset(&mut self) -> usize;
                pub fn set(&mut self, val: usize) -> usize;
                inner as Inner:
                pub fn to_data(self) -> usize;
                pub fn to_data_add(self, val: usize) -> usize;
            }
        }

        assert_eq!(Outer::new_inner().get(), 42);
        assert_eq!(Outer::new_inner_add(58).get(), 100);

        let mut x = Outer { inner: Inner::new_inner() };

        assert_eq!(x.get(), 42);
        assert_eq!(x.get_add(58), 100);
        x.noop();

        x.reset();
        assert_eq!(x.get(), 0);

        x.set(36);
        assert_eq!(x.get(), 36);

        assert_eq!(x.clone().to_data(), 36);
        assert_eq!(x.clone().to_data_add(4), 40);
    }
}
<commit_msg>Fix the declaration.<commit_after>#[macro_export]
macro_rules! delegate_method {
    ( $fld:ident as $fldty:ty : ) => {

    };

    ( $fld:ident : $($rest:tt)*) => {
        delegate_method!($fld as () : $($rest)*)
    };

    ( $fld_last:ident as $fldty_last:ty : $fld:ident : $($rest:tt)*) => {
        delegate_method!($fld : $($rest)*);
    };

    ( $fld_last:ident as $fldty_last:ty : $fld:ident as $fldty:ty: $($rest:tt)*) => {
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (self) $(-> $r:ty)* ; $($rest:tt)* ) => {
        fn $fcn ( self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (self) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&self) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&self) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &self ) $(-> $r)* {
            (self.$fld).$fcn()
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&mut self) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &mut self ) $(-> $r)* {
            (self.$fld).$fcn()
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&mut self) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &mut self ) $(-> $r)* {
            (self.$fld).$fcn()
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident (&mut self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( &mut self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident (&mut self, $( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( &mut self, $( $a : $at ),* ) $(-> $r)* {
            (self.$fld).$fcn( $( $a ),* )
        }

        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : fn $fcn:ident ($( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        fn $fcn ( $( $a : $at ),* ) $(-> $r)* {
            <$fldty>::$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

    ( $fld:ident as $fldty:ty : pub fn $fcn:ident ($( $a:ident : $at:ty ),* ) $(-> $r:ty)*; $($rest:tt)* ) => {
        pub fn $fcn ( $( $a : $at ),* ) $(-> $r)* {
            <$fldty>::$fcn( $( $a ),* )
        }
        delegate_method!($fld as $fldty: $($rest)*);
    };

}

#[cfg(test)]
mod tests {
    #[derive(Copy, Clone)]
    struct Inner {
        data: usize,
    }

    impl Inner {
        pub fn new_inner() -> Self {
            Inner { data: 42 }
        }

        pub fn new_inner_add(val: usize) -> Self {
            Inner { data: 42 + val }
        }

        pub fn noop(&self) {}

        pub fn get(&self) -> usize {
            self.data
        }

        pub fn get_add(&self, val: usize) -> usize {
            self.data + val
        }

        pub fn reset(&mut self) -> usize {
            self.data = 0;
            self.data
        }

        pub fn set(&mut self, val: usize) -> usize {
            self.data = val;
            self.data
        }

        pub fn to_data(self) -> usize {
            self.data
        }

        pub fn to_data_add(self, val: usize) -> usize {
            self.data + val
        }
    }

    #[test]
    fn test_delegate() {
        #[derive(Copy, Clone)]
        struct Outer {
            inner: Inner,
        }

        impl Outer {
            delegate_method! {
                inner as Inner:
                pub fn new_inner() -> Inner;
                pub fn new_inner_add(val: usize) -> Inner;
                pub fn noop(&self);
                pub fn get(&self) -> usize;
                pub fn get_add(&self, val: usize) -> usize;
                pub fn reset(&mut self) -> usize;
                pub fn set(&mut self, val: usize) -> usize;
                inner as Inner:
                pub fn to_data(self) -> usize;
                pub fn to_data_add(self, val: usize) -> usize;
            }
        }

        assert_eq!(Outer::new_inner().get(), 42);
        assert_eq!(Outer::new_inner_add(58).get(), 100);

        let mut x = Outer { inner: Inner::new_inner() };

        assert_eq!(x.get(), 42);
        assert_eq!(x.get_add(58), 100);
        x.noop();

        x.reset();
        assert_eq!(x.get(), 0);

        x.set(36);
        assert_eq!(x.get(), 36);

        assert_eq!(x.clone().to_data(), 36);
        assert_eq!(x.clone().to_data_add(4), 40);
    }
}
<|endoftext|>


<commit_before>
//! A semi-safe, semi-stateless wrapper around OpenGL 3.3 Core. This library provides various
//! utilities to make using OpenGL 3.3 safer. It uses rust's type system to encode some information
//! which helps prevent common errors. This library is primarily intended to be used for games,
//! but you can also use it to create other graphics applications.

#[cfg(feature = "serialize")]
extern crate serde;

extern crate gl;
extern crate png;
extern crate rusttype;

extern crate cable_math;

mod color;
mod input;
mod window;

pub mod texture;
#[macro_use]
pub mod shader;
pub mod buffer;
pub mod graphics;
pub mod framebuffer;
pub mod font;
pub mod draw_group;
//pub mod ui; // Temporarily disabled. Broken due to changes in font code. Should be rewritten to use draw_group

pub use color::*;
pub use input::*;
pub use window::*;

use std::time::{Instant, Duration};
use std::ops::{Add, Sub, AddAssign, SubAssign};

use cable_math::Vec2;

pub use draw_group::DrawGroup;

/// Utility to track time in a program
#[derive(Clone)]
pub struct Timer {
    start: Instant,
    last: Instant,
}

impl Timer {
    pub fn new() -> Timer {
        let now = Instant::now();

        Timer {
            start: now,
            last: now,
        }
    }

    /// Returns `(time_since_start, time_since_last_tick)`
    pub fn tick(&mut self) -> (Timing, Timing) {
        let now = Instant::now();

        let age = (now - self.start).into();
        let delta = (now - self.last).into();

        self.last = now;

        (age, delta)
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timing(pub u64);

impl Timing {
    pub fn zero() -> Timing { Timing(0) }

    pub fn from_ms(ms: u64) -> Timing { Timing(ms * 1_000_000) }
    pub fn from_secs(s: u64) -> Timing { Timing(s * 1_000_000_000) }
    pub fn from_secs_float(s: f32) -> Timing { Timing((s * 1_000_000_000.0) as u64) }

    /// Converts this timing to seconds, truncating any overflow. 1.999 ms will be converted to 1 ms.
    pub fn as_ms(self) -> u64 { self.0 / 1_000_000 }

    /// Converts this timing to seconds, truncating any overflow. 1.999 seconds will be converted to 1.
    pub fn as_secs(self) -> u64 { self.0 / 1_000_000_000 }

    pub fn as_secs_float(self) -> f32 { self.0 as f32 / 1_000_000_000.0 }

    pub fn max(self, other: Timing) -> Timing {
        ::std::cmp::max(self, other)
    }

    pub fn min(self, other: Timing) -> Timing {
        ::std::cmp::min(self, other)
    }
}

impl Add for Timing {
    type Output = Timing;
    fn add(self, rhs: Timing) -> Timing {
        Timing(self.0 + rhs.0)
    }
}

impl Sub for Timing {
    type Output = Timing;
    fn sub(self, rhs: Timing) -> Timing {
        Timing(self.0 - rhs.0)
    }
}

impl AddAssign for Timing {
    fn add_assign(&mut self, rhs: Timing) {
        self.0 += rhs.0;
    }
}

impl SubAssign for Timing {
    fn sub_assign(&mut self, rhs: Timing) {
        self.0 -= rhs.0;
    }
}

impl From<Duration> for Timing {
    fn from(d: Duration) -> Timing {
        Timing(d.as_secs()*1_000_000_000 + (d.subsec_nanos() as u64))
    }
}

impl From<Timing> for Duration {
    fn from(t: Timing) -> Duration {
        let nanos = t.0 % 1_000_000_000;
        let secs = t.0 / 1_000_000_000;
        Duration::new(secs, nanos as u32)
    }
}

#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Region {
    pub min: Vec2<f32>,
    pub max: Vec2<f32>,
}

impl Region {
    pub fn center(&self) -> Vec2<f32> { (self.min + self.max) / 2.0 }

    pub fn width(&self) -> f32        { self.max.x - self.min.x }
    pub fn height(&self) -> f32       { self.max.y - self.min.y }

    pub fn size(&self) -> Vec2<f32>   { self.max - self.min }

    /// Checks if the given point is inside this region.
    pub fn contains(&self, p: Vec2<f32>) -> bool {
        p.x > self.min.x && p.x < self.max.x &&
        p.y > self.min.y && p.y < self.max.y
    }

    /// Width divided by height.
    pub fn aspect(&self) -> f32 {
        let size = self.size();
        size.x / size.y
    }

    /// Swaps `min` and `max` along the y axis
    pub fn flip_y(self) -> Region {
        Region {
            min: Vec2::new(self.min.x, self.max.y),
            max: Vec2::new(self.max.x, self.min.y),
        }
    }

    /// Swaps `min` and `max` along the x axis
    pub fn flip_x(self) -> Region {
        Region {
            min: Vec2::new(self.max.x, self.min.y),
            max: Vec2::new(self.min.x, self.max.y),
        }
    }

    /// Returns the region in which this region overlaps the given other region. This might produce
    /// a negative region.
    pub fn overlap(self, other: Region) -> Region {
        Region {
            min: Vec2 {
                x: f32::max(self.min.x, other.min.x),
                y: f32::max(self.min.y, other.min.y),
            },
            max: Vec2 {
                x: f32::min(self.max.x, other.max.x),
                y: f32::min(self.max.y, other.max.y),
            },
        }
    }

    /// Moves `min` to `(0, 0)` but preserves width and height.
    pub fn unpositioned(self) -> Region {
        Region {
            min: Vec2::zero(),
            max: self.max - self.min,
        }
    }
}
<commit_msg>top_right and bottom_left for region<commit_after>
//! A semi-safe, semi-stateless wrapper around OpenGL 3.3 Core. This library provides various
//! utilities to make using OpenGL 3.3 safer. It uses rust's type system to encode some information
//! which helps prevent common errors. This library is primarily intended to be used for games,
//! but you can also use it to create other graphics applications.

#[cfg(feature = "serialize")]
extern crate serde;

extern crate gl;
extern crate png;
extern crate rusttype;

extern crate cable_math;

mod color;
mod input;
mod window;

pub mod texture;
#[macro_use]
pub mod shader;
pub mod buffer;
pub mod graphics;
pub mod framebuffer;
pub mod font;
pub mod draw_group;
//pub mod ui; // Temporarily disabled. Broken due to changes in font code. Should be rewritten to use draw_group

pub use color::*;
pub use input::*;
pub use window::*;

use std::time::{Instant, Duration};
use std::ops::{Add, Sub, AddAssign, SubAssign};

use cable_math::Vec2;

pub use draw_group::DrawGroup;

/// Utility to track time in a program
#[derive(Clone)]
pub struct Timer {
    start: Instant,
    last: Instant,
}

impl Timer {
    pub fn new() -> Timer {
        let now = Instant::now();

        Timer {
            start: now,
            last: now,
        }
    }

    /// Returns `(time_since_start, time_since_last_tick)`
    pub fn tick(&mut self) -> (Timing, Timing) {
        let now = Instant::now();

        let age = (now - self.start).into();
        let delta = (now - self.last).into();

        self.last = now;

        (age, delta)
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timing(pub u64);

impl Timing {
    pub fn zero() -> Timing { Timing(0) }

    pub fn from_ms(ms: u64) -> Timing { Timing(ms * 1_000_000) }
    pub fn from_secs(s: u64) -> Timing { Timing(s * 1_000_000_000) }
    pub fn from_secs_float(s: f32) -> Timing { Timing((s * 1_000_000_000.0) as u64) }

    /// Converts this timing to seconds, truncating any overflow. 1.999 ms will be converted to 1 ms.
    pub fn as_ms(self) -> u64 { self.0 / 1_000_000 }

    /// Converts this timing to seconds, truncating any overflow. 1.999 seconds will be converted to 1.
    pub fn as_secs(self) -> u64 { self.0 / 1_000_000_000 }

    pub fn as_secs_float(self) -> f32 { self.0 as f32 / 1_000_000_000.0 }

    pub fn max(self, other: Timing) -> Timing {
        ::std::cmp::max(self, other)
    }

    pub fn min(self, other: Timing) -> Timing {
        ::std::cmp::min(self, other)
    }
}

impl Add for Timing {
    type Output = Timing;
    fn add(self, rhs: Timing) -> Timing {
        Timing(self.0 + rhs.0)
    }
}

impl Sub for Timing {
    type Output = Timing;
    fn sub(self, rhs: Timing) -> Timing {
        Timing(self.0 - rhs.0)
    }
}

impl AddAssign for Timing {
    fn add_assign(&mut self, rhs: Timing) {
        self.0 += rhs.0;
    }
}

impl SubAssign for Timing {
    fn sub_assign(&mut self, rhs: Timing) {
        self.0 -= rhs.0;
    }
}

impl From<Duration> for Timing {
    fn from(d: Duration) -> Timing {
        Timing(d.as_secs()*1_000_000_000 + (d.subsec_nanos() as u64))
    }
}

impl From<Timing> for Duration {
    fn from(t: Timing) -> Duration {
        let nanos = t.0 % 1_000_000_000;
        let secs = t.0 / 1_000_000_000;
        Duration::new(secs, nanos as u32)
    }
}

#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Region {
    pub min: Vec2<f32>,
    pub max: Vec2<f32>,
}

impl Region {
    pub fn center(&self) -> Vec2<f32> { (self.min + self.max) / 2.0 }

    pub fn width(&self) -> f32        { self.max.x - self.min.x }
    pub fn height(&self) -> f32       { self.max.y - self.min.y }

    pub fn size(&self) -> Vec2<f32>   { self.max - self.min }

    /// Checks if the given point is inside this region.
    pub fn contains(&self, p: Vec2<f32>) -> bool {
        p.x > self.min.x && p.x < self.max.x &&
        p.y > self.min.y && p.y < self.max.y
    }

    /// Width divided by height.
    pub fn aspect(&self) -> f32 {
        let size = self.size();
        size.x / size.y
    }

    /// Swaps `min` and `max` along the y axis
    pub fn flip_y(self) -> Region {
        Region {
            min: Vec2::new(self.min.x, self.max.y),
            max: Vec2::new(self.max.x, self.min.y),
        }
    }

    /// Swaps `min` and `max` along the x axis
    pub fn flip_x(self) -> Region {
        Region {
            min: Vec2::new(self.max.x, self.min.y),
            max: Vec2::new(self.min.x, self.max.y),
        }
    }

    /// Returns the region in which this region overlaps the given other region. This might produce
    /// a negative region.
    pub fn overlap(self, other: Region) -> Region {
        Region {
            min: Vec2 {
                x: f32::max(self.min.x, other.min.x),
                y: f32::max(self.min.y, other.min.y),
            },
            max: Vec2 {
                x: f32::min(self.max.x, other.max.x),
                y: f32::min(self.max.y, other.max.y),
            },
        }
    }

    /// Moves `min` to `(0, 0)` but preserves width and height.
    pub fn unpositioned(self) -> Region {
        Region {
            min: Vec2::zero(),
            max: self.max - self.min,
        }
    }

    /// Assumes that `min` is top left and `max` bottom right
    pub fn top_right(self) -> Vec2<f32> {
        Vec2::new(min.y, max.x)
    }

    /// Assumes that `min` is top left and `max` bottom right
    pub fn bottom_left(self) -> Vec2<f32> {
        Vec2::new(max.y, min.x)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;

mod commands;
mod services;

use commands::{Command, CommandExecutor};
use std::error;

pub struct SovrinClient {
    command_executor: CommandExecutor
}

impl SovrinClient {
    pub fn new() -> SovrinClient {
        SovrinClient {
            command_executor: CommandExecutor::new()
        }
    }

    pub fn set_did(&self, did: String, cb: Box<Fn(Result<(), Box<error::Error>>) + Send>) {
        self.command_executor.send(Command::SetDidCommand(did, cb));
    }

    pub fn create_master_secret() {

    }

    pub fn create_keys(schema: String) {

    }

    pub fn create_context_attribute(i_a: String, user_id: String) {

    }

    pub fn issue_accumulator(schema: String, i_a: String, l: String,
                             public_key_revocation: String) {

    }

    pub fn issue_claim(attributes: String, accumulator: String,i_a: String, i: String,
                       claim_request: String, context_attribute: String, public_key: String,
                       secret_key: String, public_key_revocation: String,
                       secret_key_revocation: String, tails: String,
                       secret_key_accumulator: String) {

    }

    pub fn create_claim_request(master_secret: String, public_key: String,
                                public_key_revocation: String, request_non_revocation: String) {

    }

    pub fn create_proof(proof_input: String, nonce: String, claims: String,
                        public_key_revocation: String, accum: String, public_key: String,
                        master_secret: String) {

    }

    pub fn verify_proof(proof_input: String, proof: String, revealed_attributes: String,
                        nonce: String, public_key_revocation: String,
                        public_key_accumulator: String, accumulator: String,
                        public_key: String, attributes: String) {

    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::channel;

    #[test]
    fn sovrin_client_can_be_created() {
        let sovrin_client = SovrinClient::new();
        assert!(true, "No crashes on SovrinClient::new");
    }

    #[test]
    fn sovrin_client_can_be_dropped() {
        fn drop_test() {
            let sovrin_client = SovrinClient::new();
        }

        drop_test();
        assert!(true, "No crashes on SovrinClient::drop");
    }

    #[test]
    fn set_did_method_can_be_called() {
        let (sender, receiver) = channel();

        let cb = Box::new(move |result| {
            match result {
                Ok(val) => sender.send("OK"),
                Err(err) => sender.send("ERROR")
            };
        });

        let sovrin_client = SovrinClient::new();
        sovrin_client.set_did("DID0".to_string(), cb);

        match receiver.recv() {
            Ok(result) => {
                assert_eq!("OK", result);
            }
            Err(err) => {
                panic!("Error on result recv: {:?}", err);
            }
        }
    }
}<commit_msg>added callback<commit_after>#[macro_use]
extern crate log;

mod commands;
mod services;

use commands::{Command, CommandExecutor};
use std::error;

pub struct SovrinClient {
    command_executor: CommandExecutor
}

impl SovrinClient {
    pub fn new() -> SovrinClient {
        SovrinClient {
            command_executor: CommandExecutor::new()
        }
    }

    pub fn set_did(&self, did: String, cb: Box<Fn(Result<(), Box<error::Error>>) + Send>) {
        self.command_executor.send(Command::SetDidCommand(did, cb));
    }

    pub fn create_master_secret(cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }

    pub fn create_keys(schema: String,
                       cb: Box<Fn(Result<((String, String)), Box<error::Error>>) + Send>) {

    }

    pub fn create_context_attribute(i_a: String, user_id: String,
                                    cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }

    pub fn issue_accumulator(schema: String, i_a: String, l: String,
                             public_key_revocation: String,
                             cb: Box<Fn(
                                 Result<((String, String, String, String)),
                                 Box<error::Error>>
                             ) + Send>) {

    }

    pub fn issue_claim(attributes: String, accumulator: String,i_a: String, i: String,
                       claim_request: String, context_attribute: String, public_key: String,
                       secret_key: String, public_key_revocation: String,
                       secret_key_revocation: String, tails: String,
                       secret_key_accumulator: String,
                       cb: Box<Fn(Result<(String, String), Box<error::Error>>) + Send>) {

    }

    pub fn create_claim_request(master_secret: String, public_key: String,
                                public_key_revocation: String, request_non_revocation: String,
                                cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }

    pub fn create_proof(proof_input: String, nonce: String, claims: String,
                        public_key_revocation: String, accum: String, public_key: String,
                        master_secret: String,
                        cb: Box<Fn(Result<(String, String), Box<error::Error>>) + Send>) {

    }

    pub fn verify_proof(proof_input: String, proof: String, revealed_attributes: String,
                        nonce: String, public_key_revocation: String,
                        public_key_accumulator: String, accumulator: String,
                        public_key: String, attributes: String,
                        cb: Box<Fn(Result<(String), Box<error::Error>>) + Send>) {

    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::channel;

    #[test]
    fn sovrin_client_can_be_created() {
        let sovrin_client = SovrinClient::new();
        assert!(true, "No crashes on SovrinClient::new");
    }

    #[test]
    fn sovrin_client_can_be_dropped() {
        fn drop_test() {
            let sovrin_client = SovrinClient::new();
        }

        drop_test();
        assert!(true, "No crashes on SovrinClient::drop");
    }

    #[test]
    fn set_did_method_can_be_called() {
        let (sender, receiver) = channel();

        let cb = Box::new(move |result| {
            match result {
                Ok(val) => sender.send("OK"),
                Err(err) => sender.send("ERROR")
            };
        });

        let sovrin_client = SovrinClient::new();
        sovrin_client.set_did("DID0".to_string(), cb);

        match receiver.recv() {
            Ok(result) => {
                assert_eq!("OK", result);
            }
            Err(err) => {
                panic!("Error on result recv: {:?}", err);
            }
        }
    }
}<|endoftext|>


<commit_before>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

//! TiKV - A distributed key/value database
//!
//! TiKV ("Ti" stands for Titanium) is an open source distributed
//! transactional key-value database. Unlike other traditional NoSQL
//! systems, TiKV not only provides classical key-value APIs, but also
//! transactional APIs with ACID compliance. TiKV was originally
//! created to complement [TiDB], a distributed HTAP database
//! compatible with the MySQL protocol.
//!
//! [TiDB]: https://github.com/pingcap/tidb
//!
//! The design of TiKV is inspired by some great distributed systems
//! from Google, such as BigTable, Spanner, and Percolator, and some
//! of the latest achievements in academia in recent years, such as
//! the Raft consensus algorithm.

#![crate_type = "lib"]
#![cfg_attr(test, feature(test))]
#![recursion_limit = "400"]
#![feature(cell_update)]
#![feature(proc_macro_hygiene)]
#![feature(specialization)]
#![feature(const_fn)]
#![feature(box_patterns)]
#![feature(shrink_to)]
#![feature(drain_filter)]
#![feature(str_strip)]

#[macro_use(fail_point)]
extern crate fail;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog_derive;
#[macro_use]
extern crate slog_global;
#[macro_use]
extern crate derive_more;
#[macro_use]
extern crate more_asserts;
#[macro_use]
extern crate vlog;
#[macro_use]
extern crate tikv_util;
#[macro_use]
extern crate failure;

#[cfg(test)]
extern crate test;

extern crate encryption;

pub mod config;
pub mod coprocessor;
pub mod import;
pub mod read_pool;
pub mod server;
pub mod storage;

/// Returns the tikv version information.
pub fn tikv_version_info() -> String {
    let fallback = "Unknown (env var does not exist when building)";
    format!(
        "\nRelease Version:   {}\
         \nGit Commit Hash:   {}\
         \nGit Commit Branch: {}\
         \nUTC Build Time:    {}\
         \nRust Version:      {}\
         \nEnable Features:   {}\
         \nProfile:           {}",
        env!("CARGO_PKG_VERSION"),
        option_env!("TIKV_BUILD_GIT_HASH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_GIT_BRANCH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_TIME").unwrap_or(fallback),
        option_env!("TIKV_BUILD_RUSTC_VERSION").unwrap_or(fallback),
        option_env!("TIKV_ENABLE_FEATURES")
            .unwrap_or(fallback)
            .trim(),
        option_env!("TIKV_PROFILE").unwrap_or(fallback),
    )
}

/// Prints the tikv version information to the standard output.
pub fn log_tikv_info() {
    info!("Welcome to TiKV");
    for line in tikv_version_info().lines() {
        info!("{}", line);
    }
}
<commit_msg>remove empty log at startup (#7341)<commit_after>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

//! TiKV - A distributed key/value database
//!
//! TiKV ("Ti" stands for Titanium) is an open source distributed
//! transactional key-value database. Unlike other traditional NoSQL
//! systems, TiKV not only provides classical key-value APIs, but also
//! transactional APIs with ACID compliance. TiKV was originally
//! created to complement [TiDB], a distributed HTAP database
//! compatible with the MySQL protocol.
//!
//! [TiDB]: https://github.com/pingcap/tidb
//!
//! The design of TiKV is inspired by some great distributed systems
//! from Google, such as BigTable, Spanner, and Percolator, and some
//! of the latest achievements in academia in recent years, such as
//! the Raft consensus algorithm.

#![crate_type = "lib"]
#![cfg_attr(test, feature(test))]
#![recursion_limit = "400"]
#![feature(cell_update)]
#![feature(proc_macro_hygiene)]
#![feature(specialization)]
#![feature(const_fn)]
#![feature(box_patterns)]
#![feature(shrink_to)]
#![feature(drain_filter)]
#![feature(str_strip)]

#[macro_use(fail_point)]
extern crate fail;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog_derive;
#[macro_use]
extern crate slog_global;
#[macro_use]
extern crate derive_more;
#[macro_use]
extern crate more_asserts;
#[macro_use]
extern crate vlog;
#[macro_use]
extern crate tikv_util;
#[macro_use]
extern crate failure;

#[cfg(test)]
extern crate test;

extern crate encryption;

pub mod config;
pub mod coprocessor;
pub mod import;
pub mod read_pool;
pub mod server;
pub mod storage;

/// Returns the tikv version information.
pub fn tikv_version_info() -> String {
    let fallback = "Unknown (env var does not exist when building)";
    format!(
        "\nRelease Version:   {}\
         \nGit Commit Hash:   {}\
         \nGit Commit Branch: {}\
         \nUTC Build Time:    {}\
         \nRust Version:      {}\
         \nEnable Features:   {}\
         \nProfile:           {}",
        env!("CARGO_PKG_VERSION"),
        option_env!("TIKV_BUILD_GIT_HASH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_GIT_BRANCH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_TIME").unwrap_or(fallback),
        option_env!("TIKV_BUILD_RUSTC_VERSION").unwrap_or(fallback),
        option_env!("TIKV_ENABLE_FEATURES")
            .unwrap_or(fallback)
            .trim(),
        option_env!("TIKV_PROFILE").unwrap_or(fallback),
    )
}

/// Prints the tikv version information to the standard output.
pub fn log_tikv_info() {
    info!("Welcome to TiKV");
    for line in tikv_version_info().lines().filter(|s| !s.is_empty()) {
        info!("{}", line);
    }
}
<|endoftext|>


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

    #[test]
    fn push_get() {
        let n = BRANCH_FACTOR.pow(2) + 1;
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        println!("{:#?}", v);
        for i in 0..n {
            println!("{}:", i);
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    }

    #[test]
    fn false_get() {
        let v = PVec::new().push(0);
        for n in 0..BRANCH_FACTOR {
            let i = (n + 1) * BRANCH_FACTOR;
            println!("n: {}, i: {}", n, i);
            assert_eq!(v.get(i), None);
        }
    }
}

use std::sync::Arc;
use std::mem;

#[cfg(feature = "narrow_branching")]
const BRANCH_EXPONENT: usize = 2;
#[cfg(feature = "narrow_branching")]
const BRANCH_FACTOR: usize = 4; // 2^BRANCH_EXPONENT

#[cfg(not(feature = "narrow_branching"))]
const BRANCH_EXPONENT: usize = 5;
#[cfg(not(feature = "narrow_branching"))]
const BRANCH_FACTOR: usize = 32; // 2^BRANCH_EXPONENT

#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Default)]
pub struct PVec<T> {
    root: Node<T>,
    len: usize,
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
enum Node<T> {
    Branch {
        children: [Option<Arc<PVec<T>>>; BRANCH_FACTOR],
        // depth won't ever be higher than log_{BRANCH_FACTOR}(MAX: usize)
        depth: u8,
    },
    Leaf { elements: [Option<T>; BRANCH_FACTOR], },
}

#[cfg(feature = "narrow_branching")]
macro_rules! empty_arr {
    () => {
        [None, None,
         None, None]
    }
}

#[cfg(not(feature = "narrow_branching"))]
macro_rules! empty_arr {
    () => {
        [None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None]
    }
}

impl<T> Default for Node<T> {
    fn default() -> Self {
        Node::Leaf { elements: empty_arr!() }
    }
}

impl<T: Clone> Clone for Node<T> {
    fn clone(&self) -> Self {
        match *self {
            Node::Branch {
                ref children,
                ref depth,
            } => {
                let mut kids = empty_arr!();
                for i in 0..children.len() {
                    kids[i] = children[i].clone()
                }
                Node::Branch {
                    children: kids,
                    depth: *depth,
                }
            }
            Node::Leaf { ref elements } => {
                let mut elems = empty_arr!();
                for i in 0..elements.len() {
                    elems[i] = elements[i].clone()
                }
                Node::Leaf { elements: elems }
            }
        }
    }
}

use std::fmt::Debug;

impl<T: Clone + Debug> PVec<T> {
    pub fn new() -> Self {
        PVec {
            root: Node::default(),
            len: 0,
        }
    }

    // For elegance, this would be recursive (and there wouldn't be a depth field on `Branch`),
    // but I'm worried about the performance of that.
    fn depth(&self) -> u8 {
        match self.root {
            Node::Branch { ref depth, .. } => *depth,
            Node::Leaf { .. } => 0,
        }
    }

    pub fn push(self, element: T) -> Self {
        if self.len < BRANCH_FACTOR {
            let mut new = self.clone();
            match new.root {
                Node::Leaf { ref mut elements } => {
                    elements[new.len] = Some(element);
                    new.len += 1;
                }
                Node::Branch { ref mut children, .. } => {
                    let i = self.len;
                    let old = mem::replace(&mut children[i], None);
                    match old {
                        Some(child_ref) => {
                            let child = (*child_ref).clone().push(element);
                            if child.len == BRANCH_FACTOR {
                                new.len += 1;
                            }
                            mem::replace(&mut children[i], Some(Arc::new(child)));
                        }
                        None => {
                            let child = PVec::new().push(element);
                            mem::replace(&mut children[i], Some(Arc::new(child)));
                        }
                    }
                }
            }
            new
        } else {
            let mut children = empty_arr!();
            let depth = self.depth();
            children[0] = Some(Arc::new(self));
            children[1] = Some(Arc::new(PVec::new().push(element)));
            PVec {
                root: Node::Branch {
                    children: children,
                    depth: depth + 1,
                },
                len: 1,
            }
        }
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        let i = (index >> (BRANCH_EXPONENT * (self.depth() as usize))) & (BRANCH_FACTOR - 1);
        match self.root {
            Node::Branch { ref children, .. } => children[i].as_ref().and_then(|c| c.get(index)),
            Node::Leaf { ref elements } => elements[i].as_ref(),
        }
    }
}
<commit_msg>Make `push_get' test large enough<commit_after>#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn push_get() {
        let n = BRANCH_FACTOR.pow(3) + 1;
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        println!("{:#?}", v);
        for i in 0..n {
            println!("{}:", i);
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    }

    #[test]
    fn false_get() {
        let v = PVec::new().push(0);
        for n in 0..BRANCH_FACTOR {
            let i = (n + 1) * BRANCH_FACTOR;
            println!("n: {}, i: {}", n, i);
            assert_eq!(v.get(i), None);
        }
    }
}

use std::sync::Arc;
use std::mem;

#[cfg(feature = "narrow_branching")]
const BRANCH_EXPONENT: usize = 2;
#[cfg(feature = "narrow_branching")]
const BRANCH_FACTOR: usize = 4; // 2^BRANCH_EXPONENT

#[cfg(not(feature = "narrow_branching"))]
const BRANCH_EXPONENT: usize = 5;
#[cfg(not(feature = "narrow_branching"))]
const BRANCH_FACTOR: usize = 32; // 2^BRANCH_EXPONENT

#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Default)]
pub struct PVec<T> {
    root: Node<T>,
    len: usize,
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
enum Node<T> {
    Branch {
        children: [Option<Arc<PVec<T>>>; BRANCH_FACTOR],
        // depth won't ever be higher than log_{BRANCH_FACTOR}(MAX: usize)
        depth: u8,
    },
    Leaf { elements: [Option<T>; BRANCH_FACTOR], },
}

#[cfg(feature = "narrow_branching")]
macro_rules! empty_arr {
    () => {
        [None, None,
         None, None]
    }
}

#[cfg(not(feature = "narrow_branching"))]
macro_rules! empty_arr {
    () => {
        [None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None,
         None, None, None, None]
    }
}

impl<T> Default for Node<T> {
    fn default() -> Self {
        Node::Leaf { elements: empty_arr!() }
    }
}

impl<T: Clone> Clone for Node<T> {
    fn clone(&self) -> Self {
        match *self {
            Node::Branch {
                ref children,
                ref depth,
            } => {
                let mut kids = empty_arr!();
                for i in 0..children.len() {
                    kids[i] = children[i].clone()
                }
                Node::Branch {
                    children: kids,
                    depth: *depth,
                }
            }
            Node::Leaf { ref elements } => {
                let mut elems = empty_arr!();
                for i in 0..elements.len() {
                    elems[i] = elements[i].clone()
                }
                Node::Leaf { elements: elems }
            }
        }
    }
}

use std::fmt::Debug;

impl<T: Clone + Debug> PVec<T> {
    pub fn new() -> Self {
        PVec {
            root: Node::default(),
            len: 0,
        }
    }

    // For elegance, this would be recursive (and there wouldn't be a depth field on `Branch`),
    // but I'm worried about the performance of that.
    fn depth(&self) -> u8 {
        match self.root {
            Node::Branch { ref depth, .. } => *depth,
            Node::Leaf { .. } => 0,
        }
    }

    pub fn push(self, element: T) -> Self {
        if self.len < BRANCH_FACTOR {
            let mut new = self.clone();
            match new.root {
                Node::Leaf { ref mut elements } => {
                    elements[new.len] = Some(element);
                    new.len += 1;
                }
                Node::Branch { ref mut children, .. } => {
                    let i = self.len;
                    let old = mem::replace(&mut children[i], None);
                    match old {
                        Some(child_ref) => {
                            let child = (*child_ref).clone().push(element);
                            if child.len == BRANCH_FACTOR {
                                new.len += 1;
                            }
                            mem::replace(&mut children[i], Some(Arc::new(child)));
                        }
                        None => {
                            let child = PVec::new().push(element);
                            mem::replace(&mut children[i], Some(Arc::new(child)));
                        }
                    }
                }
            }
            new
        } else {
            let mut children = empty_arr!();
            let depth = self.depth();
            children[0] = Some(Arc::new(self));
            children[1] = Some(Arc::new(PVec::new().push(element)));
            PVec {
                root: Node::Branch {
                    children: children,
                    depth: depth + 1,
                },
                len: 1,
            }
        }
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        let i = (index >> (BRANCH_EXPONENT * (self.depth() as usize))) & (BRANCH_FACTOR - 1);
        match self.root {
            Node::Branch { ref children, .. } => children[i].as_ref().and_then(|c| c.get(index)),
            Node::Leaf { ref elements } => elements[i].as_ref(),
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "spinlock"]
#![experimental]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]

//! This crate provides a thread-safe data container.
//!
//! # Description
//!
//! This structure behaves a lot like a normal Mutex. There are some differences:
//!
//! - It may be used outside the runtime.
//!   - A normal mutex will fail when used without the runtime, this will just lock
//!   - When the runtime is present, it will call the deschedule function when appropriate
//! - No lock poisoning. When a fail occurs when the lock is held, no guarantees are made
//!
//! When calling rust functions from bare threads, such as C `pthread`s, this lock will be very
//! helpfull. In other cases however, you are encouraged to use the locks from the standard
//! library.
//!
//! # Simple example
//!
//! ```
//! use spinlock::Spinlock;
//! let spinlock = Spinlock::new(0u);
//!
//! // Modify the data
//! {
//!     let mut data = spinlock.lock();
//!     *data = 2;
//! }
//!
//! // Read the data
//! let answer =
//! {
//!     let data = spinlock.lock();
//!     *data
//! };
//!
//! assert_eq!(answer, 2u);
//! ```
//!
//! # Thread-safety example
//!
//! ```
//! use spinlock::Spinlock;
//! use std::sync::{Arc, Barrier};
//!
//! let numthreads = 1000;
//! let spinlock = Arc::new(Spinlock::new(0u));
//!
//! // We use a barrier to ensure the readout happens after all writing
//! let barrier = Arc::new(Barrier::new(numthreads + 1));
//!
//! for _ in range(0, numthreads)
//! {
//!     let my_barrier = barrier.clone();
//!     let my_lock = spinlock.clone();
//!     spawn(proc()
//!     {
//!         let mut guard = my_lock.lock();
//!         *guard += 1;
//!
//!         // Release the lock to prevent a deadlock
//!         drop(guard);
//!         my_barrier.wait();
//!     });
//! }
//!
//! barrier.wait();
//!
//! let answer = { *spinlock.lock() };
//! assert_eq!(answer, numthreads);
//! ```

use std::sync::atomics::{AtomicBool, SeqCst};
use std::ty::Unsafe;
use std::rt::local::Local;
use std::rt::task::Task;

/// A wrapper for the data giving access in a thread-safe manner
pub struct Spinlock<T>
{
    lock: AtomicBool,
    data: Unsafe<T>,
}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
#[experimental]
pub struct SpinlockGuard<'a, T:'a>
{
    lock: &'a AtomicBool,
    data: &'a mut T,
}

impl<T: Send> Spinlock<T>
{
    /// Creates a new spinlock wrapping the supplied data.
    #[unstable]
    pub fn new(user_data: T) -> Spinlock<T>
    {
        Spinlock
        {
            lock: AtomicBool::new(false),
            data: Unsafe::new(user_data),
        }
    }

    #[inline(always)]
    fn lock_check(&self) -> bool
    {
        self.lock.compare_and_swap(false, true, SeqCst) != false
    }

    fn obtain_lock(&self)
    {
        if Local::exists(None::<Task>)
        {
            self.obtain_lock_with_runtime();
        }
        else
        {
            self.obtain_lock_without_runtime();
        }
    }

    fn obtain_lock_with_runtime(&self)
    {
        while self.lock_check()
        {
            std::task::deschedule();
        }
    }

    fn obtain_lock_without_runtime(&self)
    {
        while self.lock_check()
        {
            // Do nothing
        }
    }

    /// Locks the spinlock and returns a guard.
    ///
    /// The returned value may be dereferenced for data access
    /// and the lock will be dropped when the guard falls out of scope.
    ///
    /// ```
    /// let mylock = spinlock::Spinlock::new(0u);
    /// {
    ///     let mut data = mylock.lock();
    ///     // The lock is now locked and the data can be accessed
    ///     *data += 1;
    /// }
    /// // The lock is dropped
    /// ```
    pub fn lock(&self) -> SpinlockGuard<T>
    {
        self.obtain_lock();
        SpinlockGuard
        {
            lock: &self.lock,
            data: unsafe { &mut *self.data.get() },
        }
    }
}

impl<'a, T: Send> Deref<T> for SpinlockGuard<'a, T>
{
    fn deref<'a>(&'a self) -> &'a T { &*self.data }
}

impl<'a, T: Send> DerefMut<T> for SpinlockGuard<'a, T>
{
    fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self.data }
}

#[unsafe_destructor]
impl<'a, T: Send> Drop for SpinlockGuard<'a, T>
{
    /// The dropping of the SpinlockGuard will release the lock it was created from.
    fn drop(&mut self)
    {
        self.lock.store(false, SeqCst);
    }
}
<commit_msg>Ensure the doc will stay at 100%<commit_after>#![crate_name = "spinlock"]
#![experimental]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]
#![warn(missing_doc)]

//! This crate provides a thread-safe data container.
//!
//! # Description
//!
//! This structure behaves a lot like a normal Mutex. There are some differences:
//!
//! - It may be used outside the runtime.
//!   - A normal mutex will fail when used without the runtime, this will just lock
//!   - When the runtime is present, it will call the deschedule function when appropriate
//! - No lock poisoning. When a fail occurs when the lock is held, no guarantees are made
//!
//! When calling rust functions from bare threads, such as C `pthread`s, this lock will be very
//! helpfull. In other cases however, you are encouraged to use the locks from the standard
//! library.
//!
//! # Simple example
//!
//! ```
//! use spinlock::Spinlock;
//! let spinlock = Spinlock::new(0u);
//!
//! // Modify the data
//! {
//!     let mut data = spinlock.lock();
//!     *data = 2;
//! }
//!
//! // Read the data
//! let answer =
//! {
//!     let data = spinlock.lock();
//!     *data
//! };
//!
//! assert_eq!(answer, 2u);
//! ```
//!
//! # Thread-safety example
//!
//! ```
//! use spinlock::Spinlock;
//! use std::sync::{Arc, Barrier};
//!
//! let numthreads = 1000;
//! let spinlock = Arc::new(Spinlock::new(0u));
//!
//! // We use a barrier to ensure the readout happens after all writing
//! let barrier = Arc::new(Barrier::new(numthreads + 1));
//!
//! for _ in range(0, numthreads)
//! {
//!     let my_barrier = barrier.clone();
//!     let my_lock = spinlock.clone();
//!     spawn(proc()
//!     {
//!         let mut guard = my_lock.lock();
//!         *guard += 1;
//!
//!         // Release the lock to prevent a deadlock
//!         drop(guard);
//!         my_barrier.wait();
//!     });
//! }
//!
//! barrier.wait();
//!
//! let answer = { *spinlock.lock() };
//! assert_eq!(answer, numthreads);
//! ```

use std::sync::atomics::{AtomicBool, SeqCst};
use std::ty::Unsafe;
use std::rt::local::Local;
use std::rt::task::Task;

/// A wrapper for the data giving access in a thread-safe manner
pub struct Spinlock<T>
{
    lock: AtomicBool,
    data: Unsafe<T>,
}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
#[experimental]
pub struct SpinlockGuard<'a, T:'a>
{
    lock: &'a AtomicBool,
    data: &'a mut T,
}

impl<T: Send> Spinlock<T>
{
    /// Creates a new spinlock wrapping the supplied data.
    #[unstable]
    pub fn new(user_data: T) -> Spinlock<T>
    {
        Spinlock
        {
            lock: AtomicBool::new(false),
            data: Unsafe::new(user_data),
        }
    }

    #[inline(always)]
    fn lock_check(&self) -> bool
    {
        self.lock.compare_and_swap(false, true, SeqCst) != false
    }

    fn obtain_lock(&self)
    {
        if Local::exists(None::<Task>)
        {
            self.obtain_lock_with_runtime();
        }
        else
        {
            self.obtain_lock_without_runtime();
        }
    }

    fn obtain_lock_with_runtime(&self)
    {
        while self.lock_check()
        {
            std::task::deschedule();
        }
    }

    fn obtain_lock_without_runtime(&self)
    {
        while self.lock_check()
        {
            // Do nothing
        }
    }

    /// Locks the spinlock and returns a guard.
    ///
    /// The returned value may be dereferenced for data access
    /// and the lock will be dropped when the guard falls out of scope.
    ///
    /// ```
    /// let mylock = spinlock::Spinlock::new(0u);
    /// {
    ///     let mut data = mylock.lock();
    ///     // The lock is now locked and the data can be accessed
    ///     *data += 1;
    /// }
    /// // The lock is dropped
    /// ```
    pub fn lock(&self) -> SpinlockGuard<T>
    {
        self.obtain_lock();
        SpinlockGuard
        {
            lock: &self.lock,
            data: unsafe { &mut *self.data.get() },
        }
    }
}

impl<'a, T: Send> Deref<T> for SpinlockGuard<'a, T>
{
    fn deref<'a>(&'a self) -> &'a T { &*self.data }
}

impl<'a, T: Send> DerefMut<T> for SpinlockGuard<'a, T>
{
    fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self.data }
}

#[unsafe_destructor]
impl<'a, T: Send> Drop for SpinlockGuard<'a, T>
{
    /// The dropping of the SpinlockGuard will release the lock it was created from.
    fn drop(&mut self)
    {
        self.lock.store(false, SeqCst);
    }
}
<|endoftext|>