<commit_before>// NOTE: Object is a term for an entity or a prop.

use time;
use opengl_graphics::*;
use graphics::*;
use core::{Vec2};

/// A trait for positioned objects
pub trait Position {
  /// Get the x coordinate
  fn get_pos(&self) -> Vec2<i64>;
  /// Set the Vec coordinate
  fn set_pos(&mut self, new_pos: Vec2<i64>);
}

// TODO: This should probably just be a Vec2, especially since you're doing
//       things like Dir::to_vec, and you want to allow two different
//       directions at once.
/// The direction of a given object
#[derive(Clone, Copy)]
pub enum Dir {
  Left,
  Right,
  Up,
  Down,
}

impl Dir {
  fn to_vec(&self) -> Vec2<i64> {
    Vec2(
      match *self {
        Dir::Left => 1,
        Dir::Right => -1,
        _ => 0,
      },

      match *self {
        Dir::Up => 1,
        Dir::Down => -1,
      _ => 0,
      }
    )
  }
}

// TODO: Implement two directions at once. (See comment above.)

/// A movable object
pub trait Move: Position {
  /// Get the direction
  fn get_dir(&self) -> Dir;
  /// Set the direction
  fn set_dir(&mut self, new_dir: Dir);
  /// Is the object moving?
  fn is_moving(&self) -> bool;
  /// Can the object move? Or is it blocked?
  fn can_move(&self) -> bool;
  /// Move the object
  fn move_obj(&mut self, mov: Vec2<i64>) {
    let coord = self.get_pos();
    self.set_pos(coord + mov);
  }
  /// Get new coordinate
  fn get_new_pos(&self) -> Vec2<i64> {
    let dir = self.get_dir();
    self.get_pos() + dir.to_vec()
  }
  /// Move object in direction.
  fn move_obj_dir(&mut self) {
    let new_coord = self.get_new_pos();
    self.set_pos(new_coord)
  }
  /// Get the timestamp of the last move
  fn get_last_move(&self) -> f64;
  /// Set the timestamp of the last move
  fn set_last_move(&mut self, new: &f64);
  /// Get the speed of the object
  fn get_speed(&self) -> f64;
  /// Moves regularly
  fn move_reg(&mut self) {
    let now = &time::precise_time_s();
    if self.is_moving() && self.can_move()
       && self.get_last_move() - now > 1.0 / self.get_speed() {
      self.set_last_move(now);
      self.move_obj_dir();
    }
  }
  /// Get transitition point, which is in the interval [0,1]
  fn get_trans_state(&self) -> f64;
  /// Get animation frame
  fn get_animation_frame(&self) -> i16;
}

/// Trait for sprited objects
pub trait Sprite: Move {
  /// Get current sprite
  fn get_sprite(&self) -> &Texture;
  /// Get width, not neccesarily the width of the sprite, but rather the space
  /// the given object occupies. Given in fields.
  fn get_width(&self) -> i16;
  /// Get height, see note above
  fn get_height(&self) -> i16;
  /// Get the opacity of the object
  fn get_opacity(&self) -> f64;
  //
  fn draw(&self, c: &Context, gl: &mut GlGraphics);
}

// TODO: Add event trait, for objects you can click on etc.
<commit_msg>Update<commit_after>// NOTE: Object is a term for an entity or a prop.

use time;
use opengl_graphics::*;
use graphics::*;
use core::{Vec2};

/// A trait for positioned objects
pub trait Position {
  /// Get the x coordinate
  fn get_pos(&self) -> Vec2<i64>;
  /// Set the Vec coordinate
  fn set_pos(&mut self, new_pos: Vec2<i64>);
}

// TODO: This should probably just be a Vec2, especially since you're doing
//       things like Dir::to_vec, and you want to allow two different
//       directions at once.
/// The direction of a given object
#[derive(Clone, Copy)]
pub enum Dir {
  Left,
  Right,
  Up,
  Down,
}

pub struct Movement {
  dir1: Option<Dir>,
  dir2: Option<Dir>,
  state: i64, // This should change every half second
}

impl Movement {
  fn to_vec(&self) -> Vec2<i64> {
    unimplemented!()
  }
}

impl Dir {
  fn to_vec(self) -> Vec2<i64> {
    Vec2(
      match self {
        Dir::Left => 1,
        Dir::Right => -1,
        _ => 0,
      },

      match self {
        Dir::Up => 1,
        Dir::Down => -1,
      _ => 0,
      }
    )
  }
  /// Get the dir in the opposite direction
  fn invert(self) -> Dir {
    match self {
      Dir::Left => Dir::Right,
      Dir::Right => Dir::Left,
      Dir::Up => Dir::Down,
      Dir::Down => Dir::Up,
    }
  }
}

// TODO: Implement two directions at once. (See comment above.)

/// A movable object
pub trait Move: Position {
  /// Get the direction
  fn get_movement(&self) -> Movement;
  /// Set the direction
  fn set_movement(&mut self, new_dir: Movement);
  /// Is the object moving?
  fn is_moving(&self) -> bool;
  /// Can the object move? Or is it blocked?
  fn can_move(&self) -> bool;
  /// Move the object
  fn move_obj(&mut self, mov: Vec2<i64>) {
    let coord = self.get_pos();
    self.set_pos(coord + mov);
  }
  /// Get new coordinate
  fn get_new_pos(&self) -> Vec2<i64> {
    let mov = self.get_movement();
    self.get_pos() + mov.to_vec()
  }
  /// Move object in direction.
  fn move_obj_dir(&mut self) {
    let new_coord = self.get_new_pos();
    self.set_pos(new_coord)
  }
  /// Get the timestamp of the last move
  fn get_last_move(&self) -> f64;
  /// Set the timestamp of the last move
  fn set_last_move(&mut self, new: &f64);
  /// Get the speed of the object
  fn get_speed(&self) -> f64;
  /// Moves regularly
  fn move_reg(&mut self) {
    let now = &time::precise_time_s();
    if self.is_moving() && self.can_move()
       && self.get_last_move() - now > 1.0 / self.get_speed() {
      self.set_last_move(now);
      self.move_obj_dir();
    }
  }
  /// Get transitition point, which is in the interval [0,1]
  fn get_trans_state(&self) -> f64;
  /// Get animation frame
  fn get_animation_frame(&self) -> i16;
}

/// Trait for sprited objects
pub trait Sprite: Move {
  /// Get current sprite
  fn get_sprite(&self) -> &Texture;
  /// Get width, not neccesarily the width of the sprite, but rather the space
  /// the given object occupies. Given in fields.
  fn get_width(&self) -> i16;
  /// Get height, see note above
  fn get_height(&self) -> i16;
  /// Get the opacity of the object
  fn get_opacity(&self) -> f64;
  //
  fn draw(&self, c: &Context, gl: &mut GlGraphics);
}

// TODO: Add event trait, for objects you can click on etc.
<|endoftext|>


<commit_before>use io::file::FileStatus;
use state::editor::Editor;

use std::process::exit;

