<commit_before>use data::{get_map_tile, load_map_file};
use game::constants::{MAP_A_FILE_PATH, MAP_B_FILE_PATH, TILE_MAP_BUF_LENGTH, TILES_PCS_H, TILES_PCS_W};
use shaders::TileMapData;
use tiled::Map;

fn calc_index(x_pos: usize, y_pos: usize) -> usize {
  (y_pos * TILES_PCS_W) + x_pos
}

fn populate_tile_map<'a>(tiles: &'a mut Vec<TileMapData>, map: &Map) -> &'a mut Vec<TileMapData> {
  for y_pos in 0..TILES_PCS_H {
    for x_pos in 0..TILES_PCS_W {
      let map_val = get_map_tile(map, 0, x_pos, y_pos);
      let tex_x = map_val % 32;
      let y = (map_val - tex_x) / 32;
      let x = if tex_x < 1 { 1 } else { tex_x - 1 };
      let idx = calc_index(x_pos, y_pos);
      tiles[idx] = TileMapData::new([x as f32, y as f32, 0.0, 0.0]);
    }
  }
  tiles
}

#[derive(Debug)]
pub struct Terrain {
  pub tiles: Vec<TileMapData>,
  pub tile_sets: [Map; 2],
}

impl Terrain {
  pub fn new() -> Terrain {
    let mut map_data = Vec::with_capacity(TILE_MAP_BUF_LENGTH);

    for _ in 0..TILE_MAP_BUF_LENGTH {
      map_data.push(TileMapData::new_empty());
    }

    let map_a = load_map_file(MAP_A_FILE_PATH);
    let map_b = load_map_file(MAP_B_FILE_PATH);

    Terrain {
      tiles: populate_tile_map(&mut map_data, &map_a).to_vec(),
      tile_sets: [map_a, map_b],
    }
  }

  pub fn change_map(&mut self, idx: usize) {
    self.tiles = populate_tile_map(&mut self.tiles, &self.tile_sets[idx]).to_vec()
  }
}
<commit_msg>Store current map index to "curr_tile_set_idx"<commit_after>use data::{get_map_tile, load_map_file};
use game::constants::{MAP_A_FILE_PATH, MAP_B_FILE_PATH, TILE_MAP_BUF_LENGTH, TILES_PCS_H, TILES_PCS_W};
use shaders::TileMapData;
use tiled::Map;

fn calc_index(x_pos: usize, y_pos: usize) -> usize {
  (y_pos * TILES_PCS_W) + x_pos
}

fn populate_tile_map<'a>(tiles: &'a mut Vec<TileMapData>, map: &Map) -> &'a mut Vec<TileMapData> {
  for y_pos in 0..TILES_PCS_H {
    for x_pos in 0..TILES_PCS_W {
      let map_val = get_map_tile(map, 0, x_pos, y_pos);
      let tex_x = map_val % 32;
      let y = (map_val - tex_x) / 32;
      let x = if tex_x < 1 { 1 } else { tex_x - 1 };
      let idx = calc_index(x_pos, y_pos);
      tiles[idx] = TileMapData::new([x as f32, y as f32, 0.0, 0.0]);
    }
  }
  tiles
}

#[derive(Debug)]
pub struct Terrain {
  pub tiles: Vec<TileMapData>,
  pub tile_sets: [Map; 2],
  pub curr_tile_set_idx: usize,
}

impl Terrain {
  pub fn new() -> Terrain {
    let mut map_data = Vec::with_capacity(TILE_MAP_BUF_LENGTH);

    for _ in 0..TILE_MAP_BUF_LENGTH {
      map_data.push(TileMapData::new_empty());
    }

    let map_a = load_map_file(MAP_A_FILE_PATH);
    let map_b = load_map_file(MAP_B_FILE_PATH);

    Terrain {
      tiles: populate_tile_map(&mut map_data, &map_a).to_vec(),
      tile_sets: [map_a, map_b],
      curr_tile_set_idx: 0,
    }
  }

  pub fn change_map(&mut self, idx: usize) {
    self.tiles = populate_tile_map(&mut self.tiles, &self.tile_sets[idx]).to_vec();
    self.curr_tile_set_idx = idx;
  }
}
<|endoftext|>


<commit_before>use error::Result;
use handle::{Handle, ID, FromID, get_id_type};
use object::Object;

use ffi::h5i::{H5I_DATATYPE, hid_t};
use ffi::h5t::{H5T_INTEGER, H5T_FLOAT, H5T_NO_CLASS, H5T_NCLASSES, H5T_ORDER_BE, H5T_ORDER_LE,
               H5T_SGN_2, H5Tcopy, H5Tget_class, H5Tget_order, H5Tget_offset, H5Tget_sign,
               H5Tget_precision};

#[cfg(target_endian = "big")]
use globals::{
    H5T_STD_I8BE, H5T_STD_I16BE,
    H5T_STD_I32BE, H5T_STD_I64BE,
    H5T_STD_U8BE, H5T_STD_U16BE,
    H5T_STD_U32BE, H5T_STD_U64BE,
    H5T_IEEE_F32BE, H5T_IEEE_F64BE,
};

#[cfg(target_endian = "little")]
use globals::{
    H5T_STD_I8LE, H5T_STD_I16LE,
    H5T_STD_I32LE, H5T_STD_I64LE,
    H5T_STD_U8LE, H5T_STD_U16LE,
    H5T_STD_U32LE, H5T_STD_U64LE,
    H5T_IEEE_F32LE, H5T_IEEE_F64LE,
};

pub enum Datatype {
    Integer(IntegerDatatype),
    Float(FloatDatatype),
}

macro_rules! def_atomic {
    ($name:ident, $h5t:ident) => (
        pub struct $name {
            handle: Handle,
        }

        impl ID for $name {
            fn id(&self) -> hid_t {
                self.handle.id()
            }
        }

        impl FromID for $name {
            fn from_id(id: hid_t) -> Result<$name> {
                h5lock!({
                    if get_id_type(id) != H5I_DATATYPE {
                        return Err(From::from(format!("Invalid datatype id: {}", id)));
                    }
                    let cls = H5Tget_class(id);
                    if cls != $h5t {
                        return Err(From::from(format!("Invalid datatype class: {:?}", cls)));
                    }
                    Ok($name { handle: try!(Handle::new(id)) })
                })
            }
        }

        impl Object for $name {}
        impl AtomicDatatype for $name{}
    )
}

def_atomic!(IntegerDatatype, H5T_INTEGER);

impl IntegerDatatype {
    /// Returns true if the datatype is signed.
    pub fn is_signed(&self) -> bool {
        h5lock!(H5Tget_sign(self.id()) == H5T_SGN_2)
    }
}

def_atomic!(FloatDatatype, H5T_FLOAT);

pub trait AtomicDatatype: ID {
    /// Returns true if the datatype byte order is big endian.
    fn is_be(&self) -> bool {
        h5lock!(H5Tget_order(self.id()) == H5T_ORDER_BE)

    }

    /// Returns true if the datatype byte order is little endian.
    fn is_le(&self) -> bool {
        h5lock!(H5Tget_order(self.id()) == H5T_ORDER_LE)
    }

    /// Get the offset of the first significant bit.
    fn offset(&self) -> usize {
        h5call!(H5Tget_offset(self.id())).unwrap_or(0) as usize
    }

    /// Get the number of significant bits, excluding padding.
    fn precision(&self) -> usize {
        h5call!(H5Tget_precision(self.id())).unwrap_or(0) as usize
    }
}

pub trait ToDatatype {
    fn to_datatype() -> Result<Datatype>;
}

macro_rules! impl_atomic {
    ($tp:ty, $be:ident, $le:ident) => (
        impl ToDatatype for $tp {
            #[cfg(target_endian = "big")]
            fn to_datatype() -> Result<Datatype> {
                Datatype::from_id(h5try!(H5Tcopy(*$be)))
            }

            #[cfg(target_endian = "little")]
            fn to_datatype() -> Result<Datatype> {
                Datatype::from_id(h5try!(H5Tcopy(*$le)))
            }
        }
    )
}

impl_atomic!(i8, H5T_STD_I8BE, H5T_STD_I8LE);
impl_atomic!(i16, H5T_STD_I16BE, H5T_STD_I16LE);
impl_atomic!(i32, H5T_STD_I32BE, H5T_STD_I32LE);
impl_atomic!(i64, H5T_STD_I64BE, H5T_STD_I64LE);

impl_atomic!(u8, H5T_STD_U8BE, H5T_STD_U8LE);
impl_atomic!(u16, H5T_STD_U16BE, H5T_STD_U16LE);
impl_atomic!(u32, H5T_STD_U32BE, H5T_STD_U32LE);
impl_atomic!(u64, H5T_STD_U64BE, H5T_STD_U64LE);

impl_atomic!(f32, H5T_IEEE_F32BE, H5T_IEEE_F32LE);
impl_atomic!(f64, H5T_IEEE_F64BE, H5T_IEEE_F64LE);

#[cfg(target_pointer_width = "32")]
impl_atomic!(usize, H5T_STD_U32BE, H5T_STD_U32LE);
#[cfg(target_pointer_width = "32")]
impl_atomic!(isize, H5T_STD_I32BE, H5T_STD_I32LE);

#[cfg(target_pointer_width = "64")]
impl_atomic!(usize, H5T_STD_U64BE, H5T_STD_U64LE);
#[cfg(target_pointer_width = "64")]
impl_atomic!(isize, H5T_STD_I64BE, H5T_STD_I64LE);

impl ID for Datatype {
    fn id(&self) -> hid_t {
        match *self {
            Datatype::Integer(ref dt) => dt.id(),
            Datatype::Float(ref dt)   => dt.id(),
        }
    }
}

impl FromID for Datatype {
    fn from_id(id: hid_t) -> Result<Datatype> {
        h5lock!({
            match get_id_type(id) {
                H5I_DATATYPE => {
                    match H5Tget_class(id) {
                        H5T_INTEGER  => Ok(Datatype::Integer(try!(IntegerDatatype::from_id(id)))),
                        H5T_FLOAT    => Ok(Datatype::Float(try!(FloatDatatype::from_id(id)))),
                        H5T_NO_CLASS |
                        H5T_NCLASSES => Err(From::from("Invalid datatype class")),
                        cls          => Err(From::from(format!("Unsupported datatype: {:?}", cls)))
                    }
                },
                _ => Err(From::from(format!("Invalid datatype id: {}", id))),
            }
        })
    }
}

impl Object for Datatype {}

#[cfg(test)]
mod tests {
    use super::{Datatype, AtomicDatatype, ToDatatype};
    use super::Datatype::*;

    #[cfg(target_endian = "big")] const IS_BE: bool = true;
    #[cfg(target_endian = "big")] const IS_LE: bool = false;

    #[cfg(target_endian = "little")] const IS_BE: bool = false;
    #[cfg(target_endian = "little")] const IS_LE: bool = true;

    #[cfg(target_pointer_width = "32")] const POINTER_WIDTH: usize = 32;
    #[cfg(target_pointer_width = "64")] const POINTER_WIDTH: usize = 64;

    #[test]
    pub fn test_datatype() {
        macro_rules! test_atomic {
            ($tp:ty, $variant:ident, $precision:expr, $block:expr) => (
                match <$tp as ToDatatype>::to_datatype().unwrap() {
                    Datatype::$variant(dt) => {
                        assert_eq!(dt.is_be(), IS_BE);
                        assert_eq!(dt.is_le(), IS_LE);
                        assert_eq!(dt.offset(), 0);
                        assert_eq!(dt.precision(), $precision);
                    },
                    _ => panic!("Invalid datatype object")
                }
            )
        }

        macro_rules! test_integer {
            ($tp:ty, $signed:expr, $precision:expr) => (
                test_atomic!($tp, Integer, $precision, |dt| {
                    assert_eq!(dt.is_signed(), $signed)
                })
            )
        }

        macro_rules! test_float {
            ($tp:ty, $precision:expr) => (
                test_atomic!($tp, Float, $precision, |dt| {});
            )
        }

        test_integer!(i8, true, 8);
        test_integer!(i16, true, 16);
        test_integer!(i32, true, 32);
        test_integer!(i64, true, 64);

        test_integer!(u8, false, 8);
        test_integer!(u16, false, 16);
        test_integer!(u32, false, 32);
        test_integer!(u64, false, 64);

        test_float!(f32, 32);
        test_float!(f64, 64);

        test_integer!(isize, true, POINTER_WIDTH);
        test_integer!(usize, false, POINTER_WIDTH);
    }
}
<commit_msg>Implement ToDatatype for bool, add a few more tests<commit_after>use error::Result;
use handle::{Handle, ID, FromID, get_id_type};
use object::Object;