impl Editor {
    /// Invoke a command in the prompt
    pub fn invoke(&mut self, cmd: String) {
        let mut split = cmd.split(' ');
        let base_cmd = split.nth(0).unwrap_or("");
        let sec_cmd = split.nth(0).unwrap_or("");

        match base_cmd {
            "set" => {
                self.status_bar.msg = match self.options.set(sec_cmd) {
                    Ok(()) => format!("Option set: {}", sec_cmd),
                    Err(()) => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "unset" => {
                self.status_bar.msg = match self.options.unset(sec_cmd) {
                    Ok(()) => format!("Option unset: {}", sec_cmd),
                    Err(()) => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "toggle" | "tog" => {
                self.status_bar.msg = match self.options.toggle(sec_cmd) {
                    Ok(()) => format!("Option toggled: {}", sec_cmd),
                    Err(()) => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "get" => {
                self.status_bar.msg = match self.options.get(sec_cmd) {
                    Some(true) => format!("Option set: {}", sec_cmd),
                    Some(false) => format!("Option unset: {}", sec_cmd),
                    None => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "o" | "open" => {
                self.status_bar.msg = match self.open(sec_cmd) {
                    FileStatus::NotFound => format!("File {} could not be opened", sec_cmd),
                    FileStatus::Ok => format!("File {} opened", sec_cmd),
                    _ => unreachable!(),
                }
            },
            "w" | "write" => {
                self.status_bar.msg = match self.write(sec_cmd) {
                    FileStatus::NotFound => format!("File {} could not be opened", sec_cmd),
                    FileStatus::Ok => format!("File {} written", sec_cmd),
                    FileStatus::Other => format!("Couldn't write {}", sec_cmd),
                }
            },
            "help" => {
                self.open("/apps/sodium/help.txt");
            },
            "q" | "quit" => {
                exit(0);
            },
            c => {
                self.status_bar.msg = format!("Unknown command: {}", c);
            }
        }

        self.hint();
    }
}
<commit_msg>Add command to switch between buffers "b{n}"<commit_after>use io::file::FileStatus;
use io::redraw::RedrawTask;
use state::editor::Editor;

use std::process::exit;

enum BufferCommand {
    SwitchToBuffer(usize),
}

fn try_get_buffer_command(c: &str) -> Option<BufferCommand> {
    if !c.starts_with("b") {
        return None;
    }

    let rest : String = c.chars().skip(1).collect();

    //TODO more buffer commands

    if let Ok(number) = rest.parse::<usize>() {
        Some(BufferCommand::SwitchToBuffer(number))
    } else {
        None
    }
}

impl Editor {
    /// Invoke a command in the prompt
    pub fn invoke(&mut self, cmd: String) {
        let mut split = cmd.split(' ');
        let base_cmd = split.nth(0).unwrap_or("");
        let sec_cmd = split.nth(0).unwrap_or("");

        match base_cmd {
            "set" => {
                self.status_bar.msg = match self.options.set(sec_cmd) {
                    Ok(()) => format!("Option set: {}", sec_cmd),
                    Err(()) => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "unset" => {
                self.status_bar.msg = match self.options.unset(sec_cmd) {
                    Ok(()) => format!("Option unset: {}", sec_cmd),
                    Err(()) => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "toggle" | "tog" => {
                self.status_bar.msg = match self.options.toggle(sec_cmd) {
                    Ok(()) => format!("Option toggled: {}", sec_cmd),
                    Err(()) => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "get" => {
                self.status_bar.msg = match self.options.get(sec_cmd) {
                    Some(true) => format!("Option set: {}", sec_cmd),
                    Some(false) => format!("Option unset: {}", sec_cmd),
                    None => format!("Option does not exist: {}", sec_cmd),
                }
            },
            "o" | "open" => {
                self.status_bar.msg = match self.open(sec_cmd) {
                    FileStatus::NotFound => format!("File {} could not be opened", sec_cmd),
                    FileStatus::Ok => format!("File {} opened", sec_cmd),
                    _ => unreachable!(),
                }
            },
            "w" | "write" => {
                self.status_bar.msg = match self.write(sec_cmd) {
                    FileStatus::NotFound => format!("File {} could not be opened", sec_cmd),
                    FileStatus::Ok => format!("File {} written", sec_cmd),
                    FileStatus::Other => format!("Couldn't write {}", sec_cmd),
                }
            },
            "help" => {
                self.open("/apps/sodium/help.txt");
            },
            "q" | "quit" => {
                exit(0);
            },
            c => {
                if let Some(buffer_command) = try_get_buffer_command(c) {
                    match buffer_command {
                        BufferCommand::SwitchToBuffer(n) => {
                            if n >= self.buffers.len() {
                                self.status_bar.msg = format!("Invalid buffer #{}", n);
                            } else {
                                self.current_buffer_index = n;
                                self.redraw_task = RedrawTask::Full;
                                self.status_bar.msg = format!("Switched to buffer #{}", n);
                            }
                        },
                    }
                } else {
                    self.status_bar.msg = format!("Unknown command: {}", c);
                }
            }
        }

        self.hint();
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use super::stream::Stream;
use super::parser::{parse_statement, Statement, ParseError};

#[derive(Debug, PartialEq)]
pub enum DatabaseError {
    TableExists,
    QueryParseError,
}

#[derive(Debug)]
pub enum QueryResult {
    ResultSet,
}

impl From<ParseError> for DatabaseError {
    fn from(err: ParseError) -> DatabaseError {
        DatabaseError::QueryParseError
    }
}

pub struct Database {
    tables: HashMap<String, Stream>
}

impl Database {
    pub fn new() -> Database {
        Database{
            tables: HashMap::new()
        }
    }

    pub fn create_stream(&mut self, name: &str) -> Result<&mut Stream, DatabaseError> {
        let tmp = Stream::new();
        if self.tables.contains_key(name) {
            return Err(DatabaseError::TableExists);
        }
        self.tables.insert(name.to_string(), tmp);
        let stream = self.tables.get_mut(name).unwrap();
        Ok(stream)
    }

    fn get_stream_mut(&mut self, name: &str) -> Option<&mut Stream> {
        self.tables.get_mut(name)
    }

    pub fn execute(&mut self, query: &str) -> Result<QueryResult, DatabaseError> {
        let tmp = try!(parse_statement(query));
        let result = QueryResult::ResultSet;
        Ok(result)
    }
}

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

    // returns a valid DB for use with testing with valid simple schema
    fn get_db_with_stream() -> Database {
        let mut db = Database::new();
        db.create_stream("Jon");

        db
    }

    #[test]
    fn create_table() {
        let mut db = Database::new();
        db.create_stream("Jon");
    }

    #[test]
    fn create_table_fails_when_table_exists() {
        let mut db = get_db_with_stream();
        if let Err(result) = db.create_stream("Jon") {
            assert_eq!(result, DatabaseError::TableExists);
        } else {
            panic!("Was expecting DatabaseError::TableExists, got an OK");
        }

    }
}
<commit_msg>rigging up inserts<commit_after>use std::collections::HashMap;
use super::stream::Stream;
use super::parser::{parse_statement, Statement, ParseError};
use super::row_builder::RowBuilder;

#[derive(Debug, PartialEq)]
pub enum DatabaseError {
    TableExists,
    QueryParseError,
}

#[derive(Debug)]
pub enum QueryResult {
    ResultSet,
    Insert(u64),
}

impl From<ParseError> for DatabaseError {
    fn from(err: ParseError) -> DatabaseError {
        DatabaseError::QueryParseError
    }
}

pub struct Database {
    tables: HashMap<String, Stream>
}

impl Database {
    pub fn new() -> Database {
        Database{
            tables: HashMap::new()
        }
    }

    pub fn create_stream(&mut self, name: &str) -> Result<&mut Stream, DatabaseError> {
        let tmp = Stream::new();
        if self.tables.contains_key(name) {
            return Err(DatabaseError::TableExists);
        }
        self.tables.insert(name.to_string(), tmp);
        let stream = self.tables.get_mut(name).unwrap();
        Ok(stream)
    }

    fn get_stream_mut(&mut self, name: &str) -> Option<&mut Stream> {
        self.tables.get_mut(name)
    }

    pub fn execute(&mut self, query: &str) -> Result<QueryResult, DatabaseError> {
        let tmp = try!(parse_statement(query));

        let result = match tmp {
            Statement::Insert(stream, row_builder) =>
                self.insert(&stream, &row_builder),
            _ => Ok(QueryResult::ResultSet)
        };
        result
    }

    pub fn insert(&mut self, query: &str, row_builder: &RowBuilder) -> Result<QueryResult, DatabaseError> {
        Ok(QueryResult::Insert(0))
    }

}

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

    // returns a valid DB for use with testing with valid simple schema
    fn get_db_with_stream() -> Database {
        let mut db = Database::new();
        db.create_stream("Jon");

        db
    }

    #[test]
    fn create_table() {
        let mut db = Database::new();
        db.create_stream("Jon");
    }

    #[test]
    fn create_table_fails_when_table_exists() {
        let mut db = get_db_with_stream();
        if let Err(result) = db.create_stream("Jon") {
            assert_eq!(result, DatabaseError::TableExists);
        } else {
            panic!("Was expecting DatabaseError::TableExists, got an OK");
        }

    }
}
<|endoftext|>


<commit_before>use crate::{Geometry, Wkt, WktFloat};
use serde::de::{Deserializer, Error, Visitor};
use std::{
    default::Default,
    fmt::{self, Debug},
    marker::PhantomData,
    str::FromStr,
};

struct WktVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for WktVisitor<T> {
    fn default() -> Self {
        WktVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for WktVisitor<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    type Value = Wkt<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
    }
}

impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(WktVisitor::default())
    }
}

struct GeometryVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for GeometryVisitor<T> {
    fn default() -> Self {
        GeometryVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for GeometryVisitor<T>
where
    T: FromStr + Default + WktFloat,
{
    type Value = Geometry<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let mut wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
        if wkt.items.len() == 1 {
            Ok(wkt.items.remove(0))
        } else {
            Err(serde::de::Error::custom(
                "WKT should have only 1 Geometry item",
            ))
        }
    }
}

impl<'de, T> serde::Deserialize<'de> for Geometry<T>
where
    T: FromStr + Default + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(GeometryVisitor::default())
    }
}

/// This is a helper function to convert directly from WKT format into a geo_types::Geometry.
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_geometry")]
///     pub geometry: Geometry<f64>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Geometry::Point(_)));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_geometry<'de, D>(deserializer: D) -> Result<geo_types::Geometry<f64>, D::Error>
where
    D: Deserializer<'de>,
{
    use serde::Deserialize;
    Geometry::deserialize(deserializer).and_then(|g: Geometry<f64>| {
        use std::convert::TryInto;
        g.try_into().map_err(|e| D::Error::custom(e))
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        types::{Coord, Point},
        Geometry,
    };
    use serde::de::{
        value::{Error, StrDeserializer},
        Deserializer, Error as _, IntoDeserializer,
    };

    mod wkt {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
            let wkt = deserializer
                .deserialize_any(WktVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                wkt.items[0],
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
            let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
            assert_eq!(
                wkt.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }

    mod geometry {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
            let geometry = deserializer
                .deserialize_any(GeometryVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                geometry,
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
            let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
            assert_eq!(
                geometry.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }
}
<commit_msg>make helper function generic over float type<commit_after>use crate::{Geometry, Wkt, WktFloat};
use serde::de::{Deserializer, Error, Visitor};
use std::{
    default::Default,
    fmt::{self, Debug},
    marker::PhantomData,
    str::FromStr,
};

struct WktVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for WktVisitor<T> {
    fn default() -> Self {
        WktVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for WktVisitor<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    type Value = Wkt<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
    }
}

impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(WktVisitor::default())
    }
}

struct GeometryVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for GeometryVisitor<T> {
    fn default() -> Self {
        GeometryVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for GeometryVisitor<T>
where
    T: FromStr + Default + WktFloat,
{
    type Value = Geometry<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let mut wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
        if wkt.items.len() == 1 {
            Ok(wkt.items.remove(0))
        } else {
            Err(serde::de::Error::custom(
                "WKT should have only 1 Geometry item",
            ))
        }
    }
}

impl<'de, T> serde::Deserialize<'de> for Geometry<T>
where
    T: FromStr + Default + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(GeometryVisitor::default())
    }
}

/// This is a helper function to convert directly from WKT format into a geo_types::Geometry.
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_geometry")]
///     pub geometry: Geometry<f64>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Geometry::Point(_)));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_geometry<'de, D, T>(deserializer: D) -> Result<geo_types::Geometry<T>, D::Error>
where
    D: Deserializer<'de>,
    T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Geometry::deserialize(deserializer).and_then(|g: Geometry<T>| {
        use std::convert::TryInto;
        g.try_into().map_err(|e| D::Error::custom(e))
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        types::{Coord, Point},
        Geometry,
    };
    use serde::de::{
        value::{Error, StrDeserializer},
        Deserializer, Error as _, IntoDeserializer,
    };

    mod wkt {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
            let wkt = deserializer
                .deserialize_any(WktVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                wkt.items[0],
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
            let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
            assert_eq!(
                wkt.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }

    mod geometry {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
            let geometry = deserializer
                .deserialize_any(GeometryVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                geometry,
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
            let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
            assert_eq!(
                geometry.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }
}
<|endoftext|>


<commit_before>//! Exposes the `Furnace` trait and `IronFurnace` type.

use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;
use super::ingot::Ingot;

pub mod ironfurnace;

/// `Furnaces` are the backbone of `Iron`. They coordinate `Ingots`
/// and ensure they are resolved and called in the right order,
/// create and distribute `Alloys`, and handle incoming requests.
///
/// `Furnaces` are internal tools. Unless you want additional
/// or unusual behavior such as enhanced debug logging you
/// probably don't need to mess with `Furnace` internals.
///
/// That being said, custom `Furnaces` are extremely powerful as
/// they allow you to completely control the resolution of `Ingots`.
///
/// The default `Furnace` used in `Iron` is the `IronFurnace`.
pub trait Furnace<Rq: Request, Rs: Response>: Send + Clone {
    /// A `Furnace's` forge method will get called once per Request, and may be
    /// called either with or without an existing `Alloy`. `Forge` is responsible
    /// for delegating the request to the correct `Ingots` and in the correct
    /// order. Effectively, 99% of the work done by a `Furnace` is done here.
    fn forge(&mut self, _request: &mut Rq, _response: &mut Rs, Option<&mut Alloy>);

    /// `Smelt` is responsible for adding an `Ingot` to the `Furnace's` internal
    /// storage of `Ingots`. Different `Furnaces` may implement different behavior
    /// for smelt, but ideally an `Ingot` added here will be delegated to during
    /// Requests.
    fn smelt<I: Ingot<Rq, Rs>>(&mut self, _ingot: I);

    /// Create a new instance of `Furnace`.
    /// If you are making your own furnace, you'll need to
    /// pass a new instance of it to `Iron`, otherwise,
    /// this function will only be used internally.
    fn new() -> Self;
}

<commit_msg>(refactor) Refactored Furnace with Request and Response types.<commit_after>//! Exposes the `Furnace` trait and `IronFurnace` type.

use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;
use super::ingot::Ingot;

pub mod stackfurnace;

/// `Furnaces` are the backbone of `Iron`. They coordinate `Ingots`
/// and ensure they are resolved and called in the right order,
/// create and distribute `Alloys`, and handle incoming requests.
///
/// `Furnaces` are internal tools. Unless you want additional
/// or unusual behavior such as enhanced debug logging you
/// probably don't need to mess with `Furnace` internals.
///
/// That being said, custom `Furnaces` are extremely powerful as
/// they allow you to completely control the resolution of `Ingots`.
///
/// The default `Furnace` used in `Iron` is the `IronFurnace`.
pub trait Furnace: Send + Clone {
    /// A `Furnace's` forge method will get called once per Request, and may be
    /// called either with or without an existing `Alloy`. `Forge` is responsible
    /// for delegating the request to the correct `Ingots` and in the correct
    /// order. Effectively, 99% of the work done by a `Furnace` is done here.
    fn forge(&mut self,
             _request: &mut Request,
             _response: &mut Response,
             Option<&mut Alloy>);

    /// `Smelt` is responsible for adding an `Ingot` to the `Furnace's` internal
    /// storage of `Ingots`. Different `Furnaces` may implement different behavior
    /// for smelt, but ideally an `Ingot` added here will be delegated to during
    /// Requests.
    fn smelt<I: Ingot>(&mut self, _ingot: I);

    /// Create a new instance of `Furnace`.
    /// If you are making your own furnace, you'll need to
    /// pass a new instance of it to `Iron`, otherwise,
    /// this function will only be used internally.
    fn new() -> Self;
}

<|endoftext|>


<commit_before>extern crate num;
use rules::BJRules;
use bjaction::BJAction::HIT;
use bjaction::BJAction::STAND;
use bjaction::BJAction::DOUBLE;
use bjaction::BJAction::SURRENDER;
use bjaction::BJAction::SPLIT;
use cards::value::VALUES;
use hand::BJHand;
use std::collections::Bitv;
use self::num::bigint::BigUint;
use self::num::Zero;
use self::num::bigint::ToBigUint;
use shoe::shoe::DirectShoe;

pub trait HandHasher {
    fn hash_hand(&self, rules: &BJRules, hand: &BJHand) -> Vec<u8>;
}

pub trait DeckHasher {
    fn hash_deck(&self, rules: &BJRules, shoe: &DirectShoe) -> Vec<u8>;
}

pub struct DealerHandHasher;

struct HashRange {
    // Should be inclusive (so 1 means 2 values (0 or 1))
    max_value: uint,
    // Should be < max_value
    current_value: uint,
}

impl HashRange {
    pub fn new(max_value: uint, current_value: uint) -> HashRange {
        assert!(max_value > 1); // if the max_value == 1, then omit the dimension
        assert!(current_value < max_value);
        HashRange {
            max_value: max_value,
            current_value: current_value,
        }
    }
}

fn create_hash(ranges: &[HashRange]) -> Vec<u8> {
    // TODO: This could be a lot more efficient ...
    let mut val: BigUint = Zero::zero();
    let mut bits_required: BigUint = Zero::zero();
    for &i in ranges.iter() {
        val = val * i.max_value.to_biguint().unwrap();
        val = val + i.current_value.to_biguint().unwrap();
        bits_required = bits_required * i.max_value.to_biguint().unwrap() +
            (i.max_value - 1).to_biguint().unwrap();
    }
    let mut bv = Bitv::with_capacity(bits_required.bits(), false);
    println!("val={}, bits_required={}", val, bits_required.bits());
    let mut current_bit = 0u;
    while val > 0u.to_biguint().unwrap() {
        bv.set(current_bit, val % 2u.to_biguint().unwrap() == 1u.to_biguint().unwrap());
        current_bit += 1;
        val = val / 2u.to_biguint().unwrap();
    }
    println!("bv={}", bv);
    return bv.to_bytes();
}

impl HandHasher for DealerHandHasher {
    fn hash_hand(&self, rules: &BJRules, hand: &BJHand) -> Vec<u8> {
        let mut score = hand.score();
        // All scores > 22 are the same to us: Note may not be true for
        // push 22 rules.
        if score > 22 {
            score = 22;
        }

        // Hash together the score and softness
        assert!(score <= 22);
        create_hash([
                    HashRange::new(23, score),
                    HashRange::new(2,
        // Treat soft 17 same as hard 17 if the dealer stands on both
                                   match hand.is_soft() &&
                                         rules.dealer_hits_soft_score(hand.score()) {
                                       true => 1,
                                       false => 0,
                                         })])
    }
}

pub struct PlayerHandHasher;

impl HandHasher for PlayerHandHasher {
    fn hash_hand(&self, rules: &BJRules, hand: &BJHand) -> Vec<u8> {
        assert!(hand.len() >= 1);
        let mut score = hand.score();
        // All scores > 22 are the same to us
        if score > 22 {
            score = 22;
        }
        let is_soft = HashRange::new(2, match hand.is_soft() {
            true => 1,
            false => 0,
        });

        // TODO: Include rules.automatic_win_at_hand_length()
        // Number of cards in the hand only matter if it's 1, 2, or 3+
        // Note: Number of cards in the hand actually don't matter, since it's
        //       covered by the rules:  For example, can_double(), etc may
        //       return different rules.  This allows games where you cannot
        //       double on 9 to treat 5+4 and 3+3+3 as the same hash.
/*        let cards_in_hand_hash = HashRange::new(3, {
            if hand.len() == 1 {
                0u
            } else if hand.len() == 2 {
                1u
            } else {
                2u
            }
        });*/

        let mut v = vec![
                    HashRange::new(23, score),
                    is_soft];
        if rules.max_doubles_single_hand() > 0 {
            v.push(HashRange::new(
                rules.max_doubles_single_hand() + 1,
                hand.double_count())
            );
        }

        if rules.split_limit() > 0 {
            v.push(HashRange::new(
                rules.split_limit() + 1,
                hand.splits_done()));
            v.push(HashRange::new(
                rules.split_limit() + 1,
                hand.splits_to_solve()));
        }
        let actions = [STAND, HIT, DOUBLE, SPLIT, SURRENDER];
        for &action in actions.iter() {
            v.push(HashRange::new(2, match rules.can_take_action(hand, action) {
                true => 1,
                false => 0,
            }));
        }

        create_hash(v.as_slice())
    }
}

pub struct SuitlessDeckHasher;

/**
 * Doesn't care about the suit of the cards in the deck
 */
impl DeckHasher for SuitlessDeckHasher {
    fn hash_deck(&self, _: &BJRules, shoe: &DirectShoe) -> Vec<u8> {
        let mut vec = Vec::new();
        for &v in VALUES.iter() {
            vec.push(HashRange::new(
                    shoe.maximum_count_of_any_value() + 1,
                    shoe.count(&v)));
        }
        create_hash(vec.as_slice())
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use hand_hasher::create_hash;
    use hand_hasher::HashRange;
    use rules::BJRules;
    use shoe::randomshoe::new_infinite_shoe;
    use hand_hasher::DealerHandHasher;
    use hand_hasher::PlayerHandHasher;
    use hand_hasher::HandHasher;
    use shoe::shoe::DirectShoe;
    use shoe::directshoe::DirectActualShoe;
    use hand_hasher::SuitlessDeckHasher;
    use shoe::deck::cards_in_deck;
    use hand_hasher::DeckHasher;
    use hand::BJHand;
    use cards::value;
    use cards::value::Value;

    #[test]
    fn test_create_hash() {
        assert_eq!(
            vec![128],
            create_hash([HashRange::new(2, 1)]));
        assert_eq!(
            vec![128],
            create_hash([HashRange::new(4, 1)]));
        assert_eq!(
            vec![128],
            create_hash([HashRange::new(128, 1)]));
        assert_eq!(
            vec![128],
            create_hash([HashRange::new(256, 1)]));
        // At this boundary, we require two bytes
        assert_eq!(
            vec![128, 0],
            create_hash([HashRange::new(257, 1)]));
        // At this boundary, we require two bytes
        assert_eq!(
            vec![0, 128],
            create_hash([HashRange::new(257, 256)]));

        assert_eq!(
            vec![0],
            create_hash([
                        HashRange::new(2, 0),
                        HashRange::new(2, 0)
                        ]));
        assert_eq!(
            vec![0],
            create_hash([
                        HashRange::new(2, 0),
                        HashRange::new(128, 0)
                        ]));
        assert_eq!(
            vec![0, 0],
            create_hash([
                        HashRange::new(2, 0),
                        HashRange::new(128, 0),
                        HashRange::new(2, 0),
                        ]));
        assert_eq!(
            vec![255],
            create_hash([
                        HashRange::new(2, 1),
                        HashRange::new(16, 15),
                        HashRange::new(8, 7),
                        ]));
    }

    fn ensure_equal_values(hasher: &HandHasher, rules: BJRules, h1: Vec<Value>, h2: Vec<Value>) {
        let mut shoe = new_infinite_shoe();
        println!("Checking {} vs {}", h1, h2);

        assert_eq!(
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h1).unwrap()),
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h2).unwrap()));
    }

    fn ensure_not_equal_values(hasher: &HandHasher, rules: BJRules, h1: Vec<Value>, h2: Vec<Value>) {
        let mut shoe = new_infinite_shoe();
        println!("Checking {} vs {}", h1, h2);

        assert!(
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h1).unwrap()) !=
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h2).unwrap()));
    }

    #[test]
    fn test_dealer_hash() {
        let mut rules = BJRules::new();
        let hasher = &DealerHandHasher;

        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::SIX],
            vec![value::EIGHT, value::EIGHT]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SEVEN],
            vec![value::TEN, value::EIGHT]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SIX],
            vec![value::TEN, value::SEVEN]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SIX],
            vec![value::TEN, value::SEVEN]);
        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SEVEN],
            vec![value::TEN, value::SEVEN]);
        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::THREE],
            vec![value::TEN, value::FOUR]);

        rules = BJRules::new_complex(false, 4, true, 1);

        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SIX],
            vec![value::TEN, value::SEVEN]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SEVEN],
            vec![value::TEN, value::EIGHT]);
    }

    #[test]
    fn test_player_hash() {
        let mut rules = BJRules::new();
        let hasher = &PlayerHandHasher;

        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::SIX],
            // Not equal: You can split the 88
            vec![value::EIGHT, value::EIGHT]);

        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::FOUR],
            vec![value::EIGHT, value::SIX]);

        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::FOUR],
            vec![value::FOUR, value::TEN]);

        ensure_not_equal_values(
            hasher,
            rules,
            // Can't double/surrender the first hand
            vec![value::TEN, value::TWO, value::TWO],
            vec![value::FOUR, value::TEN]);

        ensure_not_equal_values(
            hasher,
            rules,
            // First hand is soft
            vec![value::ACE, value::SEVEN],
            vec![value::EIGHT, value::TEN]);

        // No surrender/split or double, so these two hands are the same
        rules = BJRules::new_complex(false, 0, true, 0);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::TWO, value::TWO],
            vec![value::FOUR, value::TEN]);

    }

    #[test]
    fn test_random_deck_hash() {
        let rules = BJRules::new();
        let hasher = SuitlessDeckHasher;
        let shoe = new_infinite_shoe();
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe),
            hasher.hash_deck(&rules,
                             &shoe));
        let mut shoe2 = new_infinite_shoe();
        shoe2.pop().unwrap();
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe),
            hasher.hash_deck(&rules,
                             &shoe2));
    }

    #[test]
    fn test_direct_deck_hash1() {
        let rules = BJRules::new();
        let hasher = SuitlessDeckHasher;
        let shoe1 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };
        let mut shoe2 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe1),
            hasher.hash_deck(&rules,
                             &shoe2));
        shoe2.pop().unwrap();
        assert!(
            hasher.hash_deck(&rules,
                             &shoe1) !=
            hasher.hash_deck(&rules,
                             &shoe2));
    }

    #[test]
    fn test_direct_deck_hash2() {
        let rules = BJRules::new();
        let hasher = SuitlessDeckHasher;
        let mut shoe3 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };
        let mut shoe4 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };

        shoe3.remove(&value::TEN);
        assert!(
            hasher.hash_deck(&rules,
                             &shoe3) !=
            hasher.hash_deck(&rules,
                             &shoe4));
        shoe4.remove(&value::FOUR);
        assert!(
            hasher.hash_deck(&rules,
                             &shoe3) !=
            hasher.hash_deck(&rules,
                             &shoe4));
        shoe3.remove(&value::FOUR);
        shoe4.remove(&value::TEN);
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe3),
            hasher.hash_deck(&rules,
                             &shoe4));
    }
}
<commit_msg>Make code compile on nightly build<commit_after>extern crate num;
use rules::BJRules;
use bjaction::BJAction::HIT;
use bjaction::BJAction::STAND;
use bjaction::BJAction::DOUBLE;
use bjaction::BJAction::SURRENDER;
use bjaction::BJAction::SPLIT;
use cards::value::VALUES;
use hand::BJHand;
use std::collections::Bitv;
use self::num::bigint::BigUint;
use self::num::Zero;
use self::num::bigint::ToBigUint;
use shoe::shoe::DirectShoe;

pub trait HandHasher {
    fn hash_hand(&self, rules: &BJRules, hand: &BJHand) -> Vec<u8>;
}

pub trait DeckHasher {
    fn hash_deck(&self, rules: &BJRules, shoe: &DirectShoe) -> Vec<u8>;
}

pub struct DealerHandHasher;

struct HashRange {
    // Should be inclusive (so 1 means 2 values (0 or 1))
    max_value: uint,
    // Should be < max_value
    current_value: uint,
}

impl HashRange {
    pub fn new(max_value: uint, current_value: uint) -> HashRange {
        assert!(max_value > 1); // if the max_value == 1, then omit the dimension
        assert!(current_value < max_value);
        HashRange {
            max_value: max_value,
            current_value: current_value,
        }
    }
}

fn create_hash(ranges: &[HashRange]) -> Vec<u8> {
    // TODO: This could be a lot more efficient ...
    let mut val: BigUint = Zero::zero();
    let mut bits_required: BigUint = Zero::zero();
    for &i in ranges.iter() {
        val = val * i.max_value.to_biguint().unwrap();
        val = val + i.current_value.to_biguint().unwrap();
        bits_required = bits_required * i.max_value.to_biguint().unwrap() +
            (i.max_value - 1).to_biguint().unwrap();
    }
    let mut bv = Bitv::with_capacity(bits_required.bits(), false);
    println!("val={}, bits_required={}", val, bits_required.bits());
    let mut current_bit = 0u;
    while val > 0u.to_biguint().unwrap() {
        bv.set(current_bit, val % 2u.to_biguint().unwrap() == 1u.to_biguint().unwrap());
        current_bit += 1;
        val = val / 2u.to_biguint().unwrap();
    }
    println!("bv={}", bv);
    return bv.to_bytes();
}