use ffi::h5i::{H5I_DATATYPE, hid_t};
use ffi::h5t::{H5T_INTEGER, H5T_FLOAT, H5T_NO_CLASS, H5T_NCLASSES, H5T_ORDER_BE, H5T_ORDER_LE,
               H5T_SGN_2, H5Tcopy, H5Tget_class, H5Tget_order, H5Tget_offset, H5Tget_sign,
               H5Tget_precision};

#[cfg(target_endian = "big")]
use globals::{
    H5T_STD_I8BE, H5T_STD_I16BE,
    H5T_STD_I32BE, H5T_STD_I64BE,
    H5T_STD_U8BE, H5T_STD_U16BE,
    H5T_STD_U32BE, H5T_STD_U64BE,
    H5T_IEEE_F32BE, H5T_IEEE_F64BE,
};

#[cfg(target_endian = "little")]
use globals::{
    H5T_STD_I8LE, H5T_STD_I16LE,
    H5T_STD_I32LE, H5T_STD_I64LE,
    H5T_STD_U8LE, H5T_STD_U16LE,
    H5T_STD_U32LE, H5T_STD_U64LE,
    H5T_IEEE_F32LE, H5T_IEEE_F64LE,
};

pub enum Datatype {
    Integer(IntegerDatatype),
    Float(FloatDatatype),
}

macro_rules! def_atomic {
    ($name:ident, $h5t:ident) => (
        pub struct $name {
            handle: Handle,
        }

        impl ID for $name {
            fn id(&self) -> hid_t {
                self.handle.id()
            }
        }

        impl FromID for $name {
            fn from_id(id: hid_t) -> Result<$name> {
                h5lock!({
                    if get_id_type(id) != H5I_DATATYPE {
                        return Err(From::from(format!("Invalid datatype id: {}", id)));
                    }
                    let cls = H5Tget_class(id);
                    if cls != $h5t {
                        return Err(From::from(format!("Invalid datatype class: {:?}", cls)));
                    }
                    Ok($name { handle: try!(Handle::new(id)) })
                })
            }
        }

        impl Object for $name {}
        impl AtomicDatatype for $name{}
    )
}

def_atomic!(IntegerDatatype, H5T_INTEGER);

impl IntegerDatatype {
    /// Returns true if the datatype is signed.
    pub fn is_signed(&self) -> bool {
        h5lock!(H5Tget_sign(self.id()) == H5T_SGN_2)
    }
}

def_atomic!(FloatDatatype, H5T_FLOAT);

pub trait AtomicDatatype: ID {
    /// Returns true if the datatype byte order is big endian.
    fn is_be(&self) -> bool {
        h5lock!(H5Tget_order(self.id()) == H5T_ORDER_BE)

    }

    /// Returns true if the datatype byte order is little endian.
    fn is_le(&self) -> bool {
        h5lock!(H5Tget_order(self.id()) == H5T_ORDER_LE)
    }

    /// Get the offset of the first significant bit.
    fn offset(&self) -> usize {
        h5call!(H5Tget_offset(self.id())).unwrap_or(0) as usize
    }

    /// Get the number of significant bits, excluding padding.
    fn precision(&self) -> usize {
        h5call!(H5Tget_precision(self.id())).unwrap_or(0) as usize
    }
}

pub trait ToDatatype {
    fn to_datatype() -> Result<Datatype>;
}

macro_rules! impl_atomic {
    ($tp:ty, $be:ident, $le:ident) => (
        impl ToDatatype for $tp {
            #[cfg(target_endian = "big")]
            fn to_datatype() -> Result<Datatype> {
                Datatype::from_id(h5try!(H5Tcopy(*$be)))
            }

            #[cfg(target_endian = "little")]
            fn to_datatype() -> Result<Datatype> {
                Datatype::from_id(h5try!(H5Tcopy(*$le)))
            }
        }
    )
}

impl_atomic!(bool, H5T_STD_U8BE, H5T_STD_U8LE);

impl_atomic!(i8, H5T_STD_I8BE, H5T_STD_I8LE);
impl_atomic!(i16, H5T_STD_I16BE, H5T_STD_I16LE);
impl_atomic!(i32, H5T_STD_I32BE, H5T_STD_I32LE);
impl_atomic!(i64, H5T_STD_I64BE, H5T_STD_I64LE);

impl_atomic!(u8, H5T_STD_U8BE, H5T_STD_U8LE);
impl_atomic!(u16, H5T_STD_U16BE, H5T_STD_U16LE);
impl_atomic!(u32, H5T_STD_U32BE, H5T_STD_U32LE);
impl_atomic!(u64, H5T_STD_U64BE, H5T_STD_U64LE);

impl_atomic!(f32, H5T_IEEE_F32BE, H5T_IEEE_F32LE);
impl_atomic!(f64, H5T_IEEE_F64BE, H5T_IEEE_F64LE);

#[cfg(target_pointer_width = "32")] impl_atomic!(usize, H5T_STD_U32BE, H5T_STD_U32LE);
#[cfg(target_pointer_width = "32")] impl_atomic!(isize, H5T_STD_I32BE, H5T_STD_I32LE);

#[cfg(target_pointer_width = "64")] impl_atomic!(usize, H5T_STD_U64BE, H5T_STD_U64LE);
#[cfg(target_pointer_width = "64")] impl_atomic!(isize, H5T_STD_I64BE, H5T_STD_I64LE);

impl ID for Datatype {
    fn id(&self) -> hid_t {
        match *self {
            Datatype::Integer(ref dt) => dt.id(),
            Datatype::Float(ref dt)   => dt.id(),
        }
    }
}

impl FromID for Datatype {
    fn from_id(id: hid_t) -> Result<Datatype> {
        h5lock!({
            match get_id_type(id) {
                H5I_DATATYPE => {
                    match H5Tget_class(id) {
                        H5T_INTEGER  => Ok(Datatype::Integer(try!(IntegerDatatype::from_id(id)))),
                        H5T_FLOAT    => Ok(Datatype::Float(try!(FloatDatatype::from_id(id)))),
                        H5T_NO_CLASS |
                        H5T_NCLASSES => Err(From::from("Invalid datatype class")),
                        cls          => Err(From::from(format!("Unsupported datatype: {:?}", cls)))
                    }
                },
                _ => Err(From::from(format!("Invalid datatype id: {}", id))),
            }
        })
    }
}

impl Object for Datatype {}

#[cfg(test)]
mod tests {
    use super::{Datatype, AtomicDatatype, ToDatatype};
    use super::Datatype::*;
    use handle::FromID;
    use ffi::h5i::H5I_INVALID_HID;
    use ffi::h5t::H5Tcopy;
    use globals::H5T_STD_REF_OBJ;

    #[cfg(target_endian = "big")] const IS_BE: bool = true;
    #[cfg(target_endian = "big")] const IS_LE: bool = false;

    #[cfg(target_endian = "little")] const IS_BE: bool = false;
    #[cfg(target_endian = "little")] const IS_LE: bool = true;

    #[cfg(target_pointer_width = "32")] const POINTER_WIDTH: usize = 32;
    #[cfg(target_pointer_width = "64")] const POINTER_WIDTH: usize = 64;

    #[test]
    pub fn test_invalid_datatype() {
        assert_err!(Datatype::from_id(H5I_INVALID_HID), "Invalid datatype id");
        assert_err!(Datatype::from_id(h5lock!(H5Tcopy(*H5T_STD_REF_OBJ))), "Unsupported datatype");
    }

    #[test]
    pub fn test_atomic_datatype() {
        macro_rules! test_integer {
            ($tp:ty, $signed:expr, $precision:expr) => (
                match <$tp as ToDatatype>::to_datatype().unwrap() {
                    Datatype::Integer(dt) => {
                        assert_eq!(dt.is_be(), IS_BE);
                        assert_eq!(dt.is_le(), IS_LE);
                        assert_eq!(dt.offset(), 0);
                        assert_eq!(dt.precision(), $precision);
                        assert_eq!(dt.is_signed(), $signed);
                    },
                    _ => panic!("Integer datatype expected")
                }
            )
        }

        macro_rules! test_float {
            ($tp:ty, $precision:expr) => (
                match <$tp as ToDatatype>::to_datatype().unwrap() {
                    Datatype::Float(dt) => {
                        assert_eq!(dt.is_be(), IS_BE);
                        assert_eq!(dt.is_le(), IS_LE);
                        assert_eq!(dt.offset(), 0);
                        assert_eq!(dt.precision(), $precision)
                    },
                    _ => panic!("Float datatype expected")
                }
            )
        }

        test_integer!(bool, false, 8);

        test_integer!(i8, true, 8);
        test_integer!(i16, true, 16);
        test_integer!(i32, true, 32);
        test_integer!(i64, true, 64);

        test_integer!(u8, false, 8);
        test_integer!(u16, false, 16);
        test_integer!(u32, false, 32);
        test_integer!(u64, false, 64);

        test_float!(f32, 32);
        test_float!(f64, 64);

        test_integer!(isize, true, POINTER_WIDTH);
        test_integer!(usize, false, POINTER_WIDTH);
    }
}
<|endoftext|>


<commit_before>use super::*;

#[derive(Debug, PartialEq, Deserialize)]
struct EmptyStruct1;

#[derive(Debug, PartialEq, Deserialize)]
struct EmptyStruct2 {}

#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
struct MyStruct {
    x: f32,
    y: f32,
}

#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
enum MyEnum {
    A,
    B(bool),
    C(bool, f32),
    D { a: i32, b: i32 },
}

#[test]
fn test_empty_struct() {
    assert_eq!(Ok(EmptyStruct1), from_str("EmptyStruct1"));
    assert_eq!(Ok(EmptyStruct2 {}), from_str("EmptyStruct2()"));
}

#[test]
fn test_struct() {
    let my_struct = MyStruct { x: 4.0, y: 7.0 };

    assert_eq!(Ok(my_struct), from_str("MyStruct(x:4,y:7,)"));
    assert_eq!(Ok(my_struct), from_str("(x:4,y:7)"));

    #[derive(Debug, PartialEq, Deserialize)]
    struct NewType(i32);

    assert_eq!(Ok(NewType(42)), from_str("NewType(42)"));
    assert_eq!(Ok(NewType(33)), from_str("(33)"));

    #[derive(Debug, PartialEq, Deserialize)]
    struct TupleStruct(f32, f32);

    assert_eq!(Ok(TupleStruct(2.0, 5.0)), from_str("TupleStruct(2,5,)"));
    assert_eq!(Ok(TupleStruct(3.0, 4.0)), from_str("(3,4)"));
}

#[test]
fn test_option() {
    assert_eq!(Ok(Some(1u8)), from_str("Some(1)"));
    assert_eq!(Ok(None::<u8>), from_str("None"));
}

#[test]
fn test_enum() {
    assert_eq!(Ok(MyEnum::A), from_str("A"));
    assert_eq!(Ok(MyEnum::B(true)), from_str("B(true,)"));
    assert_eq!(Ok(MyEnum::C(true, 3.5)), from_str("C(true,3.5,)"));
    assert_eq!(Ok(MyEnum::D { a: 2, b: 3 }), from_str("D(a:2,b:3,)"));
}

#[test]
fn test_array() {
    let empty: [i32; 0] = [];
    assert_eq!(Ok(empty), from_str("()"));
    let empty_array = empty.to_vec();
    assert_eq!(Ok(empty_array), from_str("[]"));

    assert_eq!(Ok([2, 3, 4i32]), from_str("(2,3,4,)"));
    assert_eq!(Ok([2, 3, 4i32].to_vec()), from_str("[2,3,4,]"));
}

#[test]
fn test_map() {
    use std::collections::HashMap;

    let mut map = HashMap::new();
    map.insert((true, false), 4);
    map.insert((false, false), 123);

    assert_eq!(
        Ok(map),
        from_str(
            "{
        (true,false,):4,
        (false,false,):123,
    }"
        )
    );
}

#[test]
fn test_string() {
    let s: String = from_str("\"String\"").unwrap();
    assert_eq!("String", s);

    let raw: String = from_str("r\"String\"").unwrap();
    assert_eq!("String", raw);

    let raw_hashes: String = from_str("r#\"String\"#").unwrap();
    assert_eq!("String", raw_hashes);

    let raw_hashes_quote: String = from_str("r##\"String with \"#\"##").unwrap();
    assert_eq!("String with \"#", raw_hashes_quote);
}

#[test]
fn test_char() {
    assert_eq!(Ok('c'), from_str("'c'"));
}

#[test]
fn test_escape_char() {
    assert_eq!('\'', from_str::<char>("'\\''").unwrap());
}

#[test]
fn test_escape() {
    assert_eq!("\"Quoted\"", from_str::<String>(r#""\"Quoted\"""#).unwrap());
}

#[test]
fn test_comment() {
    assert_eq!(
        MyStruct { x: 1.0, y: 2.0 },
        from_str(
            "(
x: 1.0, // x is just 1
// There is another comment in the very next line..
// And y is indeed
y: 2.0 // 2!
    )"
        ).unwrap()
    );
}

fn err<T>(kind: ParseError, line: usize, col: usize) -> Result<T> {
    use parse::Position;

    Err(Error::Parser(kind, Position { line, col }))
}

#[test]
fn test_err_wrong_value() {
    use self::ParseError::*;
    use std::collections::HashMap;

    assert_eq!(from_str::<f32>("'c'"), err(ExpectedFloat, 1, 1));
    assert_eq!(from_str::<String>("'c'"), err(ExpectedString, 1, 1));
    assert_eq!(from_str::<HashMap<u32, u32>>("'c'"), err(ExpectedMap, 1, 1));
    assert_eq!(from_str::<[u8; 5]>("'c'"), err(ExpectedArray, 1, 1));
    assert_eq!(from_str::<Vec<u32>>("'c'"), err(ExpectedArray, 1, 1));
    assert_eq!(from_str::<MyEnum>("'c'"), err(ExpectedIdentifier, 1, 1));
    assert_eq!(from_str::<MyStruct>("'c'"), err(ExpectedStruct, 1, 1));
    assert_eq!(from_str::<(u8, bool)>("'c'"), err(ExpectedArray, 1, 1));
    assert_eq!(from_str::<bool>("notabool"), err(ExpectedBoolean, 1, 1));

    assert_eq!(
        from_str::<MyStruct>("MyStruct(\n    x: true)"),
        err(ExpectedFloat, 2, 8)
    );
    assert_eq!(
        from_str::<MyStruct>("MyStruct(\n    x: 3.5, \n    y:)"),
        err(ExpectedFloat, 3, 7)
    );
}

#[test]
fn test_perm_ws() {
    assert_eq!(
        from_str::<MyStruct>("\nMyStruct  \t ( \n x   : 3.5 , \t y\n: 4.5 \n ) \t\n"),
        Ok(MyStruct { x: 3.5, y: 4.5 })
    );
}

#[test]
fn untagged() {
    #[derive(Deserialize, Debug, PartialEq)]
    #[serde(untagged)]
    enum Untagged {
        U8(u8),
        Bool(bool),
    }

    assert_eq!(from_str::<Untagged>("true").unwrap(), Untagged::Bool(true));
}

#[test]
fn forgot_apostrophes() {
    let de: Result<(i32, String)> = from_str("(4, \"Hello)");

    assert!(match de {
        Err(Error::Parser(ParseError::ExpectedStringEnd, _)) => true,
        _ => false,
    });
}

#[test]
fn expected_attribute() {
    let de: Result<String> = from_str("#\"Hello\"");

    assert_eq!(de, err(ParseError::ExpectedAttribute, 1, 2));
}

#[test]
fn expected_attribute_end() {
    let de: Result<String> = from_str("#![enable(unwrap_newtypes) \"Hello\"");

    assert_eq!(de, err(ParseError::ExpectedAttributeEnd, 1, 28));
}

#[test]
fn invalid_attribute() {
    let de: Result<String> = from_str("#![enable(invalid)] \"Hello\"");

    assert_eq!(
        de,
        err(ParseError::NoSuchExtension("invalid".to_string()), 1, 18)
    );
}

#[test]
fn multiple_attributes() {
    #[derive(Debug, Deserialize, PartialEq)]
    struct New(String);
    let de: Result<New> =
        from_str("#![enable(unwrap_newtypes)] #![enable(unwrap_newtypes)] \"Hello\"");

    assert_eq!(de, Ok(New("Hello".to_owned())));
}

#[test]
fn uglified_attribute() {
    let de: Result<()> = from_str(
        "#   !\
    // We definitely want to add a comment here
    [\t\tenable( // best style ever
            unwrap_newtypes  ) ] ()",
    );

    assert_eq!(de, Ok(()));
}

#[test]
fn implicit_some() {
    use serde::de::DeserializeOwned;

    fn de<T: DeserializeOwned>(s: &str) -> Option<T> {
        let enable = "#![enable(implicit_some)]\n".to_string();

        from_str::<Option<T>>(&(enable + s)).unwrap()
    }

    assert_eq!(de("'c'"), Some('c'));
    assert_eq!(de("5"), Some(5));
    assert_eq!(de("\"Hello\""), Some("Hello".to_owned()));
    assert_eq!(de("false"), Some(false));
    assert_eq!(
        de("MyStruct(x: .4, y: .5)"),
        Some(MyStruct { x: 0.4, y: 0.5 })
    );

    assert_eq!(de::<char>("None"), None);

    // Not concise
    assert_eq!(de::<Option<Option<char>>>("None"), None);
}

#[test]
fn ws_tuple_newtype_variant() {
    assert_eq!(Ok(MyEnum::B(true)), from_str("B  ( \n true \n ) "));
}
<commit_msg>Add test for multiline string literals<commit_after>use super::*;

#[derive(Debug, PartialEq, Deserialize)]
struct EmptyStruct1;

#[derive(Debug, PartialEq, Deserialize)]
struct EmptyStruct2 {}

#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
struct MyStruct {
    x: f32,
    y: f32,
}

#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
enum MyEnum {
    A,
    B(bool),
    C(bool, f32),
    D { a: i32, b: i32 },
}

#[test]
fn test_empty_struct() {
    assert_eq!(Ok(EmptyStruct1), from_str("EmptyStruct1"));
    assert_eq!(Ok(EmptyStruct2 {}), from_str("EmptyStruct2()"));
}

#[test]
fn test_struct() {
    let my_struct = MyStruct { x: 4.0, y: 7.0 };

    assert_eq!(Ok(my_struct), from_str("MyStruct(x:4,y:7,)"));
    assert_eq!(Ok(my_struct), from_str("(x:4,y:7)"));

    #[derive(Debug, PartialEq, Deserialize)]
    struct NewType(i32);

    assert_eq!(Ok(NewType(42)), from_str("NewType(42)"));
    assert_eq!(Ok(NewType(33)), from_str("(33)"));

    #[derive(Debug, PartialEq, Deserialize)]
    struct TupleStruct(f32, f32);

    assert_eq!(Ok(TupleStruct(2.0, 5.0)), from_str("TupleStruct(2,5,)"));
    assert_eq!(Ok(TupleStruct(3.0, 4.0)), from_str("(3,4)"));
}

#[test]
fn test_option() {
    assert_eq!(Ok(Some(1u8)), from_str("Some(1)"));
    assert_eq!(Ok(None::<u8>), from_str("None"));
}

#[test]
fn test_enum() {
    assert_eq!(Ok(MyEnum::A), from_str("A"));
    assert_eq!(Ok(MyEnum::B(true)), from_str("B(true,)"));
    assert_eq!(Ok(MyEnum::C(true, 3.5)), from_str("C(true,3.5,)"));
    assert_eq!(Ok(MyEnum::D { a: 2, b: 3 }), from_str("D(a:2,b:3,)"));
}

#[test]
fn test_array() {
    let empty: [i32; 0] = [];
    assert_eq!(Ok(empty), from_str("()"));
    let empty_array = empty.to_vec();
    assert_eq!(Ok(empty_array), from_str("[]"));

    assert_eq!(Ok([2, 3, 4i32]), from_str("(2,3,4,)"));
    assert_eq!(Ok([2, 3, 4i32].to_vec()), from_str("[2,3,4,]"));
}

#[test]
fn test_map() {
    use std::collections::HashMap;

    let mut map = HashMap::new();
    map.insert((true, false), 4);
    map.insert((false, false), 123);

    assert_eq!(
        Ok(map),
        from_str(
            "{
        (true,false,):4,
        (false,false,):123,
    }"
        )
    );
}

#[test]
fn test_string() {
    let s: String = from_str("\"String\"").unwrap();
    assert_eq!("String", s);

    let raw: String = from_str("r\"String\"").unwrap();
    assert_eq!("String", raw);

    let raw_hashes: String = from_str("r#\"String\"#").unwrap();
    assert_eq!("String", raw_hashes);

    let raw_hashes_multiline: String = from_str("r#\"String with\nmultiple\nlines\n\"#").unwrap();
    assert_eq!("String with\nmultiple\nlines\n", raw_hashes_multiline);

    let raw_hashes_quote: String = from_str("r##\"String with \"#\"##").unwrap();
    assert_eq!("String with \"#", raw_hashes_quote);
}

#[test]
fn test_char() {
    assert_eq!(Ok('c'), from_str("'c'"));
}

#[test]
fn test_escape_char() {
    assert_eq!('\'', from_str::<char>("'\\''").unwrap());
}