impl HandHasher for DealerHandHasher {
    fn hash_hand(&self, rules: &BJRules, hand: &BJHand) -> Vec<u8> {
        let mut score = hand.score();
        // All scores > 22 are the same to us: Note may not be true for
        // push 22 rules.
        if score > 22 {
            score = 22;
        }

        // Hash together the score and softness
        assert!(score <= 22);
        create_hash(&[
                    HashRange::new(23, score),
                    HashRange::new(2,
        // Treat soft 17 same as hard 17 if the dealer stands on both
                                   match hand.is_soft() &&
                                         rules.dealer_hits_soft_score(hand.score()) {
                                       true => 1,
                                       false => 0,
                                         })])
    }
}

pub struct PlayerHandHasher;

impl HandHasher for PlayerHandHasher {
    fn hash_hand(&self, rules: &BJRules, hand: &BJHand) -> Vec<u8> {
        assert!(hand.len() >= 1);
        let mut score = hand.score();
        // All scores > 22 are the same to us
        if score > 22 {
            score = 22;
        }
        let is_soft = HashRange::new(2, match hand.is_soft() {
            true => 1,
            false => 0,
        });

        // TODO: Include rules.automatic_win_at_hand_length()
        // Number of cards in the hand only matter if it's 1, 2, or 3+
        // Note: Number of cards in the hand actually don't matter, since it's
        //       covered by the rules:  For example, can_double(), etc may
        //       return different rules.  This allows games where you cannot
        //       double on 9 to treat 5+4 and 3+3+3 as the same hash.
/*        let cards_in_hand_hash = HashRange::new(3, {
            if hand.len() == 1 {
                0u
            } else if hand.len() == 2 {
                1u
            } else {
                2u
            }
        });*/

        let mut v = vec![
                    HashRange::new(23, score),
                    is_soft];
        if rules.max_doubles_single_hand() > 0 {
            v.push(HashRange::new(
                rules.max_doubles_single_hand() + 1,
                hand.double_count())
            );
        }

        if rules.split_limit() > 0 {
            v.push(HashRange::new(
                rules.split_limit() + 1,
                hand.splits_done()));
            v.push(HashRange::new(
                rules.split_limit() + 1,
                hand.splits_to_solve()));
        }
        let actions = [STAND, HIT, DOUBLE, SPLIT, SURRENDER];
        for &action in actions.iter() {
            v.push(HashRange::new(2, match rules.can_take_action(hand, action) {
                true => 1,
                false => 0,
            }));
        }

        create_hash(v.as_slice())
    }
}