#[test]
fn test_escape() {
    assert_eq!("\"Quoted\"", from_str::<String>(r#""\"Quoted\"""#).unwrap());
}

#[test]
fn test_comment() {
    assert_eq!(
        MyStruct { x: 1.0, y: 2.0 },
        from_str(
            "(
x: 1.0, // x is just 1
// There is another comment in the very next line..
// And y is indeed
y: 2.0 // 2!
    )"
        ).unwrap()
    );
}

fn err<T>(kind: ParseError, line: usize, col: usize) -> Result<T> {
    use parse::Position;

    Err(Error::Parser(kind, Position { line, col }))
}

#[test]
fn test_err_wrong_value() {
    use self::ParseError::*;
    use std::collections::HashMap;

    assert_eq!(from_str::<f32>("'c'"), err(ExpectedFloat, 1, 1));
    assert_eq!(from_str::<String>("'c'"), err(ExpectedString, 1, 1));
    assert_eq!(from_str::<HashMap<u32, u32>>("'c'"), err(ExpectedMap, 1, 1));
    assert_eq!(from_str::<[u8; 5]>("'c'"), err(ExpectedArray, 1, 1));
    assert_eq!(from_str::<Vec<u32>>("'c'"), err(ExpectedArray, 1, 1));
    assert_eq!(from_str::<MyEnum>("'c'"), err(ExpectedIdentifier, 1, 1));
    assert_eq!(from_str::<MyStruct>("'c'"), err(ExpectedStruct, 1, 1));
    assert_eq!(from_str::<(u8, bool)>("'c'"), err(ExpectedArray, 1, 1));
    assert_eq!(from_str::<bool>("notabool"), err(ExpectedBoolean, 1, 1));

    assert_eq!(
        from_str::<MyStruct>("MyStruct(\n    x: true)"),
        err(ExpectedFloat, 2, 8)
    );
    assert_eq!(
        from_str::<MyStruct>("MyStruct(\n    x: 3.5, \n    y:)"),
        err(ExpectedFloat, 3, 7)
    );
}

#[test]
fn test_perm_ws() {
    assert_eq!(
        from_str::<MyStruct>("\nMyStruct  \t ( \n x   : 3.5 , \t y\n: 4.5 \n ) \t\n"),
        Ok(MyStruct { x: 3.5, y: 4.5 })
    );
}

#[test]
fn untagged() {
    #[derive(Deserialize, Debug, PartialEq)]
    #[serde(untagged)]
    enum Untagged {
        U8(u8),
        Bool(bool),
    }

    assert_eq!(from_str::<Untagged>("true").unwrap(), Untagged::Bool(true));
}

#[test]
fn forgot_apostrophes() {
    let de: Result<(i32, String)> = from_str("(4, \"Hello)");

    assert!(match de {
        Err(Error::Parser(ParseError::ExpectedStringEnd, _)) => true,
        _ => false,
    });
}

#[test]
fn expected_attribute() {
    let de: Result<String> = from_str("#\"Hello\"");

    assert_eq!(de, err(ParseError::ExpectedAttribute, 1, 2));
}

#[test]
fn expected_attribute_end() {
    let de: Result<String> = from_str("#![enable(unwrap_newtypes) \"Hello\"");

    assert_eq!(de, err(ParseError::ExpectedAttributeEnd, 1, 28));
}

#[test]
fn invalid_attribute() {
    let de: Result<String> = from_str("#![enable(invalid)] \"Hello\"");

    assert_eq!(
        de,
        err(ParseError::NoSuchExtension("invalid".to_string()), 1, 18)
    );
}

#[test]
fn multiple_attributes() {
    #[derive(Debug, Deserialize, PartialEq)]
    struct New(String);
    let de: Result<New> =
        from_str("#![enable(unwrap_newtypes)] #![enable(unwrap_newtypes)] \"Hello\"");

    assert_eq!(de, Ok(New("Hello".to_owned())));
}

#[test]
fn uglified_attribute() {
    let de: Result<()> = from_str(
        "#   !\
    // We definitely want to add a comment here
    [\t\tenable( // best style ever
            unwrap_newtypes  ) ] ()",
    );

    assert_eq!(de, Ok(()));
}

#[test]
fn implicit_some() {
    use serde::de::DeserializeOwned;

    fn de<T: DeserializeOwned>(s: &str) -> Option<T> {
        let enable = "#![enable(implicit_some)]\n".to_string();

        from_str::<Option<T>>(&(enable + s)).unwrap()
    }

    assert_eq!(de("'c'"), Some('c'));
    assert_eq!(de("5"), Some(5));
    assert_eq!(de("\"Hello\""), Some("Hello".to_owned()));
    assert_eq!(de("false"), Some(false));
    assert_eq!(
        de("MyStruct(x: .4, y: .5)"),
        Some(MyStruct { x: 0.4, y: 0.5 })
    );

    assert_eq!(de::<char>("None"), None);

    // Not concise
    assert_eq!(de::<Option<Option<char>>>("None"), None);
}

#[test]
fn ws_tuple_newtype_variant() {
    assert_eq!(Ok(MyEnum::B(true)), from_str("B  ( \n true \n ) "));
}
<|endoftext|>


<commit_before>use time::Timespec;
use pg::PostgresRow;

use Model;
use db::Connection;
use util::CargoResult;

pub struct VersionDownload {
    pub id: i32,
    pub version_id: i32,
    pub downloads: i32,
    pub counted: i32,
    pub date: Timespec,
}

#[deriving(Encodable, Decodable)]
pub struct EncodableVersionDownload {
    pub id: i32,
    pub version_id: i32,
    pub downloads: i32,
    pub date: String,
}

impl VersionDownload {
    pub fn find(conn: &Connection, id: i32) -> CargoResult<VersionDownload> {
        Model::find(conn, id)
    }

    pub fn encodable(self) -> EncodableVersionDownload {
        let VersionDownload { id, version_id, downloads, counted: _,
                              date } = self;
        EncodableVersionDownload {
            id: id,
            version_id: version_id,
            downloads: downloads,
            date: ::encode_time(date),
        }
    }
}

impl Model for VersionDownload {
    fn from_row(row: &PostgresRow) -> VersionDownload {
        VersionDownload {
            id: row.get("id"),
            version_id: row.get("version_id"),
            downloads: row.get("downloads"),
            counted: row.get("counted"),
            date: row.get("date"),
        }
    }

    fn table_name(_: Option<VersionDownload>) -> &'static str { "version_downloads" }
}

pub struct CrateDownload {
    pub id: i32,
    pub crate_id: i32,
    pub downloads: i32,
    pub date: Timespec,
}

impl CrateDownload {
    pub fn find(conn: &Connection, id: i32) -> CargoResult<CrateDownload> {
        Model::find(conn, id)
    }
}

impl Model for CrateDownload {
    fn from_row(row: &PostgresRow) -> CrateDownload {
        CrateDownload {
            id: row.get("id"),
            crate_id: row.get("crate_id"),
            downloads: row.get("downloads"),
            date: row.get("date"),
        }
    }

    fn table_name(_: Option<CrateDownload>) -> &'static str { "crate_downloads" }
}
<commit_msg>Don't suffix with _id<commit_after>use time::Timespec;
use pg::PostgresRow;

use Model;
use db::Connection;
use util::CargoResult;

pub struct VersionDownload {
    pub id: i32,
    pub version_id: i32,
    pub downloads: i32,
    pub counted: i32,
    pub date: Timespec,
}

#[deriving(Encodable, Decodable)]
pub struct EncodableVersionDownload {
    pub id: i32,
    pub version: i32,
    pub downloads: i32,
    pub date: String,
}

impl VersionDownload {
    pub fn find(conn: &Connection, id: i32) -> CargoResult<VersionDownload> {
        Model::find(conn, id)
    }

    pub fn encodable(self) -> EncodableVersionDownload {
        let VersionDownload { id, version_id, downloads, counted: _,
                              date } = self;
        EncodableVersionDownload {
            id: id,
            version: version_id,
            downloads: downloads,
            date: ::encode_time(date),
        }
    }
}

impl Model for VersionDownload {
    fn from_row(row: &PostgresRow) -> VersionDownload {
        VersionDownload {
            id: row.get("id"),
            version_id: row.get("version_id"),
            downloads: row.get("downloads"),
            counted: row.get("counted"),
            date: row.get("date"),
        }
    }

    fn table_name(_: Option<VersionDownload>) -> &'static str { "version_downloads" }
}

pub struct CrateDownload {
    pub id: i32,
    pub crate_id: i32,
    pub downloads: i32,
    pub date: Timespec,
}

impl CrateDownload {
    pub fn find(conn: &Connection, id: i32) -> CargoResult<CrateDownload> {
        Model::find(conn, id)
    }
}

impl Model for CrateDownload {
    fn from_row(row: &PostgresRow) -> CrateDownload {
        CrateDownload {
            id: row.get("id"),
            crate_id: row.get("crate_id"),
            downloads: row.get("downloads"),
            date: row.get("date"),
        }
    }

    fn table_name(_: Option<CrateDownload>) -> &'static str { "crate_downloads" }
}
<|endoftext|>


<commit_before>extern crate orbtk;
use orbtk::*;
use std::{cell::Cell, rc::Rc};
static CENTER_DEMO_CSS: &'static str = include_str!("center-demo.css");

#[derive(Default)]
struct MainViewState {
  counter: Cell<i32>,
}

impl MainViewState {}

impl State for MainViewState {
  fn update(&self, context: &mut Context<'_>) {
    if let Ok(button_count_label) = context.widget().borrow_mut_property::<Label>() {
      button_count_label.0 = format!("Button count: {}", self.counter.get());
    }
  }
}

fn _create_header(text: &str) -> Template {
  TextBlock::create()
    .with_property(Label::from(text))
    .with_property(Selector::from("textblock").with_class("h1"))
}

struct MainView;

impl Widget for MainView {
  fn create() -> Template {
    let state = Rc::new(MainViewState::default());
    // let clear_state = state.clone();
    let label = SharedProperty::new(Label::from("prototype"));

    Template::default()
      .as_parent_type(ParentType::Single)
      .with_state(state.clone())
      // Nav bar
      .with_child(Column::create()
        .with_child(build_navbar())
        .with_child(build_main_view())
      )
      .with_shared_property(label)
      .with_debug_name("MainView")
  }
}

// Create a row for buttons and information
fn build_navbar() -> Template {
  let frame = Constraint::default()
    .with_width(400)
    .with_height(50)
    .with_min_width(400);

  Row::create().with_property(Selector::from("row").with_class("full"))
      .with_child(Column::create()
        .with_child(Button::create()
          .with_property(Selector::from("button").with_class("nav"))
          .with_property(Label::from("Home")),
        ),
      )
      .with_child(Column::create()
        .with_layout(FixedSizeLayout::default())
        .with_property(Selector::from("column").with_class("navview"))
        .with_child(Container::create()
          .with_property(Selector::from("container").with_class("navbarview"))
          .with_child(Center::create()
            .with_property(frame)
            .with_property(Selector::from("center").with_class("navtitleview"))
            .with_child(TextBlock::create()
              .with_property(Label::from("TITLE"))
              .with_property(Selector::from("textblock").with_class("navtitle")),
            ))))
      .with_child(Column::create()
        .with_child(Button::create()
          .with_property(Selector::from("button").with_class("nav"))
          .with_property(Label::from("Settings")),
      ),
    )
}

fn build_main_view() -> Template {
  Row::create()
    .with_child(build_boxview("Step 1"))
    .with_child(build_boxview("Step 2"))
    .with_child(build_boxview("Step 3"))
}

fn build_boxview(title: &str) -> Template {
  Column::create()
    .with_child(Container::create()
    .with_property(Selector::from("container").with_class("mainviewbox"))
    .with_child(Center::create()
    .with_property(Selector::from("center").with_class("mainviewbox"))
    .with_child(Button::create()
          .with_property(Selector::from("button").with_class("primary"))
          .with_property(Label::from(title)),
    )))
}

fn main() {
  let mut application = Application::default();
  application
    .create_window()
    .with_bounds(Bounds::new(100, 200, 600, 400))
    .with_title("Fixed and center layouts")
    .with_theme(Theme::create()
        .with_extenstion_css(CENTER_DEMO_CSS)
        .build(),
    )
    .with_root(MainView::create())
    .with_debug_flag(false)
    .build();
  application.run();
}
<commit_msg>Remove dead code.<commit_after>extern crate orbtk;
use orbtk::*;
use std::{rc::Rc};
static CENTER_DEMO_CSS: &'static str = include_str!("center-demo.css");

#[derive(Default)]
struct MainViewState {}

impl MainViewState {}

impl State for MainViewState {
}

struct MainView;

impl Widget for MainView {
  fn create() -> Template {
    let state = Rc::new(MainViewState::default());
    let label = SharedProperty::new(Label::from("prototype"));

    Template::default()
      .as_parent_type(ParentType::Single)
      .with_state(state.clone())
      // Nav bar
      .with_child(Column::create()
        .with_child(build_navbar())
        .with_child(build_main_view())
      )
      .with_shared_property(label)
      .with_debug_name("MainView")
  }
}

// Create a row for buttons and information
fn build_navbar() -> Template {
  let frame = Constraint::default()
    .with_width(400)
    .with_height(50)
    .with_min_width(400);

  Row::create().with_property(Selector::from("row").with_class("full"))
      .with_child(Column::create()
        .with_child(Button::create()
          .with_property(Selector::from("button").with_class("nav"))
          .with_property(Label::from("Home")),
        ),
      )
      .with_child(Column::create()
        .with_layout(FixedSizeLayout::default())
        .with_property(Selector::from("column").with_class("navview"))
        .with_child(Container::create()
          .with_property(Selector::from("container").with_class("navbarview"))
          .with_child(Center::create()
            .with_property(frame)
            .with_property(Selector::from("center").with_class("navtitleview"))
            .with_child(TextBlock::create()
              .with_property(Label::from("TITLE"))
              .with_property(Selector::from("textblock").with_class("navtitle")),
            ))))
      .with_child(Column::create()
        .with_child(Button::create()
          .with_property(Selector::from("button").with_class("nav"))
          .with_property(Label::from("Settings")),
      ),
    )
}

fn build_main_view() -> Template {
  Row::create()
    .with_child(build_boxview("Step 1"))
    .with_child(build_boxview("Step 2"))
    .with_child(build_boxview("Step 3"))
}

fn build_boxview(title: &str) -> Template {
  Column::create()
    .with_child(Container::create()
    .with_property(Selector::from("container").with_class("mainviewbox"))
    .with_child(Center::create()
    .with_property(Selector::from("center").with_class("mainviewbox"))
    .with_child(Button::create()
          .with_property(Selector::from("button").with_class("primary"))
          .with_property(Label::from(title)),
    )))
}

fn main() {
  let mut application = Application::default();
  application
    .create_window()
    .with_bounds(Bounds::new(100, 200, 600, 400))
    .with_title("Fixed and center layouts")
    .with_theme(Theme::create()
        .with_extenstion_css(CENTER_DEMO_CSS)
        .build(),
    )
    .with_root(MainView::create())
    .with_debug_flag(false)
    .build();
  application.run();
}
<|endoftext|>


<commit_before>//! Types for computing game time from wall time.
use float_duration::FloatDuration;
use framerate::FrameCount;

/// Compute elapsed game time for a frame.
pub trait TimeProgression {
    /// Compute the game time.
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration;
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct VariableStep {}
#[derive(Debug)]
pub struct FixedStep<'a, C: 'a + FrameCount + ?Sized> {
    counter: &'a mut C,
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct ConstantStep {
    step: FloatDuration,
}

impl VariableStep {
    pub fn new() -> VariableStep {
        VariableStep {}
    }
}
impl<'a, C> FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    pub fn new(counter: &'a mut C) -> FixedStep<'a, C> {
        FixedStep { counter: counter }
    }
}
impl ConstantStep {
    pub fn new(step: FloatDuration) -> ConstantStep {
        ConstantStep { step }
    }
}

impl TimeProgression for VariableStep {
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration {
        *wall_time
    }
}
impl<'a, C> TimeProgression for FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.counter.target_time_per_frame()
    }
}
impl TimeProgression for ConstantStep {
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.step.clone()
    }
}
<commit_msg>Document `time_progression` module.<commit_after>//! Types for computing game time from wall time.
use float_duration::FloatDuration;
use framerate::FrameCount;

/// Compute elapsed game time for a frame.
pub trait TimeProgression {
    /// Compute the game time.
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration;
}

/// A time step based on elapsed wall time.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct VariableStep {}
/// A fixed time step derived from a set frame rate.
#[derive(Debug)]
pub struct FixedStep<'a, C: 'a + FrameCount + ?Sized> {
    counter: &'a mut C,
}
/// A specific, constant time step.
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct ConstantStep {
    step: FloatDuration,
}

impl VariableStep {
    /// Construct a new `VariableStep` object.
    pub fn new() -> VariableStep {
        VariableStep {}
    }
}
impl<'a, C> FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    /// Construct a new `FixedStep` object based on the set frame rate in `counter`.
    pub fn new(counter: &'a mut C) -> FixedStep<'a, C> {
        FixedStep { counter: counter }
    }
}
impl ConstantStep {
    /// Construct a new `ConstantStep` object with a set time step `step`.
    pub fn new(step: FloatDuration) -> ConstantStep {
        ConstantStep { step }
    }
}

impl TimeProgression for VariableStep {
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration {
        *wall_time
    }
}
impl<'a, C> TimeProgression for FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.counter.target_time_per_frame()
    }
}
impl TimeProgression for ConstantStep {
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.step.clone()
    }
}
<|endoftext|>


<commit_before>//! Data-structures / interpretation for extended leafs (>= 0x8000_0000)
use core::fmt::{Debug, Formatter};
use core::mem::size_of;
use core::slice;
use core::str;

use crate::{get_bits, CpuIdResult, Vendor};

/// Extended Processor and Processor Feature Identifiers (LEAF=0x8000_0001)
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct ExtendedProcessorFeatureIdentifiers {
    vendor: Vendor,
    eax: u32,
    ebx: u32,
    ecx: ExtendedFunctionInfoEcx,
    edx: ExtendedFunctionInfoEdx,
}

impl ExtendedProcessorFeatureIdentifiers {
    pub(crate) fn new(vendor: Vendor, data: CpuIdResult) -> Self {
        Self {
            vendor,
            eax: data.eax,
            ebx: data.ebx,
            // Safety: Ok we don't care/want to preseve extra bits from CpuId that we don't support (yet)
            ecx: unsafe { ExtendedFunctionInfoEcx::from_bits_unchecked(data.ecx) },
            // Safety: Ok we don't care/want to preseve extra bits from CpuId that we don't support (yet)
            edx: unsafe { ExtendedFunctionInfoEdx::from_bits_unchecked(data.edx) },
        }
    }

    /// Extended Processor Signature.
    ///
    /// # AMD
    /// The value returned is the same as the value returned in EAX for LEAF=0x0000_0001
    /// (use `CpuId.get_feature_info` instead)
    ///
    /// # Intel
    /// Vague mention of "Extended Processor Signature", not clear what it's supposed to represent.
    pub fn extended_signature(&self) -> u32 {
        self.eax
    }

    /// Returns package type on AMD.
    ///
    /// # Intel
    /// This field is not used (reseved).
    ///
    /// # AMD
    /// Package type. If (Family[7:0] >= 10h), this field is valid.
    /// If (Family[7:0]<10h), this field is reserved
    pub fn pkg_type(&self) -> u32 {
        get_bits(self.ebx, 28, 31)
    }

    /// Returns brand ID on AMD.
    ///
    /// # Intel
    /// This field is not used (reserved).
    ///
    /// # AMD
    /// This field, in conjunction with CPUID
    /// LEAF=0x0000_0001_EBX[8BitBrandId], and used by firmware to generate the
    /// processor name string.
    pub fn brand_id(&self) -> u32 {
        get_bits(self.ebx, 0, 15)
    }

    /// Is LAHF/SAHF available in 64-bit mode?
    pub fn has_lahf_sahf(&self) -> bool {
        self.ecx.contains(ExtendedFunctionInfoEcx::LAHF_SAHF)
    }

    /// Check support for 64-bit mode.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_cmp_legacy(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::CMP_LEGACY)
    }

    /// Secure virtual machine supported.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_svm(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::SVM)
    }

    /// Is LZCNT available?
    pub fn has_lzcnt(&self) -> bool {
        self.ecx.contains(ExtendedFunctionInfoEcx::LZCNT)
    }

    /// Is PREFETCHW available?
    pub fn has_prefetchw(&self) -> bool {
        self.ecx.contains(ExtendedFunctionInfoEcx::PREFETCHW)
    }

    /// Are fast system calls available.
    pub fn has_syscall_sysret(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::SYSCALL_SYSRET)
    }

    /// Is there support for execute disable bit.
    pub fn has_execute_disable(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::EXECUTE_DISABLE)
    }

    /// Is there support for 1GiB pages.
    pub fn has_1gib_pages(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::GIB_PAGES)
    }

    /// Check support for rdtscp instruction.
    pub fn has_rdtscp(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::RDTSCP)
    }

    /// Check support for 64-bit mode.
    pub fn has_64bit_mode(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::I64BIT_MODE)
    }
}

impl Debug for ExtendedProcessorFeatureIdentifiers {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        let mut ds = f.debug_struct("ExtendedProcessorFeatureIdentifiers");
        ds.field("extended_signature", &self.extended_signature());

        if self.vendor == Vendor::Amd {
            ds.field("pkg_type", &self.pkg_type());
            ds.field("brand_id", &self.brand_id());
        }
        ds.field("ecx_features", &self.ecx);
        ds.field("edx_features", &self.edx);
        ds.finish()
    }
}

bitflags! {
    #[derive(Default)]
    #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
    struct ExtendedFunctionInfoEcx: u32 {
        const LAHF_SAHF = 1 << 0;
        const CMP_LEGACY =  1 << 1;
        const SVM = 1 << 2;
        const EXT_APIC_SPACE = 1 << 3;
        const ALTMOVCR8 = 1 << 4;
        const LZCNT = 1 << 5;
        const SSE4A = 1 << 6;
        const MISALIGNSSE = 1 << 7;
        const PREFETCHW = 1 << 8;
        const OSVW = 1 << 9;
        const IBS = 1 << 10;
        const XOP = 1 << 11;
        const SKINIT = 1 << 12;
        const WDT = 1 << 13;
        const LWP = 1 << 15;
        const FMA4 = 1 << 16;
        const TBM = 1 << 21;
        const TOPEXT = 1 << 22;
        const PERFCTREXT = 1 << 23;
        const PERFCTREXTNB = 1 << 24;
        const DATABRKPEXT = 1 << 26;
        const PERFTSC = 1 << 27;
        const PERFCTREXTLLC = 1 << 28;
        const MONITORX = 1 << 29;
        const ADDRMASKEXT = 1 << 30;
    }
}

bitflags! {
    #[derive(Default)]
    #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
    struct ExtendedFunctionInfoEdx: u32 {
        const SYSCALL_SYSRET = 1 << 11;
        const EXECUTE_DISABLE = 1 << 20;
        const GIB_PAGES = 1 << 26;
        const RDTSCP = 1 << 27;
        const I64BIT_MODE = 1 << 29;
    }
}

/// ASCII string up to 48 characters in length corresponding to the processor name.
/// (LEAF = 0x8000_0002..=0x8000_0004)
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct ProcessorBrandString {
    data: [CpuIdResult; 3],
}

impl ProcessorBrandString {
    pub(crate) fn new(data: [CpuIdResult; 3]) -> Self {
        Self { data }
    }

    /// Return the processor brand string as a rust string.
    ///
    /// For example:
    /// "11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz".
    pub fn as_str(&self) -> &str {
        // Safety: CpuIdResult is laid out with repr(C), and the array
        // self.data contains 3 contiguous elements.
        let slice: &[u8] = unsafe {
            slice::from_raw_parts(
                self.data.as_ptr() as *const u8,
                self.data.len() * size_of::<CpuIdResult>(),
            )
        };

        // Brand terminated at nul byte or end, whichever comes first.
        let slice = slice.split(|&x| x == 0).next().unwrap();
        str::from_utf8(slice).unwrap_or("Invalid Processor Brand String")
    }
}

impl Debug for ProcessorBrandString {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("ProcessorBrandString")
            .field("as_str", &self.as_str())
            .finish()
    }
}
<commit_msg>Add ecx features for amd for leaf 0x8000_0001.<commit_after>//! Data-structures / interpretation for extended leafs (>= 0x8000_0000)
use core::fmt::{Debug, Formatter};
use core::mem::size_of;
use core::slice;
use core::str;

use crate::{get_bits, CpuIdResult, Vendor};

/// Extended Processor and Processor Feature Identifiers (LEAF=0x8000_0001)
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct ExtendedProcessorFeatureIdentifiers {
    vendor: Vendor,
    eax: u32,
    ebx: u32,
    ecx: ExtendedFunctionInfoEcx,
    edx: ExtendedFunctionInfoEdx,
}

impl ExtendedProcessorFeatureIdentifiers {
    pub(crate) fn new(vendor: Vendor, data: CpuIdResult) -> Self {
        Self {
            vendor,
            eax: data.eax,
            ebx: data.ebx,
            // Safety: Ok we don't care/want to preseve extra bits from CpuId that we don't support (yet)
            ecx: unsafe { ExtendedFunctionInfoEcx::from_bits_unchecked(data.ecx) },
            // Safety: Ok we don't care/want to preseve extra bits from CpuId that we don't support (yet)
            edx: unsafe { ExtendedFunctionInfoEdx::from_bits_unchecked(data.edx) },
        }
    }

    /// Extended Processor Signature.
    ///
    /// # AMD
    /// The value returned is the same as the value returned in EAX for LEAF=0x0000_0001
    /// (use `CpuId.get_feature_info` instead)
    ///
    /// # Intel
    /// Vague mention of "Extended Processor Signature", not clear what it's supposed to represent.
    pub fn extended_signature(&self) -> u32 {
        self.eax
    }

    /// Returns package type on AMD.
    ///
    /// # Intel
    /// This field is not used (reseved).
    ///
    /// # AMD
    /// Package type. If (Family[7:0] >= 10h), this field is valid.
    /// If (Family[7:0]<10h), this field is reserved
    pub fn pkg_type(&self) -> u32 {
        get_bits(self.ebx, 28, 31)
    }

    /// Returns brand ID on AMD.
    ///
    /// # Intel
    /// This field is not used (reserved).
    ///
    /// # AMD
    /// This field, in conjunction with CPUID
    /// LEAF=0x0000_0001_EBX[8BitBrandId], and used by firmware to generate the
    /// processor name string.
    pub fn brand_id(&self) -> u32 {
        get_bits(self.ebx, 0, 15)
    }