pub struct SuitlessDeckHasher;

/**
 * Doesn't care about the suit of the cards in the deck
 */
impl DeckHasher for SuitlessDeckHasher {
    fn hash_deck(&self, _: &BJRules, shoe: &DirectShoe) -> Vec<u8> {
        let mut vec = Vec::new();
        for &v in VALUES.iter() {
            vec.push(HashRange::new(
                    shoe.maximum_count_of_any_value() + 1,
                    shoe.count(&v)));
        }
        create_hash(vec.as_slice())
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use hand_hasher::create_hash;
    use hand_hasher::HashRange;
    use rules::BJRules;
    use shoe::randomshoe::new_infinite_shoe;
    use hand_hasher::DealerHandHasher;
    use hand_hasher::PlayerHandHasher;
    use hand_hasher::HandHasher;
    use shoe::shoe::DirectShoe;
    use shoe::directshoe::DirectActualShoe;
    use hand_hasher::SuitlessDeckHasher;
    use shoe::deck::cards_in_deck;
    use hand_hasher::DeckHasher;
    use hand::BJHand;
    use cards::value;
    use cards::value::Value;

    #[test]
    fn test_create_hash() {
        assert_eq!(
            vec![128],
            create_hash(&[HashRange::new(2, 1)]));
        assert_eq!(
            vec![128],
            create_hash(&[HashRange::new(4, 1)]));
        assert_eq!(
            vec![128],
            create_hash(&[HashRange::new(128, 1)]));
        assert_eq!(
            vec![128],
            create_hash(&[HashRange::new(256, 1)]));
        // At this boundary, we require two bytes
        assert_eq!(
            vec![128, 0],
            create_hash(&[HashRange::new(257, 1)]));
        // At this boundary, we require two bytes
        assert_eq!(
            vec![0, 128],
            create_hash(&[HashRange::new(257, 256)]));

        assert_eq!(
            vec![0],
            create_hash(&[
                        HashRange::new(2, 0),
                        HashRange::new(2, 0)
                        ]));
        assert_eq!(
            vec![0],
            create_hash(&[
                        HashRange::new(2, 0),
                        HashRange::new(128, 0)
                        ]));
        assert_eq!(
            vec![0, 0],
            create_hash(&[
                        HashRange::new(2, 0),
                        HashRange::new(128, 0),
                        HashRange::new(2, 0),
                        ]));
        assert_eq!(
            vec![255],
            create_hash(&[
                        HashRange::new(2, 1),
                        HashRange::new(16, 15),
                        HashRange::new(8, 7),
                        ]));
    }

    fn ensure_equal_values(hasher: &HandHasher, rules: BJRules, h1: Vec<Value>, h2: Vec<Value>) {
        let mut shoe = new_infinite_shoe();
        println!("Checking {} vs {}", h1, h2);

        assert_eq!(
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h1).unwrap()),
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h2).unwrap()));
    }

    fn ensure_not_equal_values(hasher: &HandHasher, rules: BJRules, h1: Vec<Value>, h2: Vec<Value>) {
        let mut shoe = new_infinite_shoe();
        println!("Checking {} vs {}", h1, h2);

        assert!(
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h1).unwrap()) !=
            hasher.hash_hand(&rules,
                             &BJHand::new_from_deck(&mut shoe, &h2).unwrap()));
    }

    #[test]
    fn test_dealer_hash() {
        let mut rules = BJRules::new();
        let hasher = &DealerHandHasher;

        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::SIX],
            vec![value::EIGHT, value::EIGHT]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SEVEN],
            vec![value::TEN, value::EIGHT]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SIX],
            vec![value::TEN, value::SEVEN]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SIX],
            vec![value::TEN, value::SEVEN]);
        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SEVEN],
            vec![value::TEN, value::SEVEN]);
        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::THREE],
            vec![value::TEN, value::FOUR]);

        rules = BJRules::new_complex(false, 4, true, 1);

        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SIX],
            vec![value::TEN, value::SEVEN]);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::ACE, value::SEVEN],
            vec![value::TEN, value::EIGHT]);
    }

    #[test]
    fn test_player_hash() {
        let mut rules = BJRules::new();
        let hasher = &PlayerHandHasher;

        ensure_not_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::SIX],
            // Not equal: You can split the 88
            vec![value::EIGHT, value::EIGHT]);

        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::FOUR],
            vec![value::EIGHT, value::SIX]);

        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::FOUR],
            vec![value::FOUR, value::TEN]);

        ensure_not_equal_values(
            hasher,
            rules,
            // Can't double/surrender the first hand
            vec![value::TEN, value::TWO, value::TWO],
            vec![value::FOUR, value::TEN]);

        ensure_not_equal_values(
            hasher,
            rules,
            // First hand is soft
            vec![value::ACE, value::SEVEN],
            vec![value::EIGHT, value::TEN]);

        // No surrender/split or double, so these two hands are the same
        rules = BJRules::new_complex(false, 0, true, 0);
        ensure_equal_values(
            hasher,
            rules,
            vec![value::TEN, value::TWO, value::TWO],
            vec![value::FOUR, value::TEN]);

    }

    #[test]
    fn test_random_deck_hash() {
        let rules = BJRules::new();
        let hasher = SuitlessDeckHasher;
        let shoe = new_infinite_shoe();
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe),
            hasher.hash_deck(&rules,
                             &shoe));
        let mut shoe2 = new_infinite_shoe();
        shoe2.pop().unwrap();
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe),
            hasher.hash_deck(&rules,
                             &shoe2));
    }

    #[test]
    fn test_direct_deck_hash1() {
        let rules = BJRules::new();
        let hasher = SuitlessDeckHasher;
        let shoe1 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };
        let mut shoe2 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe1),
            hasher.hash_deck(&rules,
                             &shoe2));
        shoe2.pop().unwrap();
        assert!(
            hasher.hash_deck(&rules,
                             &shoe1) !=
            hasher.hash_deck(&rules,
                             &shoe2));
    }

    #[test]
    fn test_direct_deck_hash2() {
        let rules = BJRules::new();
        let hasher = SuitlessDeckHasher;
        let mut shoe3 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };
        let mut shoe4 = DirectActualShoe {
            cards: &mut cards_in_deck(1),
            initial_length: 52,
            maximum_count_of_any_value: 4,
        };

        shoe3.remove(&value::TEN);
        assert!(
            hasher.hash_deck(&rules,
                             &shoe3) !=
            hasher.hash_deck(&rules,
                             &shoe4));
        shoe4.remove(&value::FOUR);
        assert!(
            hasher.hash_deck(&rules,
                             &shoe3) !=
            hasher.hash_deck(&rules,
                             &shoe4));
        shoe3.remove(&value::FOUR);
        shoe4.remove(&value::TEN);
        assert_eq!(
            hasher.hash_deck(&rules,
                             &shoe3),
            hasher.hash_deck(&rules,
                             &shoe4));
    }
}
<|endoftext|>