    /// Is LAHF/SAHF available in 64-bit mode?
    pub fn has_lahf_sahf(&self) -> bool {
        self.ecx.contains(ExtendedFunctionInfoEcx::LAHF_SAHF)
    }

    /// Check support for 64-bit mode.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_cmp_legacy(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::CMP_LEGACY)
    }

    /// Secure virtual machine supported.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_svm(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::SVM)
    }

    /// Extended APIC space. This bit indicates the presence of extended APIC register space starting at offset 400h from the “APIC Base Address Register,” as specified in the BKDG.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_ext_apic_space(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::EXT_APIC_SPACE)
    }

    /// LOCK MOV CR0 means MOV CR8. See “MOV(CRn)” in APM3.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_alt_mov_cr8(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::ALTMOVCR8)
    }

    /// Is LZCNT available?
    pub fn has_lzcnt(&self) -> bool {
        self.ecx.contains(ExtendedFunctionInfoEcx::LZCNT)
    }

    /// XTRQ, INSERTQ, MOVNTSS, and MOVNTSD instruction support.
    /// See “EXTRQ”, “INSERTQ”, “MOVNTSS”, and “MOVNTSD” in APM4.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_sse4a(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::SSE4A)
    }

    /// Misaligned SSE mode. See “Misaligned Access Support Added for SSE Instructions” in APM1.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_misaligned_sse_mode(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::MISALIGNSSE)
    }

    /// Is PREFETCHW available?
    ///
    /// # AMD
    /// PREFETCH and PREFETCHW instruction support.
    pub fn has_prefetchw(&self) -> bool {
        self.ecx.contains(ExtendedFunctionInfoEcx::PREFETCHW)
    }

    /// Indicates OS-visible workaround support
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_osvw(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::OSVW)
    }

    /// Instruction based sampling.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_ibs(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::IBS)
    }

    /// Extended operation support.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_xop(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::XOP)
    }

    /// SKINIT and STGI are supported.
    ///
    /// Indicates support for SKINIT and STGI, independent of
    /// the value of MSRC000_0080[SVME].
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_skinit(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::SKINIT)
    }

    /// Watchdog timer support.
    ///
    /// Indicates support for MSRC001_0074.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_wdt(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::WDT)
    }

    /// Lightweight profiling support
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_lwp(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::LWP)
    }

    /// Four-operand FMA instruction support.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_fma4(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::FMA4)
    }

    /// Trailing bit manipulation instruction support. .
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_tbm(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::TBM)
    }

    /// Topology extensions support.
    ///
    /// Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_topology_extensions(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::TOPEXT)
    }

    /// Processor performance counter extensions support.
    ///
    /// Indicates support for MSRC001_020[A,8,6,4,2,0] and MSRC001_020[B,9,7,5,3,1].
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_perf_cntr_extensions(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::PERFCTREXT)
    }

    /// NB performance counter extensions support.
    ///
    /// Indicates support for MSRC001_024[6,4,2,0] and MSRC001_024[7,5,3,1].
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_nb_perf_cntr_extensions(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::PERFCTREXTNB)
    }

    /// Data access breakpoint extension.
    ///
    /// Indicates support for MSRC001_1027 and MSRC001_101[B:9].
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_data_access_bkpt_extension(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::DATABRKPEXT)
    }

    /// Performance time-stamp counter.
    ///
    /// Indicates support for MSRC001_0280 [Performance Time Stamp Counter].
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_perf_tsc(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::PERFTSC)
    }

    /// Support for L3 performance counter extension.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_perf_cntr_llc_extensions(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::PERFCTREXTLLC)
    }

    /// Support for MWAITX and MONITORX instructions.
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_monitorx_mwaitx(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::MONITORX)
    }

    /// Breakpoint Addressing masking extended to bit 31. .
    ///
    /// # Intel
    /// This feature unavailable on Intel (will return false).
    pub fn has_addr_mask_extension(&self) -> bool {
        self.vendor == Vendor::Amd && self.ecx.contains(ExtendedFunctionInfoEcx::ADDRMASKEXT)
    }

    /// Are fast system calls available.
    pub fn has_syscall_sysret(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::SYSCALL_SYSRET)
    }

    /// Is there support for execute disable bit.
    pub fn has_execute_disable(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::EXECUTE_DISABLE)
    }

    /// Is there support for 1GiB pages.
    pub fn has_1gib_pages(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::GIB_PAGES)
    }

    /// Check support for rdtscp instruction.
    pub fn has_rdtscp(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::RDTSCP)
    }

    /// Check support for 64-bit mode.
    pub fn has_64bit_mode(&self) -> bool {
        self.edx.contains(ExtendedFunctionInfoEdx::I64BIT_MODE)
    }
}

impl Debug for ExtendedProcessorFeatureIdentifiers {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        let mut ds = f.debug_struct("ExtendedProcessorFeatureIdentifiers");
        ds.field("extended_signature", &self.extended_signature());

        if self.vendor == Vendor::Amd {
            ds.field("pkg_type", &self.pkg_type());
            ds.field("brand_id", &self.brand_id());
        }
        ds.field("ecx_features", &self.ecx);
        ds.field("edx_features", &self.edx);
        ds.finish()
    }
}

bitflags! {
    #[derive(Default)]
    #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
    struct ExtendedFunctionInfoEcx: u32 {
        const LAHF_SAHF = 1 << 0;
        const CMP_LEGACY =  1 << 1;
        const SVM = 1 << 2;
        const EXT_APIC_SPACE = 1 << 3;
        const ALTMOVCR8 = 1 << 4;
        const LZCNT = 1 << 5;
        const SSE4A = 1 << 6;
        const MISALIGNSSE = 1 << 7;
        const PREFETCHW = 1 << 8;
        const OSVW = 1 << 9;
        const IBS = 1 << 10;
        const XOP = 1 << 11;
        const SKINIT = 1 << 12;
        const WDT = 1 << 13;
        const LWP = 1 << 15;
        const FMA4 = 1 << 16;
        const TBM = 1 << 21;
        const TOPEXT = 1 << 22;
        const PERFCTREXT = 1 << 23;
        const PERFCTREXTNB = 1 << 24;
        const DATABRKPEXT = 1 << 26;
        const PERFTSC = 1 << 27;
        const PERFCTREXTLLC = 1 << 28;
        const MONITORX = 1 << 29;
        const ADDRMASKEXT = 1 << 30;
    }
}

bitflags! {
    #[derive(Default)]
    #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
    struct ExtendedFunctionInfoEdx: u32 {
        const SYSCALL_SYSRET = 1 << 11;
        const EXECUTE_DISABLE = 1 << 20;
        const GIB_PAGES = 1 << 26;
        const RDTSCP = 1 << 27;
        const I64BIT_MODE = 1 << 29;
    }
}

/// ASCII string up to 48 characters in length corresponding to the processor name.
/// (LEAF = 0x8000_0002..=0x8000_0004)
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct ProcessorBrandString {
    data: [CpuIdResult; 3],
}

impl ProcessorBrandString {
    pub(crate) fn new(data: [CpuIdResult; 3]) -> Self {
        Self { data }
    }

    /// Return the processor brand string as a rust string.
    ///
    /// For example:
    /// "11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz".
    pub fn as_str(&self) -> &str {
        // Safety: CpuIdResult is laid out with repr(C), and the array
        // self.data contains 3 contiguous elements.
        let slice: &[u8] = unsafe {
            slice::from_raw_parts(
                self.data.as_ptr() as *const u8,
                self.data.len() * size_of::<CpuIdResult>(),
            )
        };

        // Brand terminated at nul byte or end, whichever comes first.
        let slice = slice.split(|&x| x == 0).next().unwrap();
        str::from_utf8(slice).unwrap_or("Invalid Processor Brand String")
    }
}

impl Debug for ProcessorBrandString {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("ProcessorBrandString")
            .field("as_str", &self.as_str())
            .finish()
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::sync::{Once, ONCE_INIT};
use std::{mem, raw};
use std::collections::HashMap;
use libc::{c_int,c_long,c_double,size_t};
use super::{consts,err,info,opt};
use super::err::ErrCode;
use http::body::Body;
use http::{header,Response};

use curl_ffi as ffi;

pub type ProgressCb<'a> = FnMut(usize, usize, usize, usize) + 'a;

pub struct Easy {
    curl: *mut ffi::CURL
}

impl Easy {
    pub fn new() -> Easy {
        // Ensure that curl is globally initialized
        global_init();

        let handle = unsafe {
            let p = ffi::curl_easy_init();
            ffi::curl_easy_setopt(p, opt::NOPROGRESS, 0);
            p
        };

        Easy { curl: handle }
    }

    #[inline]
    pub fn setopt<T: opt::OptVal>(&mut self, option: opt::Opt, val: T) -> Result<(), err::ErrCode> {
        // TODO: Prevent setting callback related options
        let mut res = err::ErrCode(err::OK);

        unsafe {
            val.with_c_repr(|repr| {
                res = err::ErrCode(ffi::curl_easy_setopt(self.curl, option, repr));
            })
        }

        if res.is_success() { Ok(()) } else { Err(res) }
    }

    pub fn perform(&mut self,
                   body: Option<&mut Body>,
                   progress: Option<Box<ProgressCb>>)
                   -> Result<Response, err::ErrCode> {
        let mut builder = ResponseBuilder::new();

        unsafe {
            let resp_p: usize = mem::transmute(&builder);
            let body_p: usize = match body {
                Some(b) => mem::transmute(b),
                None => 0
            };

            let progress_p: usize = match progress.as_ref() {
                Some(cb) => mem::transmute(cb),
                None => 0
            };

            // Set callback options
            ffi::curl_easy_setopt(self.curl, opt::READFUNCTION, curl_read_fn);
            ffi::curl_easy_setopt(self.curl, opt::READDATA, body_p);

            ffi::curl_easy_setopt(self.curl, opt::WRITEFUNCTION, curl_write_fn);
            ffi::curl_easy_setopt(self.curl, opt::WRITEDATA, resp_p);

            ffi::curl_easy_setopt(self.curl, opt::HEADERFUNCTION, curl_header_fn);
            ffi::curl_easy_setopt(self.curl, opt::HEADERDATA, resp_p);

            ffi::curl_easy_setopt(self.curl, opt::PROGRESSFUNCTION, curl_progress_fn);
            ffi::curl_easy_setopt(self.curl, opt::PROGRESSDATA, progress_p);
        }

        let err = err::ErrCode(unsafe { ffi::curl_easy_perform(self.curl) });

        // If the request failed, abort here
        if !err.is_success() {
            return Err(err);
        }

        // Try to get the response code
        builder.code = try!(self.get_response_code());

        Ok(builder.build())
    }

    pub fn get_response_code(&self) -> Result<u32, err::ErrCode> {
        Ok(try!(self.get_info_long(info::RESPONSE_CODE)) as u32)
    }

    pub fn get_total_time(&self) -> Result<usize, err::ErrCode> {
        Ok(try!(self.get_info_long(info::TOTAL_TIME)) as usize)
    }

    fn get_info_long(&self, key: info::Key) -> Result<c_long, err::ErrCode> {
        let v: c_long = 0;
        let res = err::ErrCode(unsafe {
            ffi::curl_easy_getinfo(self.curl as *const _, key, &v)
        });

        if !res.is_success() {
            return Err(res);
        }

        Ok(v)
    }
}

#[inline]
fn global_init() {
    // Schedule curl to be cleaned up after we're done with this whole process
    static mut INIT: Once = ONCE_INIT;
    unsafe {
        INIT.call_once(|| ::std::rt::at_exit(|| ffi::curl_global_cleanup()))
    }
}

impl Drop for Easy {
    fn drop(&mut self) {
        unsafe { ffi::curl_easy_cleanup(self.curl) }
    }
}

/*
 *
 * TODO: Move this into handle
 *
 */

struct ResponseBuilder {
    code: u32,
    hdrs: HashMap<String,Vec<String>>,
    body: Vec<u8>
}

impl ResponseBuilder {
    fn new() -> ResponseBuilder {
        ResponseBuilder {
            code: 0,
            hdrs: HashMap::new(),
            body: Vec::new()
        }
    }

    fn add_header(&mut self, name: &str, val: &str) {
        // TODO: Reduce allocations
        use std::ascii::OwnedAsciiExt;
        let name = name.to_string().into_ascii_lowercase();

        let inserted = match self.hdrs.get_mut(&name) {
            Some(vals) => {
                vals.push(val.to_string());
                true
            }
            None => false
        };

        if !inserted {
            self.hdrs.insert(name, vec!(val.to_string()));
        }
    }

    fn build(self) -> Response {
        let ResponseBuilder { code, hdrs, body } = self;
        Response::new(code, hdrs, body)
    }
}

/*
 *
 * ===== Callbacks =====
 */

pub extern "C" fn curl_read_fn(p: *mut u8, size: size_t, nmemb: size_t, body: *mut Body) -> size_t {
    if body.is_null() {
        return 0;
    }

    let dst : &mut [u8] = unsafe { mem::transmute(raw::Slice { data: p, len: (size * nmemb) as usize } )};
    let body: &mut Body = unsafe { mem::transmute(body) };

    match body.read(dst.as_mut_slice()) {
        Ok(len) => len as size_t,
        Err(_) => consts::CURL_READFUNC_ABORT as size_t,
    }
}

pub extern "C" fn curl_write_fn(p: *mut u8, size: size_t, nmemb: size_t, resp: *mut ResponseBuilder) -> size_t {
    if !resp.is_null() {
        let builder: &mut ResponseBuilder = unsafe { mem::transmute(resp) };
        let chunk : &[u8] = unsafe { mem::transmute(raw::Slice { data: p, len: (size * nmemb) as usize } )};
        builder.body.push_all(chunk.as_slice());
    }

    size * nmemb
}

pub extern "C" fn curl_header_fn(p: *mut u8, size: size_t, nmemb: size_t, resp: &mut ResponseBuilder) -> size_t {
    // TODO: Skip the first call (it seems to be the status line)

    let vec : &[u8] = unsafe { mem::transmute(raw::Slice { data: p, len: (size * nmemb) as usize } )};

    match header::parse(vec.as_slice()) {
        Some((name, val)) => {
            resp.add_header(name, val);
        }
        None => {}
    }

    vec.len() as size_t
}

pub extern "C" fn curl_progress_fn(cb: *mut Box<ProgressCb>, dltotal: c_double, dlnow: c_double, ultotal: c_double, ulnow: c_double) -> c_int {
    #[inline]
    fn to_usize(v: c_double) -> usize {
        if v > 0.0 { v as usize } else { 0 }
    }

    if !cb.is_null() {
        let cb: &mut ProgressCb = unsafe { &mut **cb };
        (*cb)(to_usize(dltotal), to_usize(dlnow), to_usize(ultotal), to_usize(ulnow));
    }

    0
}
<commit_msg>Use atexit instead of rt::at_exit<commit_after>#![allow(dead_code)]

use std::sync::{Once, ONCE_INIT};
use std::{mem, raw};
use std::collections::HashMap;
use libc::{self, c_int, c_long, c_double, size_t};
use super::{consts, err, info, opt};
use super::err::ErrCode;
use http::body::Body;
use http::{header, Response};

use curl_ffi as ffi;

pub type ProgressCb<'a> = FnMut(usize, usize, usize, usize) + 'a;

pub struct Easy {
    curl: *mut ffi::CURL
}

impl Easy {
    pub fn new() -> Easy {
        // Ensure that curl is globally initialized
        global_init();

        let handle = unsafe {
            let p = ffi::curl_easy_init();
            ffi::curl_easy_setopt(p, opt::NOPROGRESS, 0);
            p
        };

        Easy { curl: handle }
    }

    #[inline]
    pub fn setopt<T: opt::OptVal>(&mut self, option: opt::Opt, val: T) -> Result<(), err::ErrCode> {
        // TODO: Prevent setting callback related options
        let mut res = err::ErrCode(err::OK);

        unsafe {
            val.with_c_repr(|repr| {
                res = err::ErrCode(ffi::curl_easy_setopt(self.curl, option, repr));
            })
        }

        if res.is_success() { Ok(()) } else { Err(res) }
    }

    pub fn perform(&mut self,
                   body: Option<&mut Body>,
                   progress: Option<Box<ProgressCb>>)
                   -> Result<Response, err::ErrCode> {
        let mut builder = ResponseBuilder::new();

        unsafe {
            let resp_p: usize = mem::transmute(&builder);
            let body_p: usize = match body {
                Some(b) => mem::transmute(b),
                None => 0
            };

            let progress_p: usize = match progress.as_ref() {
                Some(cb) => mem::transmute(cb),
                None => 0
            };

            // Set callback options
            ffi::curl_easy_setopt(self.curl, opt::READFUNCTION, curl_read_fn);
            ffi::curl_easy_setopt(self.curl, opt::READDATA, body_p);

            ffi::curl_easy_setopt(self.curl, opt::WRITEFUNCTION, curl_write_fn);
            ffi::curl_easy_setopt(self.curl, opt::WRITEDATA, resp_p);

            ffi::curl_easy_setopt(self.curl, opt::HEADERFUNCTION, curl_header_fn);
            ffi::curl_easy_setopt(self.curl, opt::HEADERDATA, resp_p);

            ffi::curl_easy_setopt(self.curl, opt::PROGRESSFUNCTION, curl_progress_fn);
            ffi::curl_easy_setopt(self.curl, opt::PROGRESSDATA, progress_p);
        }

        let err = err::ErrCode(unsafe { ffi::curl_easy_perform(self.curl) });

        // If the request failed, abort here
        if !err.is_success() {
            return Err(err);
        }

        // Try to get the response code
        builder.code = try!(self.get_response_code());

        Ok(builder.build())
    }

    pub fn get_response_code(&self) -> Result<u32, err::ErrCode> {
        Ok(try!(self.get_info_long(info::RESPONSE_CODE)) as u32)
    }

    pub fn get_total_time(&self) -> Result<usize, err::ErrCode> {
        Ok(try!(self.get_info_long(info::TOTAL_TIME)) as usize)
    }

    fn get_info_long(&self, key: info::Key) -> Result<c_long, err::ErrCode> {
        let v: c_long = 0;
        let res = err::ErrCode(unsafe {
            ffi::curl_easy_getinfo(self.curl as *const _, key, &v)
        });

        if !res.is_success() {
            return Err(res);
        }

        Ok(v)
    }
}

#[inline]
fn global_init() {
    // Schedule curl to be cleaned up after we're done with this whole process
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| unsafe {
        assert_eq!(libc::atexit(cleanup), 0);
    });

    extern fn cleanup() {
        unsafe { ffi::curl_global_cleanup() }
    }
}

impl Drop for Easy {
    fn drop(&mut self) {
        unsafe { ffi::curl_easy_cleanup(self.curl) }
    }
}

/*
 *
 * TODO: Move this into handle
 *
 */

struct ResponseBuilder {
    code: u32,
    hdrs: HashMap<String,Vec<String>>,
    body: Vec<u8>
}

impl ResponseBuilder {
    fn new() -> ResponseBuilder {
        ResponseBuilder {
            code: 0,
            hdrs: HashMap::new(),
            body: Vec::new()
        }
    }

    fn add_header(&mut self, name: &str, val: &str) {
        // TODO: Reduce allocations
        use std::ascii::OwnedAsciiExt;
        let name = name.to_string().into_ascii_lowercase();

        let inserted = match self.hdrs.get_mut(&name) {
            Some(vals) => {
                vals.push(val.to_string());
                true
            }
            None => false
        };

        if !inserted {
            self.hdrs.insert(name, vec!(val.to_string()));
        }
    }

    fn build(self) -> Response {
        let ResponseBuilder { code, hdrs, body } = self;
        Response::new(code, hdrs, body)
    }
}

/*
 *
 * ===== Callbacks =====
 */

pub extern "C" fn curl_read_fn(p: *mut u8, size: size_t, nmemb: size_t, body: *mut Body) -> size_t {
    if body.is_null() {
        return 0;
    }

    let dst : &mut [u8] = unsafe { mem::transmute(raw::Slice { data: p, len: (size * nmemb) as usize } )};
    let body: &mut Body = unsafe { mem::transmute(body) };

    match body.read(dst.as_mut_slice()) {
        Ok(len) => len as size_t,
        Err(_) => consts::CURL_READFUNC_ABORT as size_t,
    }
}

pub extern "C" fn curl_write_fn(p: *mut u8, size: size_t, nmemb: size_t, resp: *mut ResponseBuilder) -> size_t {
    if !resp.is_null() {
        let builder: &mut ResponseBuilder = unsafe { mem::transmute(resp) };
        let chunk : &[u8] = unsafe { mem::transmute(raw::Slice { data: p, len: (size * nmemb) as usize } )};
        builder.body.push_all(chunk.as_slice());
    }

    size * nmemb
}

pub extern "C" fn curl_header_fn(p: *mut u8, size: size_t, nmemb: size_t, resp: &mut ResponseBuilder) -> size_t {
    // TODO: Skip the first call (it seems to be the status line)

    let vec : &[u8] = unsafe { mem::transmute(raw::Slice { data: p, len: (size * nmemb) as usize } )};

    match header::parse(vec.as_slice()) {
        Some((name, val)) => {
            resp.add_header(name, val);
        }
        None => {}
    }

    vec.len() as size_t
}

pub extern "C" fn curl_progress_fn(cb: *mut Box<ProgressCb>, dltotal: c_double, dlnow: c_double, ultotal: c_double, ulnow: c_double) -> c_int {
    #[inline]
    fn to_usize(v: c_double) -> usize {
        if v > 0.0 { v as usize } else { 0 }
    }

    if !cb.is_null() {
        let cb: &mut ProgressCb = unsafe { &mut **cb };
        (*cb)(to_usize(dltotal), to_usize(dlnow), to_usize(ultotal), to_usize(ulnow));
    }

    0
}
<|endoftext|>


<commit_before>// Copyright 2016 Alex Regueiro
//
// 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 crate::Error;
use libc::{self, c_char, c_void};
use std::ffi::{CStr, CString};
use std::path::Path;
use std::ptr;

pub(crate) unsafe fn from_cstr(ptr: *const c_char) -> String {
    let cstr = CStr::from_ptr(ptr as *const _);
    String::from_utf8_lossy(cstr.to_bytes()).into_owned()
}

pub(crate) unsafe fn raw_data(ptr: *const c_char, size: usize) -> Option<Vec<u8>> {
    if ptr.is_null() {
        None
    } else {
        let mut dst = Vec::with_capacity(size);
        dst.set_len(size);
        ptr::copy(ptr as *const u8, dst.as_mut_ptr(), size);
        Some(dst)
    }
}

pub fn error_message(ptr: *const c_char) -> String {
    unsafe {
        let s = from_cstr(ptr);
        libc::free(ptr as *mut c_void);
        s
    }
}

pub fn opt_bytes_to_ptr<T: AsRef<[u8]>>(opt: Option<T>) -> *const c_char {
    match opt {
        Some(v) => v.as_ref().as_ptr() as *const c_char,
        None => ptr::null(),
    }
}

pub(crate) fn to_cpath<P: AsRef<Path>>(path: P) -> Result<CString, Error> {
    match CString::new(path.as_ref().to_string_lossy().as_bytes()) {
        Ok(c) => Ok(c),
        Err(e) => Err(Error::new(format!(
            "Failed to convert path to CString: {}",
            e,
        ))),
    }
}

macro_rules! ffi_try {
    ( $($function:ident)::*() ) => {
        ffi_try_impl!($($function)::*())
    };

    ( $($function:ident)::*( $arg1:expr $(, $arg:expr)* $(,)? ) ) => {
        ffi_try_impl!($($function)::*($arg1 $(, $arg)* ,))
    };
}