<commit_before>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use rustc_serialize::Decodable;
use rustc_serialize::json::{Json, ToJson, Decoder, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(unsafe { buffer.as_ptr() as *const u32 } as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<commit_msg>Add basic write_packet<commit_after>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use std::mem::transmute;

use rustc_serialize::Encodable;
use rustc_serialize::json::{Json, ToJson, Encoder, encode, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError),
    /// Couldn't format Json server-side
    UnableToFormat(EncoderError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(unsafe { buffer.as_ptr() as *const u32 } as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

fn write_packet(stream: &mut Write, packet: &Json) -> Result<(), ResponseError> {
    let json_string = try!(encode(packet).map_err(ResponseError::UnableToFormat));
    trace!("Writing packet of length {}: {}", json_string.len(), json_string);
    if json_string.len() as u32 > ::std::u32::MAX {
        panic!("Attempted to send reply too big for the channel!");
    }
    let len_bytes = unsafe { transmute::<_, [u8; 4]>(json_string.len()) };
    stream.write_all(&len_bytes);
    stream.write_all(json_string.as_bytes()).map_err(ResponseError::IO)
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<|endoftext|>


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

//! Windows console handling

// FIXME (#13400): this is only a tiny fraction of the Windows console api

extern crate libc;

use std::io::IoResult;

use attr;
use color;
use {Terminal,UnwrappableTerminal};

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
    buf: T,
    def_foreground: color::Color,
    def_background: color::Color,
    foreground: color::Color,
    background: color::Color,
}

#[allow(non_snake_case)]
#[repr(C)]
struct CONSOLE_SCREEN_BUFFER_INFO {
    dwSize: [libc::c_short, ..2],
    dwCursorPosition: [libc::c_short, ..2],
    wAttributes: libc::WORD,
    srWindow: [libc::c_short, ..4],
    dwMaximumWindowSize: [libc::c_short, ..2],
}

#[allow(non_snake_case)]
#[link(name = "kernel32")]
extern "system" {
    fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
    fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
    fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
                                  info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
}

fn color_to_bits(color: color::Color) -> u16 {
    // magic numbers from mingw-w64's wincon.h

    let bits = match color % 8 {
        color::BLACK   => 0,
        color::BLUE    => 0x1,
        color::GREEN   => 0x2,
        color::RED     => 0x4,
        color::YELLOW  => 0x2 | 0x4,
        color::MAGENTA => 0x1 | 0x4,
        color::CYAN    => 0x1 | 0x2,
        color::WHITE   => 0x1 | 0x2 | 0x4,
        _ => unreachable!()
    };

    if color >= 8 {
        bits | 0x8
    } else {
        bits
    }
}

fn bits_to_color(bits: u16) -> color::Color {
    let bits = bits & 0x7;
    let color = match bits {
        0 => color::BLACK,
        0x1 => color::BLUE,
        0x2 => color::GREEN,
        0x4 => color::RED,
        0x6 => color::YELLOW,
        0x5 => color::MAGENTA,
        0x3 => color::CYAN,
        0x7 => color::WHITE,
        _ => unreachable!()
    };

    if bits >= 8 {
        color | 0x8
    } else {
        color
    }
}

impl<T: Writer+Send> WinConsole<T> {
    fn apply(&mut self) {
        let _unused = self.buf.flush();
        let mut accum: libc::WORD = 0;
        accum |= color_to_bits(self.foreground);
        accum |= color_to_bits(self.background) << 4;

        unsafe {
            // Magic -11 means stdout, from
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
            //
            // You may be wondering, "but what about stderr?", and the answer
            // to that is that setting terminal attributes on the stdout
            // handle also sets them for stderr, since they go to the same
            // terminal! Admittedly, this is fragile, since stderr could be
            // redirected to a different console. This is good enough for
            // rustc though. See #13400.
            let out = GetStdHandle(-11);
            SetConsoleTextAttribute(out, accum);
        }
    }

    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
        let fg;
        let bg;
        unsafe {
            let mut buffer_info = ::std::mem::uninitialized();
            if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
                fg = bits_to_color(buffer_info.wAttributes);
                bg = bits_to_color(buffer_info.wAttributes >> 4);
            } else {
                fg = color::WHITE;
                bg = color::BLACK;
            }
        }
        Some(box WinConsole { buf: out,
                              def_foreground: fg, def_background: bg,
                              foreground: fg, background: bg } as Box<Terminal<T>+Send>)
    }
}

impl<T: Writer> Writer for WinConsole<T> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.buf.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.buf.flush()
    }
}

impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
    fn fg(&mut self, color: color::Color) -> IoResult<bool> {
        self.foreground = color;
        self.apply();

        Ok(true)
    }

    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
        self.background = color;
        self.apply();

        Ok(true)
    }

    fn attr(&mut self, attr: attr::Attr) -> IoResult<bool> {
        match attr {
            attr::ForegroundColor(f) => {
                self.foreground = f;
                self.apply();
                Ok(true)
            },
            attr::BackgroundColor(b) => {
                self.background = b;
                self.apply();
                Ok(true)
            },
            _ => Ok(false)
        }
    }

    fn supports_attr(&self, attr: attr::Attr) -> bool {
        // it claims support for underscore and reverse video, but I can't get
        // it to do anything -cmr
        match attr {
            attr::ForegroundColor(_) | attr::BackgroundColor(_) => true,
            _ => false
        }
    }

    fn reset(&mut self) -> IoResult<()> {
        self.foreground = self.def_foreground;
        self.background = self.def_background;
        self.apply();

        Ok(())
    }

    fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

    fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}

impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
    fn unwrap(self) -> T { self.buf }
}
<commit_msg>Really fix #17982 this time.<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Windows console handling

// FIXME (#13400): this is only a tiny fraction of the Windows console api

extern crate libc;

use std::io::IoResult;

use attr;
use color;
use {Terminal,UnwrappableTerminal};

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
    buf: T,
    def_foreground: color::Color,
    def_background: color::Color,
    foreground: color::Color,
    background: color::Color,
}

#[allow(non_snake_case)]
#[repr(C)]
struct CONSOLE_SCREEN_BUFFER_INFO {
    dwSize: [libc::c_short, ..2],
    dwCursorPosition: [libc::c_short, ..2],
    wAttributes: libc::WORD,
    srWindow: [libc::c_short, ..4],
    dwMaximumWindowSize: [libc::c_short, ..2],
}

#[allow(non_snake_case)]
#[link(name = "kernel32")]
extern "system" {
    fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
    fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
    fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
                                  info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
}

fn color_to_bits(color: color::Color) -> u16 {
    // magic numbers from mingw-w64's wincon.h

    let bits = match color % 8 {
        color::BLACK   => 0,
        color::BLUE    => 0x1,
        color::GREEN   => 0x2,
        color::RED     => 0x4,
        color::YELLOW  => 0x2 | 0x4,
        color::MAGENTA => 0x1 | 0x4,
        color::CYAN    => 0x1 | 0x2,
        color::WHITE   => 0x1 | 0x2 | 0x4,
        _ => unreachable!()
    };

    if color >= 8 {
        bits | 0x8
    } else {
        bits
    }
}

fn bits_to_color(bits: u16) -> color::Color {
    let color = match bits & 0x7 {
        0 => color::BLACK,
        0x1 => color::BLUE,
        0x2 => color::GREEN,
        0x4 => color::RED,
        0x6 => color::YELLOW,
        0x5 => color::MAGENTA,
        0x3 => color::CYAN,
        0x7 => color::WHITE,
        _ => unreachable!()
    };

    color | (bits & 0x8) // copy the hi-intensity bit
}

impl<T: Writer+Send> WinConsole<T> {
    fn apply(&mut self) {
        let _unused = self.buf.flush();
        let mut accum: libc::WORD = 0;
        accum |= color_to_bits(self.foreground);
        accum |= color_to_bits(self.background) << 4;

        unsafe {
            // Magic -11 means stdout, from
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
            //
            // You may be wondering, "but what about stderr?", and the answer
            // to that is that setting terminal attributes on the stdout
            // handle also sets them for stderr, since they go to the same
            // terminal! Admittedly, this is fragile, since stderr could be
            // redirected to a different console. This is good enough for
            // rustc though. See #13400.
            let out = GetStdHandle(-11);
            SetConsoleTextAttribute(out, accum);
        }
    }

    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
        let fg;
        let bg;
        unsafe {
            let mut buffer_info = ::std::mem::uninitialized();
            if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
                fg = bits_to_color(buffer_info.wAttributes);
                bg = bits_to_color(buffer_info.wAttributes >> 4);
            } else {
                fg = color::WHITE;
                bg = color::BLACK;
            }
        }
        Some(box WinConsole { buf: out,
                              def_foreground: fg, def_background: bg,
                              foreground: fg, background: bg } as Box<Terminal<T>+Send>)
    }
}

impl<T: Writer> Writer for WinConsole<T> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.buf.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.buf.flush()
    }
}

impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
    fn fg(&mut self, color: color::Color) -> IoResult<bool> {
        self.foreground = color;
        self.apply();

        Ok(true)
    }

    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
        self.background = color;
        self.apply();

        Ok(true)
    }

    fn attr(&mut self, attr: attr::Attr) -> IoResult<bool> {
        match attr {
            attr::ForegroundColor(f) => {
                self.foreground = f;
                self.apply();
                Ok(true)
            },
            attr::BackgroundColor(b) => {
                self.background = b;
                self.apply();
                Ok(true)
            },
            _ => Ok(false)
        }
    }

    fn supports_attr(&self, attr: attr::Attr) -> bool {
        // it claims support for underscore and reverse video, but I can't get
        // it to do anything -cmr
        match attr {
            attr::ForegroundColor(_) | attr::BackgroundColor(_) => true,
            _ => false
        }
    }

    fn reset(&mut self) -> IoResult<()> {
        self.foreground = self.def_foreground;
        self.background = self.def_background;
        self.apply();

        Ok(())
    }

    fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

    fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}

impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
    fn unwrap(self) -> T { self.buf }
}
<|endoftext|>


<commit_before>use bits::Dibit;
use buffer;
use coding::bch;
use error::{Result, P25Error};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum NetworkAccessCode {
    Default,
    ReceiveAny,
    RepeatAny,
    Other(u16),
}

impl NetworkAccessCode {
    pub fn from_bits(bits: u16) -> NetworkAccessCode {
        use self::NetworkAccessCode::*;

        assert!(bits >> 12 == 0);

        match bits {
            0x293 => Default,
            0xF7E => ReceiveAny,
            0xF7F => RepeatAny,
            _ => Other(bits),
        }
    }