macro_rules! ffi_try_impl {
    ( $($function:ident)::*( $($arg:expr,)*) ) => {{
        let mut err: *mut ::libc::c_char = ::std::ptr::null_mut();
        let result = $($function)::*($($arg,)* &mut err);
        if !err.is_null() {
            return Err(Error::new($crate::ffi_util::error_message(err)));
        }
        result
    }};
}
<commit_msg>Optimize non-overlapping copy in raw_data (#583)<commit_after>// Copyright 2016 Alex Regueiro
//
// 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 crate::Error;
use libc::{self, c_char, c_void};
use std::ffi::{CStr, CString};
use std::path::Path;
use std::ptr;

pub(crate) unsafe fn from_cstr(ptr: *const c_char) -> String {
    let cstr = CStr::from_ptr(ptr as *const _);
    String::from_utf8_lossy(cstr.to_bytes()).into_owned()
}

pub(crate) unsafe fn raw_data(ptr: *const c_char, size: usize) -> Option<Vec<u8>> {
    if ptr.is_null() {
        None
    } else {
        let mut dst = Vec::with_capacity(size);
        ptr::copy_nonoverlapping(ptr as *const u8, dst.as_mut_ptr(), size);
        dst.set_len(size);
        Some(dst)
    }
}

pub fn error_message(ptr: *const c_char) -> String {
    unsafe {
        let s = from_cstr(ptr);
        libc::free(ptr as *mut c_void);
        s
    }
}

pub fn opt_bytes_to_ptr<T: AsRef<[u8]>>(opt: Option<T>) -> *const c_char {
    match opt {
        Some(v) => v.as_ref().as_ptr() as *const c_char,
        None => ptr::null(),
    }
}

pub(crate) fn to_cpath<P: AsRef<Path>>(path: P) -> Result<CString, Error> {
    match CString::new(path.as_ref().to_string_lossy().as_bytes()) {
        Ok(c) => Ok(c),
        Err(e) => Err(Error::new(format!(
            "Failed to convert path to CString: {}",
            e,
        ))),
    }
}

macro_rules! ffi_try {
    ( $($function:ident)::*() ) => {
        ffi_try_impl!($($function)::*())
    };

    ( $($function:ident)::*( $arg1:expr $(, $arg:expr)* $(,)? ) ) => {
        ffi_try_impl!($($function)::*($arg1 $(, $arg)* ,))
    };
}

macro_rules! ffi_try_impl {
    ( $($function:ident)::*( $($arg:expr,)*) ) => {{
        let mut err: *mut ::libc::c_char = ::std::ptr::null_mut();
        let result = $($function)::*($($arg,)* &mut err);
        if !err.is_null() {
            return Err(Error::new($crate::ffi_util::error_message(err)));
        }
        result
    }};
}
<|endoftext|>


<commit_before>use super::{ValueSet, ScannableSet, KnownBits, UIntMultiple, UIntRange, SIntRange};
use super::{EMPTY_UINTMULTIPLE, EMPTY_UINTRANGE, EMPTY_SINTRANGE};
use std::ops::{BitAnd, BitOr};
use util::{tzmsk, gcd_lcm, multiplicative_inverse};

// TODO: Find appropriate consts from stdlib
const U64MIN: u64 =  0x0000000000000000;
const U64MAX: u64 =  0xffffffffffffffff;
const S64MIN: i64 = -0x8000000000000000;
const S64MAX: i64 =  0x7fffffffffffffff;

impl ValueSet<u64> for UIntMultiple {
	fn contains(&self, value: u64) -> bool {
		if self.modulus == 0 { return false }
		value % self.modulus == self.residue
	}
}

impl ScannableSet<u64> for UIntMultiple {
	fn scan_up(&self, n: u64) -> Option<u64> {
		let io = self.modulus - self.residue;
		if n > U64MAX - io { return Option::None }
		let t = (n + io) % self.modulus;
		Option::Some(if t == 0 { n } else { n + (self.modulus - t) })
	}
	fn scan_dn(&self, n: u64) -> Option<u64> {
		if n < self.residue { return Option::None }
		Option::Some(n - (n-self.residue)%self.modulus)
	}
}

impl UIntMultiple {
	pub fn as_knownbits(&self) -> KnownBits {
		let z = tzmsk(self.modulus);
		KnownBits {
			zerobits: z & !self.residue,
			onebits:  z &  self.residue
		}
	}
	// dkreuter: it seems pointless to convert a multiple constraint to a range
	pub fn as_urange(&self) -> UIntRange {
		if self.modulus == 0 { return EMPTY_UINTRANGE }
		UIntRange {
			min: self.scan_up(U64MIN).unwrap_or(U64MAX),
			max: self.scan_dn(U64MAX).unwrap_or(U64MIN)
		}
	}
	pub fn as_srange(&self) -> SIntRange {
		if self.modulus == 0 { return EMPTY_SINTRANGE }
		SIntRange {
			min: self.scan_up(S64MIN as u64).or_else(|| self.scan_up(U64MIN)).unwrap_or(S64MIN as u64) as i64,
			max: self.scan_dn(S64MAX as u64).or_else(|| self.scan_dn(U64MAX)).unwrap_or(S64MAX as u64) as i64,
		}
	}
}

impl<'a, 'b> BitAnd<&'a UIntMultiple> for &'b UIntMultiple {
	type Output = UIntMultiple;

	fn bitand(self, rhs: &UIntMultiple) -> UIntMultiple {
		// calls the euclidean algorithm three times
		// TODO: get a mathematician to reduce this
		let (gcd, lcm) = gcd_lcm(self.modulus, rhs.modulus);
		let ioff = self.residue % gcd;
		if ioff != rhs.residue % gcd {
			return EMPTY_UINTMULTIPLE
		}

		// See http://artofproblemsolving.com/wiki/index.php/Chinese_Remainder_Theorem
		let y1 = self.residue / gcd;
		let y2 = rhs.residue / gcd;
		let d1 = self.modulus / gcd;
		let d2 = rhs.modulus / gcd;

		let x = if d1 == 1 {
			y2
		} else if d2 == 1 {
			y1
		} else {
			let m = d1 * d2;
			let b1 = d2; // = m / d1;
			let b2 = d1; // = m / d2;
			let a1 = match multiplicative_inverse(b1, d1) { None => return EMPTY_UINTMULTIPLE, Some(a1) => a1 };
			let a2 = match multiplicative_inverse(b2, d2) { None => return EMPTY_UINTMULTIPLE, Some(a2) => a2 };
			let x1 = a1 * b1 * y1;
			let x2 = a2 * b2 * y2;
			(x1 + x2) % m
		};

		let offset = ioff + gcd * x;

		assert_eq!(offset % self.modulus, self.residue);
		assert_eq!(offset % rhs.modulus, rhs.residue);

		UIntMultiple {
			modulus: lcm,
			residue: offset
		}
	}
}

impl<'a, 'b> BitOr<&'a UIntMultiple> for &'b UIntMultiple {
	type Output = UIntMultiple;

	fn bitor(self, rhs: &UIntMultiple) -> UIntMultiple {
		// TODO
		UIntMultiple { modulus: 0, residue: 0 }
	}
}
<commit_msg>use appropriate consts from stdlib<commit_after>use super::{ValueSet, ScannableSet, KnownBits, UIntMultiple, UIntRange, SIntRange};
use super::{EMPTY_UINTMULTIPLE, EMPTY_UINTRANGE, EMPTY_SINTRANGE};
use std;
use std::ops::{BitAnd, BitOr};
use util::{tzmsk, gcd_lcm, multiplicative_inverse};

const U64MIN: u64 =  std::u64::MIN;  // 0x0000000000000000;
const U64MAX: u64 =  std::u64::MAX;  // 0xffffffffffffffff;
const S64MIN: i64 =  std::i64::MIN;  // -0x8000000000000000;
const S64MAX: i64 =  std::i64::MAX;  // 0x7fffffffffffffff;

impl ValueSet<u64> for UIntMultiple {
	fn contains(&self, value: u64) -> bool {
		if self.modulus == 0 { return false }
		value % self.modulus == self.residue
	}
}

impl ScannableSet<u64> for UIntMultiple {
	fn scan_up(&self, n: u64) -> Option<u64> {
		let io = self.modulus - self.residue;
		if n > U64MAX - io { return Option::None }
		let t = (n + io) % self.modulus;
		Option::Some(if t == 0 { n } else { n + (self.modulus - t) })
	}
	fn scan_dn(&self, n: u64) -> Option<u64> {
		if n < self.residue { return Option::None }
		Option::Some(n - (n-self.residue)%self.modulus)
	}
}

impl UIntMultiple {
	pub fn as_knownbits(&self) -> KnownBits {
		let z = tzmsk(self.modulus);
		KnownBits {
			zerobits: z & !self.residue,
			onebits:  z &  self.residue
		}
	}
	// dkreuter: it seems pointless to convert a multiple constraint to a range
	pub fn as_urange(&self) -> UIntRange {
		if self.modulus == 0 { return EMPTY_UINTRANGE }
		UIntRange {
			min: self.scan_up(U64MIN).unwrap_or(U64MAX),
			max: self.scan_dn(U64MAX).unwrap_or(U64MIN)
		}
	}
	pub fn as_srange(&self) -> SIntRange {
		if self.modulus == 0 { return EMPTY_SINTRANGE }
		SIntRange {
			min: self.scan_up(S64MIN as u64).or_else(|| self.scan_up(U64MIN)).unwrap_or(S64MIN as u64) as i64,
			max: self.scan_dn(S64MAX as u64).or_else(|| self.scan_dn(U64MAX)).unwrap_or(S64MAX as u64) as i64,
		}
	}
}

impl<'a, 'b> BitAnd<&'a UIntMultiple> for &'b UIntMultiple {
	type Output = UIntMultiple;

	fn bitand(self, rhs: &UIntMultiple) -> UIntMultiple {
		// calls the euclidean algorithm three times
		// TODO: get a mathematician to reduce this
		let (gcd, lcm) = gcd_lcm(self.modulus, rhs.modulus);
		let ioff = self.residue % gcd;
		if ioff != rhs.residue % gcd {
			return EMPTY_UINTMULTIPLE
		}

		// See http://artofproblemsolving.com/wiki/index.php/Chinese_Remainder_Theorem
		let y1 = self.residue / gcd;
		let y2 = rhs.residue / gcd;
		let d1 = self.modulus / gcd;
		let d2 = rhs.modulus / gcd;

		let x = if d1 == 1 {
			y2
		} else if d2 == 1 {
			y1
		} else {
			let m = d1 * d2;
			let b1 = d2; // = m / d1;
			let b2 = d1; // = m / d2;
			let a1 = match multiplicative_inverse(b1, d1) { None => return EMPTY_UINTMULTIPLE, Some(a1) => a1 };
			let a2 = match multiplicative_inverse(b2, d2) { None => return EMPTY_UINTMULTIPLE, Some(a2) => a2 };
			let x1 = a1 * b1 * y1;
			let x2 = a2 * b2 * y2;
			(x1 + x2) % m
		};

		let offset = ioff + gcd * x;

		assert_eq!(offset % self.modulus, self.residue);
		assert_eq!(offset % rhs.modulus, rhs.residue);

		UIntMultiple {
			modulus: lcm,
			residue: offset
		}
	}
}

impl<'a, 'b> BitOr<&'a UIntMultiple> for &'b UIntMultiple {
	type Output = UIntMultiple;

	fn bitor(self, rhs: &UIntMultiple) -> UIntMultiple {
		// TODO
		UIntMultiple { modulus: 0, residue: 0 }
	}
}
<|endoftext|>


<commit_before>//! Example implementation for armstrong-numbers
//!
//! - Implement the solution to your exercise here.
//! - Put the stubs for any tested functions in `src/lib.rs`,
//!   whose variable names are `_` and
//!   whose contents are `unimplemented!()`.
//! - If your example implementation has dependencies, copy
//!   `Cargo.toml` into `Cargo-example.toml` and then make
//!   any modifications necessary to the latter so your example will run.
//! - Test your example by running `../../bin/test-exercise`

pub fn is_armstrong_number(num: u32) -> bool {
    let s = format!("{}", num);
    let l = s.len();
    s.chars()
        .map(|c| c.to_digit(10).unwrap().pow(l as u32))
        .sum::<u32>() == num
}
<commit_msg>Remove stub from `example.rs`<commit_after>pub fn is_armstrong_number(num: u32) -> bool {
    let s = format!("{}", num);
    let l = s.len();
    s.chars()
        .map(|c| c.to_digit(10).unwrap().pow(l as u32))
        .sum::<u32>() == num
}
<|endoftext|>