    pub fn to_bits(&self) -> u16 {
        use self::NetworkAccessCode::*;

        match *self {
            Default => 0x293,
            ReceiveAny => 0xF7E,
            RepeatAny => 0xF7F,
            Other(bits) => bits,
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DataUnit {
    VoiceHeader,
    VoiceSimpleTerminator,
    VoiceLCTerminator,
    VoiceLCFrameGroup,
    VoiceCCFrameGroup,
    DataPacket,
    TrunkingSignaling,
}

impl DataUnit {
    pub fn from_bits(bits: u8) -> Option<DataUnit> {
        use self::DataUnit::*;

        assert!(bits >> 4 == 0);

        match bits {
            0b0000 => Some(VoiceHeader),
            0b0011 => Some(VoiceSimpleTerminator),
            0b1111 => Some(VoiceLCTerminator),
            0b0101 => Some(VoiceLCFrameGroup),
            0b1010 => Some(VoiceCCFrameGroup),
            0b1100 => Some(DataPacket),
            0b0111 => Some(TrunkingSignaling),
            _ => None,
        }
    }

    pub fn to_bits(&self) -> u8 {
        use self::DataUnit::*;

        match *self {
            VoiceHeader => 0b0000,
            VoiceSimpleTerminator => 0b0011,
            VoiceLCTerminator => 0b1111,
            VoiceLCFrameGroup => 0b0101,
            VoiceCCFrameGroup => 0b1010,
            DataPacket => 0b1100,
            TrunkingSignaling => 0b0111,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct NetworkID {
    pub access_code: NetworkAccessCode,
    pub data_unit: DataUnit,
}

impl NetworkID {
    pub fn new(access_code: u16, data_unit: DataUnit) -> NetworkID {
        NetworkID {
            access_code: NetworkAccessCode::from_bits(access_code),
            data_unit: data_unit,
        }
    }

    pub fn from_bits(bits: u16) -> Option<NetworkID> {
        match DataUnit::from_bits(bits as u8 & 0b1111) {
            Some(du) => Some(NetworkID::new(bits >> 4, du)),
            None => None,
        }
    }

    pub fn to_bits(&self) -> u16 {
        (self.access_code.to_bits() as u16) << 4 | self.data_unit.to_bits() as u16
    }

    pub fn encode(&self) -> [u8; 8] {
        let bits = self.to_bits();
        let e = bch::encode(bits);

        [
            (e >> 56) as u8,
            (e >> 48) as u8,
            (e >> 40) as u8,
            (e >> 32) as u8,
            (e >> 24) as u8,
            (e >> 16) as u8,
            (e >> 8) as u8,
            e as u8,
        ]
    }
}

pub struct NIDReceiver {
    dibits: buffer::Buffer<buffer::NIDStorage>,
}

impl NIDReceiver {
    pub fn new() -> NIDReceiver {
        NIDReceiver {
            dibits: buffer::Buffer::new(buffer::NIDStorage::new()),
        }
    }

    pub fn feed(&mut self, dibit: Dibit) -> Option<Result<NetworkID>> {
        let buf = match self.dibits.feed(dibit) {
            Some(buf) => *buf,
            None => return None,
        };

        let data = match bch::decode(buf) {
            Some((data, err)) => data,
            None => return Some(Err(P25Error::BCHUnrecoverable)),
        };

        match NetworkID::from_bits(data) {
            Some(nid) => Some(Ok(nid)),
            None => Some(Err(P25Error::UnknownNID)),
        }
    }
}
<commit_msg>Change NetworkID::new to take NetworkAccessCode<commit_after>use bits::Dibit;
use buffer;
use coding::bch;
use error::{Result, P25Error};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum NetworkAccessCode {
    Default,
    ReceiveAny,
    RepeatAny,
    Other(u16),
}

impl NetworkAccessCode {
    pub fn from_bits(bits: u16) -> NetworkAccessCode {
        use self::NetworkAccessCode::*;

        assert!(bits >> 12 == 0);

        match bits {
            0x293 => Default,
            0xF7E => ReceiveAny,
            0xF7F => RepeatAny,
            _ => Other(bits),
        }
    }

    pub fn to_bits(&self) -> u16 {
        use self::NetworkAccessCode::*;

        match *self {
            Default => 0x293,
            ReceiveAny => 0xF7E,
            RepeatAny => 0xF7F,
            Other(bits) => bits,
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DataUnit {
    VoiceHeader,
    VoiceSimpleTerminator,
    VoiceLCTerminator,
    VoiceLCFrameGroup,
    VoiceCCFrameGroup,
    DataPacket,
    TrunkingSignaling,
}

impl DataUnit {
    pub fn from_bits(bits: u8) -> Option<DataUnit> {
        use self::DataUnit::*;

        assert!(bits >> 4 == 0);

        match bits {
            0b0000 => Some(VoiceHeader),
            0b0011 => Some(VoiceSimpleTerminator),
            0b1111 => Some(VoiceLCTerminator),
            0b0101 => Some(VoiceLCFrameGroup),
            0b1010 => Some(VoiceCCFrameGroup),
            0b1100 => Some(DataPacket),
            0b0111 => Some(TrunkingSignaling),
            _ => None,
        }
    }

    pub fn to_bits(&self) -> u8 {
        use self::DataUnit::*;

        match *self {
            VoiceHeader => 0b0000,
            VoiceSimpleTerminator => 0b0011,
            VoiceLCTerminator => 0b1111,
            VoiceLCFrameGroup => 0b0101,
            VoiceCCFrameGroup => 0b1010,
            DataPacket => 0b1100,
            TrunkingSignaling => 0b0111,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct NetworkID {
    pub access_code: NetworkAccessCode,
    pub data_unit: DataUnit,
}

impl NetworkID {
    pub fn new(access_code: NetworkAccessCode, data_unit: DataUnit) -> NetworkID {
        NetworkID {
            access_code: access_code,
            data_unit: data_unit,
        }
    }

    pub fn from_bits(bits: u16) -> Option<NetworkID> {
        match DataUnit::from_bits(bits as u8 & 0b1111) {
            Some(du) => Some(NetworkID::new(NetworkAccessCode::from_bits(bits >> 4), du)),
            None => None,
        }
    }

    pub fn to_bits(&self) -> u16 {
        (self.access_code.to_bits() as u16) << 4 | self.data_unit.to_bits() as u16
    }

    pub fn encode(&self) -> [u8; 8] {
        let bits = self.to_bits();
        let e = bch::encode(bits);

        [
            (e >> 56) as u8,
            (e >> 48) as u8,
            (e >> 40) as u8,
            (e >> 32) as u8,
            (e >> 24) as u8,
            (e >> 16) as u8,
            (e >> 8) as u8,
            e as u8,
        ]
    }
}

pub struct NIDReceiver {
    dibits: buffer::Buffer<buffer::NIDStorage>,
}

impl NIDReceiver {
    pub fn new() -> NIDReceiver {
        NIDReceiver {
            dibits: buffer::Buffer::new(buffer::NIDStorage::new()),
        }
    }

    pub fn feed(&mut self, dibit: Dibit) -> Option<Result<NetworkID>> {
        let buf = match self.dibits.feed(dibit) {
            Some(buf) => *buf,
            None => return None,
        };

        let data = match bch::decode(buf) {
            Some((data, err)) => data,
            None => return Some(Err(P25Error::BCHUnrecoverable)),
        };

        match NetworkID::from_bits(data) {
            Some(nid) => Some(Ok(nid)),
            None => Some(Err(P25Error::UnknownNID)),
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    io::{self, Read, Write},
    ops::AddAssign,
};

use serde::Serialize;
use shakmaty::{Color, Outcome};

use crate::model::{read_uint, write_uint};

#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize)]
pub struct Stats {
    pub rating_sum: u64,
    pub white: u64,
    pub draws: u64,
    pub black: u64,
}

impl Stats {
    pub fn new_single(outcome: Outcome, rating: u16) -> Stats {
        Stats {
            rating_sum: u64::from(rating),
            white: if outcome.winner() == Some(Color::White) {
                1
            } else {
                0
            },
            black: if outcome.winner() == Some(Color::Black) {
                1
            } else {
                0
            },
            draws: if outcome.winner().is_none() { 1 } else { 0 },
        }
    }
}

impl AddAssign for Stats {
    fn add_assign(&mut self, rhs: Stats) {
        self.rating_sum += rhs.rating_sum;
        self.white += rhs.white;
        self.draws += rhs.draws;
        self.black += rhs.black;
    }
}

impl Stats {
    pub fn total(&self) -> u64 {
        self.white + self.draws + self.black
    }

    pub fn is_empty(&self) -> bool {
        self.total() == 0
    }

    pub fn is_single(&self) -> bool {
        self.total() == 1
    }

    pub fn average_rating(&self) -> Option<u64> {
        self.rating_sum.checked_div(self.total())
    }

    pub fn read<R: Read>(reader: &mut R) -> io::Result<Stats> {
        let rating_sum = read_uint(reader)?;
        Ok(match read_uint(reader)? {
            0 => Stats {
                rating_sum,
                white: 1,
                draws: 0,
                black: 0,
            },
            1 => Stats {
                rating_sum,
                white: 0,
                draws: 0,
                black: 1,
            },
            2 => Stats {
                rating_sum,
                white: 0,
                draws: 1,
                black: 0,
            },
            white_plus_three => Stats {
                rating_sum,
                white: white_plus_three - 3,
                draws: read_uint(reader)?,
                black: read_uint(reader)?,
            },
        })
    }

    pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        write_uint(writer, self.rating_sum)?;
        match *self {
            Stats {
                white: 1,
                draws: 0,
                black: 0,
                ..
            } => write_uint(writer, 0),
            Stats {
                white: 0,
                draws: 0,
                black: 1,
                ..
            } => write_uint(writer, 1),
            Stats {
                white: 0,
                draws: 1,
                black: 0,
                ..
            } => write_uint(writer, 2),
            Stats {
                white,
                draws,
                black,
                ..
            } => {
                write_uint(writer, white + 3)?;
                write_uint(writer, draws)?;
                write_uint(writer, black)
            }
        }
    }
}

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

    use quickcheck::{quickcheck, Arbitrary, Gen};

    use super::*;

    impl Arbitrary for Stats {
        fn arbitrary(g: &mut Gen) -> Self {
            Stats {
                rating_sum: u64::from(u32::arbitrary(g)),
                white: u64::from(u32::arbitrary(g)),
                draws: u64::from(u32::arbitrary(g)),
                black: u64::from(u32::arbitrary(g)),
            }
        }
    }

    quickcheck! {
        fn test_stats_roundtrip(stats: Stats) -> bool {
            let mut cursor = Cursor::new(Vec::new());
            stats.write(&mut cursor).unwrap();

            let mut cursor = Cursor::new(cursor.into_inner());
            Stats::read(&mut cursor).unwrap() == stats
        }
    }
}
<commit_msg>do not json seralize rating_sum<commit_after>use std::{
    io::{self, Read, Write},
    ops::AddAssign,
};

use serde::Serialize;
use shakmaty::{Color, Outcome};

use crate::model::{read_uint, write_uint};

#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize)]
pub struct Stats {
    #[serde(skip)]
    pub rating_sum: u64,
    pub white: u64,
    pub draws: u64,
    pub black: u64,
}

impl Stats {
    pub fn new_single(outcome: Outcome, rating: u16) -> Stats {
        Stats {
            rating_sum: u64::from(rating),
            white: if outcome.winner() == Some(Color::White) {
                1
            } else {
                0
            },
            black: if outcome.winner() == Some(Color::Black) {
                1
            } else {
                0
            },
            draws: if outcome.winner().is_none() { 1 } else { 0 },
        }
    }
}

impl AddAssign for Stats {
    fn add_assign(&mut self, rhs: Stats) {
        self.rating_sum += rhs.rating_sum;
        self.white += rhs.white;
        self.draws += rhs.draws;
        self.black += rhs.black;
    }
}

impl Stats {
    pub fn total(&self) -> u64 {
        self.white + self.draws + self.black
    }

    pub fn is_empty(&self) -> bool {
        self.total() == 0
    }

    pub fn is_single(&self) -> bool {
        self.total() == 1
    }

    pub fn average_rating(&self) -> Option<u64> {
        self.rating_sum.checked_div(self.total())
    }

    pub fn read<R: Read>(reader: &mut R) -> io::Result<Stats> {
        let rating_sum = read_uint(reader)?;
        Ok(match read_uint(reader)? {
            0 => Stats {
                rating_sum,
                white: 1,
                draws: 0,
                black: 0,
            },
            1 => Stats {
                rating_sum,
                white: 0,
                draws: 0,
                black: 1,
            },
            2 => Stats {
                rating_sum,
                white: 0,
                draws: 1,
                black: 0,
            },
            white_plus_three => Stats {
                rating_sum,
                white: white_plus_three - 3,
                draws: read_uint(reader)?,
                black: read_uint(reader)?,
            },
        })
    }

    pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        write_uint(writer, self.rating_sum)?;
        match *self {
            Stats {
                white: 1,
                draws: 0,
                black: 0,
                ..
            } => write_uint(writer, 0),
            Stats {
                white: 0,
                draws: 0,
                black: 1,
                ..
            } => write_uint(writer, 1),
            Stats {
                white: 0,
                draws: 1,
                black: 0,
                ..
            } => write_uint(writer, 2),
            Stats {
                white,
                draws,
                black,
                ..
            } => {
                write_uint(writer, white + 3)?;
                write_uint(writer, draws)?;
                write_uint(writer, black)
            }
        }
    }
}

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

    use quickcheck::{quickcheck, Arbitrary, Gen};

    use super::*;

    impl Arbitrary for Stats {
        fn arbitrary(g: &mut Gen) -> Self {
            Stats {
                rating_sum: u64::from(u32::arbitrary(g)),
                white: u64::from(u32::arbitrary(g)),
                draws: u64::from(u32::arbitrary(g)),
                black: u64::from(u32::arbitrary(g)),
            }
        }
    }

    quickcheck! {
        fn test_stats_roundtrip(stats: Stats) -> bool {
            let mut cursor = Cursor::new(Vec::new());
            stats.write(&mut cursor).unwrap();

            let mut cursor = Cursor::new(cursor.into_inner());
            Stats::read(&mut cursor).unwrap() == stats
        }
    }
}
<|endoftext|>