<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod convert;

pub use convert::{FromLossy, IntoLossy};

use log::error;

pub fn convert<T, U>(item: T) -> U
where
    T: IntoLossy<U>,
{
    item.into_lossy()
}

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        // TODO: Move this into some utility module.
        // TODO: Add support for other log types.
        macro_rules! ack {
            { $expr:expr, error: $message:literal } => {
                match $expr {
                    Ok(value) => Some(value),
                    Err(err) => {
                        ::log::error!(concat!($message, ": {}"), err);
                        None
                    },
                }
            };
        }

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let btime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|crtime| ack! {
            secs(crtime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = match u64::try_from(metadata.ctime()) {
            Ok(ctime_secs) => Some(ctime_secs),
            Err(err) => {
                error!("negative inode change time: {}", err);
                None
            },
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_crtime: btime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

impl From<std::num::TryFromIntError> for MicrosError {

    fn from(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();
    Ok(std::convert::TryInto::try_into(time_micros)?)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<commit_msg>Simplify error handling for inode change time.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod convert;

pub use convert::{FromLossy, IntoLossy};

pub fn convert<T, U>(item: T) -> U
where
    T: IntoLossy<U>,
{
    item.into_lossy()
}

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        // TODO: Move this into some utility module.
        // TODO: Add support for other log types.
        macro_rules! ack {
            { $expr:expr, error: $message:literal } => {
                match $expr {
                    Ok(value) => Some(value),
                    Err(err) => {
                        ::log::error!(concat!($message, ": {}"), err);
                        None
                    },
                }
            };
        }

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let btime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|crtime| ack! {
            secs(crtime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = ack! {
            u64::try_from(metadata.ctime()),
            error: "negative inode change time"
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_crtime: btime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

impl From<std::num::TryFromIntError> for MicrosError {

    fn from(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();
    Ok(std::convert::TryInto::try_into(time_micros)?)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<|endoftext|>


<commit_before>pub struct Model {
    pub board: Board,
    pub turn: Turn,
    pub white_pieces: u32,
    pub white_hexes: u32,
    pub black_pieces: u32,
    pub black_hexes: u32,
    pub selected_piece: Option<FieldCoord>,
}

impl Model {
    pub fn init() -> Model {
        Model {
            board: Board::new(),
            turn: Turn::White,
            white_pieces: 18,
            white_hexes: 0,
            black_pieces: 18,
            black_hexes: 0,
            selected_piece: None,
        }
    }
}

pub enum Turn {
    White,
    Black,
}

pub struct Board {
    // The hex board uses an axial coordinate system with (0, 0) at the center. The x-axis slopes
    // up to the right, and the y-axis goes up and down. The board is stored as a dense 2D array,
    // as a ragged array won't work (since each row would have to be a different type).
    board: [[Option<Hex>; 5]; 5],
}

// Fields are numbered clockwise from the top. Even indicies are black, odd indicies are white.
type Hex = [Field; 6];

// There's no need to store the color of the piece on this field, since only white pieces can be on
// white fields, and vice versa.
#[derive(Clone, Copy)]
pub enum Field {
    Piece,
    Empty,
}

impl Board {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    /// Create a new board with the "Laurentius" starting position.
    pub fn new() -> Board {
        let mut board = [[None; 5]; 5];

        // (0, 0) is the only empty hex
        board[2][2] = Some([Field::Empty; 6]);

        // Conveniently, each hex (except for (0, 0)) has exactly two pieces on it in the starting
        // position. The format here is (hex_x, hex_y, field1, field2).
        let piece_locations = [
            (-2,  2, 0, 4),
            (-2,  1, 0, 3),
            (-2,  0, 3, 5),
            (-1,  2, 1, 4),
            (-1,  1, 0, 4),
            (-1,  0, 3, 5),
            (-1, -1, 2, 5),
            ( 0,  2, 1, 5),
            ( 0,  1, 1, 5),
            ( 0, -1, 2, 4),
            ( 0, -2, 2, 4),
            ( 1,  1, 2, 5),
            ( 1,  0, 0, 2),
            ( 1, -1, 1, 3),
            ( 1, -2, 1, 4),
            ( 2,  0, 0, 2),
            ( 2, -1, 0, 3),
            ( 2, -2, 1, 3),
        ];

        for &(x, y, f1, f2) in &piece_locations {
            let mut hex = [Field::Empty; 6];
            hex[f1] = Field::Piece;
            hex[f2] = Field::Piece;
            board[(x + 2) as usize][(y + 2) as usize] = Some(hex);
        }

        Board { board }
    }

    pub fn get_field(&self, coord: &FieldCoord) -> &Field {
        match *self.get_hex(&coord.to_hex()) {
            Some(ref hex) => &hex[coord.f as usize],
            None => panic!("Tried to get field on removed hex: {:?}", coord),
        }
    }
    /// Return fields that share an edge with the given field. These fields are always the opposite
    /// color of the given field. If all of a piece's edge neighbors are occupied, that piece might
    /// be capturable.
    pub fn get_field_edge_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![
            // There are always two edge neighbors on the same hex as the given field
            FieldCoord {
                f: (coord.f + 1) % 6,
                ..*coord
            },
            FieldCoord {
                f: (coord.f + 5) % 6,
                ..*coord
            },
        ];

        for (i, neighbor) in coord.to_hex().get_neighbors() {
            if coord.f == i && self.get_hex(&neighbor).is_some() {
                let f = (i + 3) % 6;
                neighbors.push(neighbor.to_field(f));
                break;
            }
        }
        neighbors
    }
    /// Return fields that share a vertex with the given field and have the same color as the given
    /// field. Pieces can move to fields that are vertex neighbors of the field they are on.
    pub fn get_field_vertex_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    pub fn move_piece(&mut self, from: &FieldCoord, to: &FieldCoord) {
        unimplemented!();
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        unimplemented!();
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        &self.board[(coord.x + 2) as usize][(coord.y + 2) as usize]
    }
    pub fn get_hex_neighbors(&self, coord: &HexCoord) -> Vec<HexCoord> {
        coord
            .get_neighbors()
            .iter()
            .filter_map(|&(_, c)| match *self.get_hex(&c) {
                Some(_) => Some(c),
                None => None,
            })
            .collect()
    }
    /// Return fields that share an edge with the given hex and are outside of the given hex. If a
    /// hex is removed from the board, pieces occupying that hex's field neighbors might be
    /// capturable.
    pub fn get_hex_field_neighbors(&self, coord: &HexCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![];

        for (i, neighbor) in coord.get_neighbors() {
            if self.get_hex(&neighbor).is_some() {
                let f = (i + 3) % 6;
                neighbors.push(neighbor.to_field(f));
            }
        }
        neighbors
    }
    /// A hex is removable (and must be removed) if it is empty and is "attached to the board by 3
    /// or less adjacent sides."
    pub fn is_hex_removable(&self, coord: &HexCoord) -> bool {
        unimplemented!();
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        unimplemented!();
    }
}

#[derive(Debug)]
pub struct FieldCoord {
    x: i32,
    y: i32,
    f: u32,
}

#[derive(Clone, Copy)]
pub struct HexCoord {
    x: i32,
    y: i32,
}

impl FieldCoord {
    pub fn new(x: i32, y: i32, f: u32) -> FieldCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2 && f < 6);
        FieldCoord { x, y, f }
    }
    pub fn to_hex(&self) -> HexCoord {
        HexCoord::new(self.x, self.y)
    }
}

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2);
        HexCoord { x, y }
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    // We return a Vec of tuples so that get_hex_field_neighbors and is_hex_removable know which
    // neighbors are on which side of the hex. They need to know this for different reasons:
    //   * get_hex_field_neighbors: the index of each neighboring field depends on which hex
    //                              neighbor that field neighbor is on
    //   * is_hex_removable: a hex is removable only if it is "attached to the board by 3 or less
    //                       adjacent sides"
    fn get_neighbors(&self) -> Vec<(u32, HexCoord)> {
        let mut neighbors = vec![];

        if self.y < 2 && (self.x + self.y) != 2 {
            neighbors.push((0, HexCoord::new(self.x, self.y + 1)));
        }
        if (self.x + self.y) != 2 && self.x < 2 {
            neighbors.push((1, HexCoord::new(self.x + 1, self.y)));
        }
        if self.x < 2 && self.y > -2 {
            neighbors.push((2, HexCoord::new(self.x + 1, self.y - 1)));
        }
        if self.y > -2 && (self.x + self.y) > -2 {
            neighbors.push((3, HexCoord::new(self.x, self.y - 1)));
        }
        if (self.x + self.y) > -2 && self.x > -2 {
            neighbors.push((4, HexCoord::new(self.x - 1, self.y)));
        }
        if self.x > -2 && self.y < 2 {
            neighbors.push((5, HexCoord::new(self.x - 1, self.y + 1)));
        }

        neighbors
    }
}
<commit_msg>Implement get_field_vertex_neighbors<commit_after>pub struct Model {
    pub board: Board,
    pub turn: Turn,
    pub white_pieces: u32,
    pub white_hexes: u32,
    pub black_pieces: u32,
    pub black_hexes: u32,
    pub selected_piece: Option<FieldCoord>,
}

impl Model {
    pub fn init() -> Model {
        Model {
            board: Board::new(),
            turn: Turn::White,
            white_pieces: 18,
            white_hexes: 0,
            black_pieces: 18,
            black_hexes: 0,
            selected_piece: None,
        }
    }
}

pub enum Turn {
    White,
    Black,
}

pub struct Board {
    // The hex board uses an axial coordinate system with (0, 0) at the center. The x-axis slopes
    // up to the right, and the y-axis goes up and down. The board is stored as a dense 2D array,
    // as a ragged array won't work (since each row would have to be a different type).
    board: [[Option<Hex>; 5]; 5],
}

// Fields are numbered clockwise from the top. Even indicies are black, odd indicies are white.
type Hex = [Field; 6];

// There's no need to store the color of the piece on this field, since only white pieces can be on
// white fields, and vice versa.
#[derive(Clone, Copy)]
pub enum Field {
    Piece,
    Empty,
}

impl Board {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    /// Create a new board with the "Laurentius" starting position.
    pub fn new() -> Board {
        let mut board = [[None; 5]; 5];

        // (0, 0) is the only empty hex
        board[2][2] = Some([Field::Empty; 6]);

        // Conveniently, each hex (except for (0, 0)) has exactly two pieces on it in the starting
        // position. The format here is (hex_x, hex_y, field1, field2).
        let piece_locations = [
            (-2,  2, 0, 4),
            (-2,  1, 0, 3),
            (-2,  0, 3, 5),
            (-1,  2, 1, 4),
            (-1,  1, 0, 4),
            (-1,  0, 3, 5),
            (-1, -1, 2, 5),
            ( 0,  2, 1, 5),
            ( 0,  1, 1, 5),
            ( 0, -1, 2, 4),
            ( 0, -2, 2, 4),
            ( 1,  1, 2, 5),
            ( 1,  0, 0, 2),
            ( 1, -1, 1, 3),
            ( 1, -2, 1, 4),
            ( 2,  0, 0, 2),
            ( 2, -1, 0, 3),
            ( 2, -2, 1, 3),
        ];

        for &(x, y, f1, f2) in &piece_locations {
            let mut hex = [Field::Empty; 6];
            hex[f1] = Field::Piece;
            hex[f2] = Field::Piece;
            board[(x + 2) as usize][(y + 2) as usize] = Some(hex);
        }

        Board { board }
    }

    pub fn get_field(&self, coord: &FieldCoord) -> &Field {
        match *self.get_hex(&coord.to_hex()) {
            Some(ref hex) => &hex[coord.f as usize],
            None => panic!("Tried to get field on removed hex: {:?}", coord),
        }
    }
    /// Return fields that share an edge with the given field. These fields are always the opposite
    /// color of the given field. If all of a piece's edge neighbors are occupied, that piece might
    /// be capturable.
    pub fn get_field_edge_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![
            // There are always two edge neighbors on the same hex as the given field
            FieldCoord {
                f: (coord.f + 1) % 6,
                ..*coord
            },
            FieldCoord {
                f: (coord.f + 5) % 6,
                ..*coord
            },
        ];

        for (i, neighbor) in coord.to_hex().get_neighbors() {
            if coord.f == i && self.get_hex(&neighbor).is_some() {
                let f = (i + 3) % 6;
                neighbors.push(neighbor.to_field(f));
                break;
            }
        }
        neighbors
    }
    /// Return fields that share a vertex with the given field and have the same color as the given
    /// field. Pieces can move to fields that are vertex neighbors of the field they are on.
    pub fn get_field_vertex_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        // A field's vertex neighbors can be defined as the edge neighbors of its edge neighbors
        let mut neighbors = vec![];
        for neighbor in self.get_field_edge_neighbors(coord) {
            neighbors.append(&mut self.get_field_edge_neighbors(&neighbor));
        }
        // A field is not its own neighbor
        neighbors.into_iter().filter(|n| n != coord).collect()
    }
    pub fn move_piece(&mut self, from: &FieldCoord, to: &FieldCoord) {
        unimplemented!();
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        unimplemented!();
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        &self.board[(coord.x + 2) as usize][(coord.y + 2) as usize]
    }
    pub fn get_hex_neighbors(&self, coord: &HexCoord) -> Vec<HexCoord> {
        coord
            .get_neighbors()
            .iter()
            .filter_map(|&(_, c)| match *self.get_hex(&c) {
                Some(_) => Some(c),
                None => None,
            })
            .collect()
    }
    /// Return fields that share an edge with the given hex and are outside of the given hex. If a
    /// hex is removed from the board, pieces occupying that hex's field neighbors might be
    /// capturable.
    pub fn get_hex_field_neighbors(&self, coord: &HexCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![];

        for (i, neighbor) in coord.get_neighbors() {
            if self.get_hex(&neighbor).is_some() {
                let f = (i + 3) % 6;
                neighbors.push(neighbor.to_field(f));
            }
        }
        neighbors
    }
    /// A hex is removable (and must be removed) if it is empty and is "attached to the board by 3
    /// or less adjacent sides."
    pub fn is_hex_removable(&self, coord: &HexCoord) -> bool {
        unimplemented!();
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        unimplemented!();
    }
}

#[derive(Debug, PartialEq)]
pub struct FieldCoord {
    x: i32,
    y: i32,
    f: u32,
}

#[derive(Clone, Copy)]
pub struct HexCoord {
    x: i32,
    y: i32,
}

impl FieldCoord {
    pub fn new(x: i32, y: i32, f: u32) -> FieldCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2 && f < 6);
        FieldCoord { x, y, f }
    }
    pub fn to_hex(&self) -> HexCoord {
        HexCoord::new(self.x, self.y)
    }
}

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2);
        HexCoord { x, y }
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    // We return a Vec of tuples so that get_hex_field_neighbors and is_hex_removable know which
    // neighbors are on which side of the hex. They need to know this for different reasons:
    //   * get_hex_field_neighbors: the index of each neighboring field depends on which hex
    //                              neighbor that field neighbor is on
    //   * is_hex_removable: a hex is removable only if it is "attached to the board by 3 or less
    //                       adjacent sides"
    fn get_neighbors(&self) -> Vec<(u32, HexCoord)> {
        let mut neighbors = vec![];

        if self.y < 2 && (self.x + self.y) != 2 {
            neighbors.push((0, HexCoord::new(self.x, self.y + 1)));
        }
        if (self.x + self.y) != 2 && self.x < 2 {
            neighbors.push((1, HexCoord::new(self.x + 1, self.y)));
        }
        if self.x < 2 && self.y > -2 {
            neighbors.push((2, HexCoord::new(self.x + 1, self.y - 1)));
        }
        if self.y > -2 && (self.x + self.y) > -2 {
            neighbors.push((3, HexCoord::new(self.x, self.y - 1)));
        }
        if (self.x + self.y) > -2 && self.x > -2 {
            neighbors.push((4, HexCoord::new(self.x - 1, self.y)));
        }
        if self.x > -2 && self.y < 2 {
            neighbors.push((5, HexCoord::new(self.x - 1, self.y + 1)));
        }

        neighbors
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use rand::Rng;

pub struct Continent {
    pub id: u8,
    pub diseases: DiceHolder,
}

pub struct DiceHolder {
    dice: Vec<Disease>,
}

// partialeq to compare variants
#[derive(PartialEq)]
pub enum Disease {
    Red,
    Yellow,
    Blue,
    Black,
}

pub struct GameModel {
    pub continents: Vec<Continent>,
    pub cdc: DiceHolder,
    pub treatment_center: DiceHolder,
    pub infection_bag: DiceHolder,
}

impl Continent {
    pub fn new(id: u8) -> Continent {
        Continent {
            id: id,
            diseases: DiceHolder::new(),
        }
    }
    // adds Disease d to the DiceHolder
    pub fn add(&mut self, d: Disease) {
        self.diseases.add(d);
    }
    pub fn disease_count(&self) -> [u8; 4] {
        self.diseases.total_count()
    }
}

impl DiceHolder {
    pub fn new() -> DiceHolder {
        DiceHolder { dice: Vec::new() }
    }
    // add a Disease to the holder
    pub fn add(&mut self, d: Disease) {
        self.dice.push(d);
    }
    // return number of given color
    pub fn count(&self, color: &str) -> u8 {
        let mut count = 0;
        match color {
            "red" | "Red" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Red => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            "yellow" | "Yellow" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Yellow => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            "blue" | "Blue" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Blue => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            "black" | "Black" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Black => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            _ => 0,
        }
    }
    // grab random die, remove and return it
    pub fn grab(&mut self) -> Option<Disease> {
        if self.size() <= 0 {
            None
        } else {
            // try randomly until we hit a color that exists
            loop {
                let color = match rand::thread_rng().gen_range(0, 4) {
                    0 => Disease::Red,
                    1 => Disease::Yellow,
                    2 => Disease::Blue,
                    3 => Disease::Black,
                    _ => panic!("Check disease.grab() something's fucked"),
                };
                match self.remove(color) {
                    Some(color) => return Some(color),
                    None => continue,
                }
            }
        }
    }
    // remove and return an Option with the Disease specified - TODO: make this less gross
    // i'm fighting the borrow checker, not working with it
    pub fn remove(&mut self, d: Disease) -> Option<Disease> {
        // grab first die that matches
        let mut found: bool = false;
        let mut index: usize = 0;
        for (i, elem) in self.dice.iter_mut().enumerate() {
            if elem == &d {
                // TODO: cont. i'd like to be able to just return the Option from here
                // but already have a mutable reference to iterate in the first place
                found = true;
                index = i;
                break;
            }
        }
        if found {
            Some(self.dice.remove(index))
        } else {
            None
        }
    }
    // size of holder
    pub fn size(&self) -> usize {
        self.dice.len()
    }
    // returns an array with the counts [red, yellow, blue, black]
    pub fn total_count(&self) -> [u8; 4] {
        [self.count("red"), self.count("yellow"), self.count("blue"), self.count("black")]
    }
}

impl Disease {
    // returns result of die roll - die weights from rule book
    // 0 signifies a CDC token
    pub fn roll(&self) -> u8 {
        let roll = rand::thread_rng().gen_range(0, 6);
        match self {
            &Disease::Red => {
                match roll {
                    0 => 0,
                    1 | 2 => 1,
                    3 => 4,
                    4 | 5 => 6,
                    _ => panic!("invalid random roll"),
                }
            }
            &Disease::Yellow => {
                match roll {
                    0 => 0,
                    1 | 2 => 2,
                    3 => 4,
                    4 | 5 => 5,
                    _ => panic!("invalid random roll"),
                }
            }
            &Disease::Blue => {
                match roll {
                    0 => 0,
                    1 => 1,
                    2 => 2,
                    3 => 3,
                    4 | 5 => 6,
                    _ => panic!("invalid random roll"),
                }
            }
            &Disease::Black => {
                match roll {
                    0 => 0,
                    1 | 2 | 3 => 3,
                    4 => 4,
                    5 => 5,
                    _ => panic!("invalid random roll"),
                }
            }
        }
    }
}

impl GameModel {
    pub fn new() -> GameModel {
        let mut ret = GameModel {
            continents: Vec::new(),
            cdc: DiceHolder::new(),
            treatment_center: DiceHolder::new(),
            infection_bag: DiceHolder::new(),
        };
        // 6 continents
        for i in 1..7 {
            ret.continents.push(Continent::new(i));
        }
        // 12 of each color in bag
        for _ in 0..12 {
            ret.infection_bag.add(Disease::Red);
            ret.infection_bag.add(Disease::Yellow);
            ret.infection_bag.add(Disease::Blue);
            ret.infection_bag.add(Disease::Black);
        }
        ret
    }
    pub fn initial_infect(&mut self) {
        let mut dice: Vec<Disease> = Vec::new();
        // grab 12 random
        for _ in 0..12 {
            dice.push(match self.infection_bag.grab() {
                Some(color) => color,
                None => panic!("grab failed, but its the beginning of the game!"),
            });
        }
        // roll and place
        for i in dice.iter() {
            let mut roll = 0;
            // roll until we don't get a zero
            while roll == 0 {
                roll = i.roll();
            }
            // TODO: we're fighting the borrow checker again here
            let result = match i {
                &Disease::Red => Disease::Red,
                &Disease::Yellow => Disease::Yellow,
                &Disease::Blue => Disease::Blue,
                &Disease::Black => Disease::Black,
            };
            self.continents[roll as usize - 1].add(result);
        }
    }
}<commit_msg>put impl with struct<commit_after>extern crate rand;
use rand::Rng;

pub struct Continent {
    pub id: u8,
    pub diseases: DiceHolder,
}

impl Continent {
    pub fn new(id: u8) -> Continent {
        Continent {
            id: id,
            diseases: DiceHolder::new(),
        }
    }
    // adds Disease d to the DiceHolder
    pub fn add(&mut self, d: Disease) {
        self.diseases.add(d);
    }
    pub fn disease_count(&self) -> [u8; 4] {
        self.diseases.total_count()
    }
}

pub struct DiceHolder {
    dice: Vec<Disease>,
}

impl DiceHolder {
    pub fn new() -> DiceHolder {
        DiceHolder { dice: Vec::new() }
    }
    // add a Disease to the holder
    pub fn add(&mut self, d: Disease) {
        self.dice.push(d);
    }
    // return number of given color
    pub fn count(&self, color: &str) -> u8 {
        let mut count = 0;
        match color {
            "red" | "Red" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Red => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            "yellow" | "Yellow" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Yellow => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            "blue" | "Blue" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Blue => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            "black" | "Black" => {
                for i in self.dice.iter() {
                    match i {
                        &Disease::Black => count += 1,
                        _ => continue,
                    }
                }
                count
            }
            _ => 0,
        }
    }
    // grab random die, remove and return it
    pub fn grab(&mut self) -> Option<Disease> {
        if self.size() <= 0 {
            None
        } else {
            // try randomly until we hit a color that exists
            loop {
                let color = match rand::thread_rng().gen_range(0, 4) {
                    0 => Disease::Red,
                    1 => Disease::Yellow,
                    2 => Disease::Blue,
                    3 => Disease::Black,
                    _ => panic!("Check disease.grab() something's fucked"),
                };
                match self.remove(color) {
                    Some(color) => return Some(color),
                    None => continue,
                }
            }
        }
    }
    // remove and return an Option with the Disease specified - TODO: make this less gross
    // i'm fighting the borrow checker, not working with it
    pub fn remove(&mut self, d: Disease) -> Option<Disease> {
        // grab first die that matches
        let mut found: bool = false;
        let mut index: usize = 0;
        for (i, elem) in self.dice.iter_mut().enumerate() {
            if elem == &d {
                // TODO: cont. i'd like to be able to just return the Option from here
                // but already have a mutable reference to iterate in the first place
                found = true;
                index = i;
                break;
            }
        }
        if found {
            Some(self.dice.remove(index))
        } else {
            None
        }
    }
    // size of holder
    pub fn size(&self) -> usize {
        self.dice.len()
    }
    // returns an array with the counts [red, yellow, blue, black]
    pub fn total_count(&self) -> [u8; 4] {
        [self.count("red"), self.count("yellow"), self.count("blue"), self.count("black")]
    }
}

// partialeq to compare variants
#[derive(PartialEq)]
pub enum Disease {
    Red,
    Yellow,
    Blue,
    Black,
}

impl Disease {
    // returns result of die roll - die weights from rule book
    // 0 signifies a CDC token
    pub fn roll(&self) -> u8 {
        let roll = rand::thread_rng().gen_range(0, 6);
        match self {
            &Disease::Red => {
                match roll {
                    0 => 0,
                    1 | 2 => 1,
                    3 => 4,
                    4 | 5 => 6,
                    _ => panic!("invalid random roll"),
                }
            }
            &Disease::Yellow => {
                match roll {
                    0 => 0,
                    1 | 2 => 2,
                    3 => 4,
                    4 | 5 => 5,
                    _ => panic!("invalid random roll"),
                }
            }
            &Disease::Blue => {
                match roll {
                    0 => 0,
                    1 => 1,
                    2 => 2,
                    3 => 3,
                    4 | 5 => 6,
                    _ => panic!("invalid random roll"),
                }
            }
            &Disease::Black => {
                match roll {
                    0 => 0,
                    1 | 2 | 3 => 3,
                    4 => 4,
                    5 => 5,
                    _ => panic!("invalid random roll"),
                }
            }
        }
    }
}

pub struct GameModel {
    pub continents: Vec<Continent>,
    pub cdc: DiceHolder,
    pub treatment_center: DiceHolder,
    pub infection_bag: DiceHolder,
}

impl GameModel {
    pub fn new() -> GameModel {
        let mut ret = GameModel {
            continents: Vec::new(),
            cdc: DiceHolder::new(),
            treatment_center: DiceHolder::new(),
            infection_bag: DiceHolder::new(),
        };
        // 6 continents
        for i in 1..7 {
            ret.continents.push(Continent::new(i));
        }
        // 12 of each color in bag
        for _ in 0..12 {
            ret.infection_bag.add(Disease::Red);
            ret.infection_bag.add(Disease::Yellow);
            ret.infection_bag.add(Disease::Blue);
            ret.infection_bag.add(Disease::Black);
        }
        ret
    }
    pub fn initial_infect(&mut self) {
        let mut dice: Vec<Disease> = Vec::new();
        // grab 12 random
        for _ in 0..12 {
            dice.push(match self.infection_bag.grab() {
                Some(color) => color,
                None => panic!("grab failed, but its the beginning of the game!"),
            });
        }
        // roll and place
        for i in dice.iter() {
            let mut roll = 0;
            // roll until we don't get a zero
            while roll == 0 {
                roll = i.roll();
            }
            // TODO: we're fighting the borrow checker again here
            let result = match i {
                &Disease::Red => Disease::Red,
                &Disease::Yellow => Disease::Yellow,
                &Disease::Blue => Disease::Blue,
                &Disease::Black => Disease::Black,
            };
            self.continents[roll as usize - 1].add(result);
        }
    }
}<|endoftext|>


<commit_before>use std::sync::Arc;
use error::Error;

use super::{Request, Response, IronResult, status};

/// `Handler`s are responsible for handling requests by creating Responses from Requests.
///
/// By default, bare functions and variants of Chain implement `Handler`.
///
/// `Handler`s are allowed to return errors, and if they do, their `catch` method is called and the
/// error is propagated to `AfterMiddleware`.
pub trait Handler: Send + Sync {
    /// Produce a `Response` from a Request, with the possibility of error.
    ///
    /// If this returns an Err, `catch` is called with the error.
    fn call(&self, &mut Request) -> IronResult<Response>;

    /// If `Handler`'s call method produces an Err, then this method is called
    /// to produce a `Response` and possibly handle the error.
    ///
    /// If the passed-in error is not handled, it should be returned as the second
    /// item in the returned tuple. If it is handled, then `Ok(())` can be returned
    /// instead to indicate that all is good with the Response.
    fn catch(&self, &mut Request, Box<Error>) -> (Response, IronResult<()>);
}

/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Chain.
///
/// `BeforeMiddleware` are responsible for doing request pre-processing that requires
/// the ability to change control-flow, such as authorization middleware, or for editing
/// the request by modifying the headers.
///
/// `BeforeMiddleware` only have access to the Request, if you need to modify or read a Response,
/// you will need `AfterMiddleware`.
pub trait BeforeMiddleware: Send + Sync {
    /// Do whatever work this middleware should do with a `Request` object.
    ///
    /// An error here is propagated by the containing Chain to, first, this Middleware's
    /// `catch` method, then every subsequent `BeforeMiddleware`'s `catch` methods until one returns
    /// Ok(()) or the Chain's `Handler` is reached, at which point the `Handler`'s `catch` method is
    /// called to produce an error Response.
    fn before(&self, &mut Request) -> IronResult<()>;

    /// Try to `catch` an error thrown by this Middleware or a previous `BeforeMiddleware`.
    ///
    /// Should only return Ok(()) if the error has been completely handled and a Chain
    /// can proceed as normal.
    fn catch(&self, _: &mut Request, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

/// `AfterMiddleware` are fired after a `Handler` is called inside of a Chain.
///
/// `AfterMiddleware` receive both a `Request` and a `Response` and are responsible for doing
/// any response-post-processing.
///
/// `AfterMiddleware` should *not* usually overwrite the contents of a Response. In
/// the common case, a complete response is generated by the Chain's `Handler` and
/// `AfterMiddleware` simply do post-processing of that Response, such as
/// adding headers or logging.
pub trait AfterMiddleware: Send + Sync {
    /// Do whatever work this middleware needs to do with both a `Request` and `Response` objects.
    ///
    /// An error here is propagated by the containing Chain down to this and any later
    /// `AfterMiddleware`'s `catch` methods, which can attempt to handle the error or modify
    /// the `Response` to indicate to a client that something went wrong.
    fn after(&self, &mut Request, &mut Response) -> IronResult<()>;

    /// Try to catch an error thrown by previous `AfterMiddleware`, the `Handler`, or a previous
    /// `BeforeMiddleware`.
    ///
    /// The response was generated by the `catch` function of `Handler`s and is abnormal or
    /// errored in some way.
    fn catch(&self, _: &mut Request, _: &mut Response, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

/// AroundMiddleware are used to wrap and replace the `Handler` in a Chain.
///
/// AroundMiddleware must themselves be `Handler`s, and can integrate an existing
/// `Handler` through the around method, which is called once on insertion
/// into a Chain.
pub trait AroundMiddleware: Handler {
    /// Incorporate another `Handler` into this AroundMiddleware.
    ///
    /// Usually this means wrapping the handler and editing the `Request` on the
    /// way in and the `Response` on the way out.
    fn around(&mut self, handler: Box<Handler + Send + Sync>);
}

/// Chain's hold `BeforeMiddleware`, a `Handler`, and `AfterMiddleware` and are responsible
/// for correctly dispatching a `Request` through them.
///
/// Chain's are handlers, and most of their work is done in the call method of their
/// `Handler` implementation.
pub trait Chain: Handler {
    /// Create a new Chain from a `Handler`.
    fn new<H: Handler>(H) -> Self;

    /// Link both a before and after middleware to the chain at once.
    ///
    /// Middleware that have a Before and After piece should have a constructor
    /// which returns both as a tuple, so it can be passed directly to link.
    fn link<B, A>(&mut self, (B, A)) where A: AfterMiddleware, B: BeforeMiddleware;

    /// Link a `BeforeMiddleware` to the Chain.
    fn link_before<B>(&mut self, B) where B: BeforeMiddleware;

    /// Link a `AfterMiddleware` to the Chain.
    fn link_after<A>(&mut self, A) where A: AfterMiddleware;

    /// Wrap the Chain's `Handler` using an AroundMiddleware.
    fn around<A>(&mut self, A) where A: AroundMiddleware;
}

/// The default Chain used in Iron.
///
/// For almost all intents and purposes, this is synonymous with the
/// Chain trait and is the canonical implementation. However, Chain
/// is left as a trait for future interoperability with other
/// frameworks.
pub struct ChainBuilder {
    befores: Vec<Box<BeforeMiddleware + Send + Sync>>,
    afters: Vec<Box<AfterMiddleware + Send + Sync>>,
    handler: Box<Handler + Send + Sync>
}

impl ChainBuilder {
    /// Construct a new ChainBuilder from a `Handler`.
    pub fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }
}

impl Chain for ChainBuilder {
    fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }

    fn link<B, A>(&mut self, link: (B, A))
    where A: AfterMiddleware, B: BeforeMiddleware {
        let (before, after) = link;
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn link_before<B>(&mut self, before: B) where B: BeforeMiddleware {
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
    }

    fn link_after<A>(&mut self, after: A) where A: AfterMiddleware {
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn around<A>(&mut self, mut around: A) where A: AroundMiddleware {
        use std::mem;

        let old = mem::replace(&mut self.handler, box Nop as Box<Handler + Send + Sync>);
        around.around(old);
        self.handler = box around as Box<Handler + Send + Sync>;
    }
}

impl Handler for ChainBuilder {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), None);

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        helpers::run_afters(req, res, err, self.afters.as_slice())
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), Some(err));

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        match helpers::run_afters(req, res, err, self.afters.as_slice()) {
            Ok(res) => (res, Ok(())),
            Err(err) => (Response::status(status::InternalServerError), Err(err))
        }
    }
}

impl Handler for fn(&mut Request) -> IronResult<Response> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        (*self)(req)
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

pub struct Nop;

impl Handler for Nop {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

impl Handler for Box<Handler + Send + Sync> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl Handler for Arc<Box<Handler + Send + Sync>> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

mod helpers {
    use super::super::{Request, Response, IronResult};
    use super::{AfterMiddleware, BeforeMiddleware, Handler};
    use error::Error;

    pub fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error>>) -> IronResult<()> {
        match err {
            Some(mut e) => {
                for (i, before) in befores.iter().enumerate() {
                    match before.catch(req, e) {
                        Ok(_) => return run_befores(req, befores, None),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, before) in befores.iter().enumerate() {
                    match before.before(req) {
                        Ok(_) => (),
                        Err(err) => return run_befores(req, befores.slice_from(i), Some(err))
                    }
                }
                Ok(())
            }
        }
    }

    pub fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error>>,
                  afters: &[Box<AfterMiddleware>]) -> IronResult<Response> {
        match err {
            Some(mut e) => {
                for (i, after) in afters.iter().enumerate() {
                    match after.catch(req, &mut res, e) {
                        Ok(_) => return run_afters(req, res, None, afters),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, after) in afters.iter().enumerate() {
                    match after.after(req, &mut res) {
                        Ok(_) => (),
                        Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i))
                    }
                }
                Ok(res)
            }
        }
    }

    pub fn run_handler_catch(req: &mut Request, err: Box<Error>,
                         handler: &Box<Handler>) -> (Response, Option<Box<Error>>) {
        match handler.catch(req, err) {
            (res, Ok(())) => (res, None),
            (res, Err(e)) => (res, Some(e))
        }
    }
}

<commit_msg>(doc) Small doc fixes in middleware.<commit_after>use std::sync::Arc;
use error::Error;

use super::{Request, Response, IronResult, status};

/// `Handler`s are responsible for handling requests by creating Responses from Requests.
///
/// By default, bare functions and variants of Chain implement `Handler`.
///
/// `Handler`s are allowed to return errors, and if they do, their `catch` method is called and the
/// error is propagated to `AfterMiddleware`.
pub trait Handler: Send + Sync {
    /// Produce a `Response` from a Request, with the possibility of error.
    ///
    /// If this returns an Err, `catch` is called with the error.
    fn call(&self, &mut Request) -> IronResult<Response>;

    /// If `Handler`'s call method produces an Err, then this method is called
    /// to produce a `Response` and possibly handle the error.
    ///
    /// If the passed-in error is not handled, it should be returned as the second
    /// item in the returned tuple. If it is handled, then `Ok(())` can be returned
    /// instead to indicate that all is good with the Response and the error has
    /// been dealt with.
    fn catch(&self, &mut Request, Box<Error>) -> (Response, IronResult<()>);
}

/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Chain.
///
/// `BeforeMiddleware` are responsible for doing request pre-processing that requires
/// the ability to change control-flow, such as authorization middleware, or for editing
/// the request by modifying the headers.
///
/// `BeforeMiddleware` only have access to the Request, if you need to modify or read a Response,
/// you will need `AfterMiddleware`.
pub trait BeforeMiddleware: Send + Sync {
    /// Do whatever work this middleware should do with a `Request` object.
    ///
    /// An error here is propagated by the containing Chain to, first, this Middleware's
    /// `catch` method, then every subsequent `BeforeMiddleware`'s `catch` methods until one returns
    /// Ok(()) or the Chain's `Handler` is reached, at which point the `Handler`'s `catch` method is
    /// called to produce an error Response.
    fn before(&self, &mut Request) -> IronResult<()>;

    /// Try to `catch` an error thrown by this Middleware or a previous `BeforeMiddleware`.
    ///
    /// Should only return Ok(()) if the error has been completely handled and a Chain
    /// can proceed as normal.
    fn catch(&self, _: &mut Request, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

/// `AfterMiddleware` are fired after a `Handler` is called inside of a Chain.
///
/// `AfterMiddleware` receive both a `Request` and a `Response` and are responsible for doing
/// any response post-processing.
///
/// `AfterMiddleware` should *not* usually overwrite the contents of a Response. In
/// the common case, a complete response is generated by the Chain's `Handler` and
/// `AfterMiddleware` simply do post-processing of that Response, such as
/// adding headers or logging.
pub trait AfterMiddleware: Send + Sync {
    /// Do whatever work this middleware needs to do with both a `Request` and `Response` objects.
    ///
    /// An error here is propagated by the containing Chain down to this and any later
    /// `AfterMiddleware`'s `catch` methods, which can attempt to handle the error or modify
    /// the `Response` to indicate to a client that something went wrong.
    fn after(&self, &mut Request, &mut Response) -> IronResult<()>;

    /// Try to catch an error thrown by previous `AfterMiddleware`, the `Handler`, or a previous
    /// `BeforeMiddleware`.
    ///
    /// This indicates that the `Response` is abnormal in some way, either because it was
    /// generated by a `Handler`s `catch` method or because a previous `AfterMiddleware`
    /// errored.
    fn catch(&self, _: &mut Request, _: &mut Response, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

/// AroundMiddleware are used to wrap and replace the `Handler` in a Chain.
///
/// AroundMiddleware must themselves be `Handler`s, and can integrate an existing
/// `Handler` through the around method, which is called once on insertion
/// into a Chain.
pub trait AroundMiddleware: Handler {
    /// Incorporate another `Handler` into this AroundMiddleware.
    ///
    /// Usually this means wrapping the handler and editing the `Request` on the
    /// way in and the `Response` on the way out.
    fn around(&mut self, handler: Box<Handler + Send + Sync>);
}

/// Chain's hold `BeforeMiddleware`, a `Handler`, and `AfterMiddleware` and are responsible
/// for correctly dispatching a `Request` through them.
///
/// Chain's are handlers, and most of their work is done in the call method of their
/// `Handler` implementation.
pub trait Chain: Handler {
    /// Create a new Chain from a `Handler`.
    fn new<H: Handler>(H) -> Self;

    /// Link both a before and after middleware to the chain at once.
    ///
    /// Middleware that have a Before and After piece should have a constructor
    /// which returns both as a tuple, so it can be passed directly to link.
    fn link<B, A>(&mut self, (B, A)) where A: AfterMiddleware, B: BeforeMiddleware;

    /// Link a `BeforeMiddleware` to the Chain.
    fn link_before<B>(&mut self, B) where B: BeforeMiddleware;

    /// Link a `AfterMiddleware` to the Chain.
    fn link_after<A>(&mut self, A) where A: AfterMiddleware;

    /// Wrap the Chain's `Handler` using an AroundMiddleware.
    fn around<A>(&mut self, A) where A: AroundMiddleware;
}

/// The default Chain used in Iron.
///
/// For almost all intents and purposes, this is synonymous with the
/// Chain trait and is the canonical implementation. Chain
/// is left as a trait for future interoperability with other
/// frameworks.
pub struct ChainBuilder {
    befores: Vec<Box<BeforeMiddleware + Send + Sync>>,
    afters: Vec<Box<AfterMiddleware + Send + Sync>>,
    handler: Box<Handler + Send + Sync>
}

impl ChainBuilder {
    /// Construct a new ChainBuilder from a `Handler`.
    pub fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }
}

impl Chain for ChainBuilder {
    fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }

    fn link<B, A>(&mut self, link: (B, A))
    where A: AfterMiddleware, B: BeforeMiddleware {
        let (before, after) = link;
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn link_before<B>(&mut self, before: B) where B: BeforeMiddleware {
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
    }

    fn link_after<A>(&mut self, after: A) where A: AfterMiddleware {
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn around<A>(&mut self, mut around: A) where A: AroundMiddleware {
        use std::mem;

        let old = mem::replace(&mut self.handler, box Nop as Box<Handler + Send + Sync>);
        around.around(old);
        self.handler = box around as Box<Handler + Send + Sync>;
    }
}

impl Handler for ChainBuilder {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), None);

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        helpers::run_afters(req, res, err, self.afters.as_slice())
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), Some(err));

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        match helpers::run_afters(req, res, err, self.afters.as_slice()) {
            Ok(res) => (res, Ok(())),
            Err(err) => (Response::status(status::InternalServerError), Err(err))
        }
    }
}

impl Handler for fn(&mut Request) -> IronResult<Response> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        (*self)(req)
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

pub struct Nop;

impl Handler for Nop {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

impl Handler for Box<Handler + Send + Sync> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl Handler for Arc<Box<Handler + Send + Sync>> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

mod helpers {
    use super::super::{Request, Response, IronResult};
    use super::{AfterMiddleware, BeforeMiddleware, Handler};
    use error::Error;

    pub fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error>>) -> IronResult<()> {
        match err {
            Some(mut e) => {
                for (i, before) in befores.iter().enumerate() {
                    match before.catch(req, e) {
                        Ok(_) => return run_befores(req, befores, None),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, before) in befores.iter().enumerate() {
                    match before.before(req) {
                        Ok(_) => (),
                        Err(err) => return run_befores(req, befores.slice_from(i), Some(err))
                    }
                }
                Ok(())
            }
        }
    }

    pub fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error>>,
                  afters: &[Box<AfterMiddleware>]) -> IronResult<Response> {
        match err {
            Some(mut e) => {
                for (i, after) in afters.iter().enumerate() {
                    match after.catch(req, &mut res, e) {
                        Ok(_) => return run_afters(req, res, None, afters),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, after) in afters.iter().enumerate() {
                    match after.after(req, &mut res) {
                        Ok(_) => (),
                        Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i))
                    }
                }
                Ok(res)
            }
        }
    }

    pub fn run_handler_catch(req: &mut Request, err: Box<Error>,
                         handler: &Box<Handler>) -> (Response, Option<Box<Error>>) {
        match handler.catch(req, err) {
            (res, Ok(())) => (res, None),
            (res, Err(e)) => (res, Some(e))
        }
    }
}

<|endoftext|>


<commit_before>extern crate piston_window;
extern crate image as im;
extern crate vecmath;

use im::GenericImage;
use piston_window::*;
use vecmath::*;

fn main() {
    let opengl = OpenGL::V3_2;
    let (width, height) = (300, 300);
    let window: PistonWindow =
        WindowSettings::new("piston: paint", (width, height))
        .exit_on_esc(true)
        .opengl(opengl)
        .build()
        .unwrap();

    let mut canvas = im::ImageBuffer::new(width, height);
    let mut draw = false;
    let mut texture = Texture::from_image(
            &mut *window.factory.borrow_mut(),
            &canvas,
            &TextureSettings::new()
        ).unwrap();

    let mut last_pos = None;

    for e in window {
        e.draw_2d(|c, g| {
            clear([1.0; 4], g);
            image(&texture, c.transform, g);
        });
        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = true;
                last_pos = e.mouse_cursor_args()
            }
        };
        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = false;
                last_pos = None
            }
        };
        if draw {
            if let Some(pos) = e.mouse_cursor_args() {
                let (x, y) = (pos[0] as f32, pos[1] as f32);

                match last_pos {
                    Some(p) => {
                        let (last_x, last_y) = (p[0] as f32, p[1] as f32);
                        let distance = vec2_len(vec2_sub(p, pos)) as u32;

                        for i in 0..distance {
                            let diff_x = (x - last_x) as f32;
                            let diff_y = (y - last_y) as f32;
                            let delta = i as f32 / distance as f32;
                            let new_x = (last_x + (diff_x * delta)) as u32;
                            let new_y = (last_y + (diff_y * delta)) as u32;
                            if new_x < width && new_y < height {
                                canvas.put_pixel(new_x, new_y, im::Rgba([0, 0, 0, 255]));
                                texture.update(&mut*e.factory.borrow_mut(), &canvas).unwrap();
                            };
                        };
                    },
                    None => {}
                };

                last_pos = Some(pos)
            };

        }
    }
}

<commit_msg>remove redundant casts<commit_after>extern crate piston_window;
extern crate image as im;
extern crate vecmath;

use im::GenericImage;
use piston_window::*;
use vecmath::*;

fn main() {
    let opengl = OpenGL::V3_2;
    let (width, height) = (300, 300);
    let window: PistonWindow =
        WindowSettings::new("piston: paint", (width, height))
        .exit_on_esc(true)
        .opengl(opengl)
        .build()
        .unwrap();

    let mut canvas = im::ImageBuffer::new(width, height);
    let mut draw = false;
    let mut texture = Texture::from_image(
            &mut *window.factory.borrow_mut(),
            &canvas,
            &TextureSettings::new()
        ).unwrap();

    let mut last_pos = None;

    for e in window {
        e.draw_2d(|c, g| {
            clear([1.0; 4], g);
            image(&texture, c.transform, g);
        });
        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = true;
                last_pos = e.mouse_cursor_args()
            }
        };
        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = false;
                last_pos = None
            }
        };
        if draw {
            if let Some(pos) = e.mouse_cursor_args() {
                let (x, y) = (pos[0] as f32, pos[1] as f32);

                match last_pos {
                    Some(p) => {
                        let (last_x, last_y) = (p[0] as f32, p[1] as f32);
                        let distance = vec2_len(vec2_sub(p, pos)) as u32;

                        for i in 0..distance {
                            let diff_x = x - last_x;
                            let diff_y = y - last_y;
                            let delta = i as f32 / distance as f32;
                            let new_x = (last_x + (diff_x * delta)) as u32;
                            let new_y = (last_y + (diff_y * delta)) as u32;
                            if new_x < width && new_y < height {
                                canvas.put_pixel(new_x, new_y, im::Rgba([0, 0, 0, 255]));
                                texture.update(&mut*e.factory.borrow_mut(), &canvas).unwrap();
                            };
                        };
                    },
                    None => {}
                };

                last_pos = Some(pos)
            };

        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2016-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

const DEFAULT_BRIGHTNESS: u8 = 7;

/// A pixel on an LED strip or board.
#[derive(Debug, Copy, Clone)]
pub struct Pixel {
    value: [u8; 4], // Brightness, blue, green, red
}

impl Pixel {
    pub fn set_rgb(&mut self, red: u8, green: u8, blue: u8) {
        self.value[1] = blue;
        self.value[2] = green;
        self.value[3] = red;
    }

    pub fn set_brightness(&mut self, brightness: f32) {
        self.value[0] = 0b1110_0000 | ((31.0 * brightness.max(0.0).min(1.0)) as u8);
    }

    pub fn set_rgbb(&mut self, red: u8, green: u8, blue: u8, brightness: f32) {
        self.set_rgb(red, green, blue);
        self.set_brightness(brightness);
    }

    pub(crate) fn bytes(&self) -> &[u8] {
        &self.value
    }
}

impl Default for Pixel {
    fn default() -> Pixel {
        Pixel {
            value: [0b1110_0000 | DEFAULT_BRIGHTNESS, 0, 0, 0],
        }
    }
}
<commit_msg>Add Pixel convenience methods<commit_after>// Copyright (c) 2016-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

const DEFAULT_BRIGHTNESS: u8 = 7;

const IDX_BRIGHTNESS: usize = 0;
const IDX_BLUE: usize = 1;
const IDX_GREEN: usize = 2;
const IDX_RED: usize = 3;

/// A pixel on an LED strip or board.
#[derive(Debug, Copy, Clone)]
pub struct Pixel {
    value: [u8; 4], // Brightness, blue, green, red
}

impl Pixel {
    /// Returns a tuple containing the values for red, green and blue.
    #[inline]
    pub fn rgb(&self) -> (u8, u8, u8) {
        (
            self.value[IDX_RED],
            self.value[IDX_GREEN],
            self.value[IDX_BLUE],
        )
    }

    /// Sets the values for red, green and blue.
    ///
    /// `red`, `green` and `blue` are specified as a `u8` between `0` (0%) and `255` (100%).
    #[inline]
    pub fn set_rgb(&mut self, red: u8, green: u8, blue: u8) {
        self.value[IDX_BLUE] = blue;
        self.value[IDX_GREEN] = green;
        self.value[IDX_RED] = red;
    }

    /// Returns a tuple containing the values for red, green, blue and brightness.
    #[inline]
    pub fn rgbb(&self) -> (u8, u8, u8, f32) {
        (
            self.value[IDX_RED],
            self.value[IDX_GREEN],
            self.value[IDX_BLUE],
            f32::from(0b0001_1111 & self.value[IDX_BRIGHTNESS]) / 31.0,
        )
    }

    /// Sets the values for red, green, blue and brightness.
    ///
    /// `red`, `green` and `blue` are specified as a `u8` between `0` (0%) and `255` (100%).
    /// `brightness` is specified as an `f32` between `0.0` (0%) and `1.0` (100%), and is converted to a 5-bit value.
    #[inline]
    pub fn set_rgbb(&mut self, red: u8, green: u8, blue: u8, brightness: f32) {
        self.set_rgb(red, green, blue);
        self.set_brightness(brightness);
    }

    /// Returns the red value.
    #[inline]
    pub fn red(&self) -> u8 {
        self.value[IDX_RED]
    }

    /// Sets the red value.
    ///
    /// `red` is specified as a `u8` between `0` (0%) and `255` (100%).
    #[inline]
    pub fn set_red(&mut self, red: u8) {
        self.value[IDX_RED] = red;
    }

    /// Returns the green value.
    #[inline]
    pub fn green(&self) -> u8 {
        self.value[IDX_GREEN]
    }

    /// Sets the green value.
    ///
    /// `green` is specified as a `u8` between `0` (0%) and `255` (100%).
    #[inline]
    pub fn set_green(&mut self, green: u8) {
        self.value[IDX_GREEN] = green;
    }

    /// Returns the blue value.
    #[inline]
    pub fn blue(&self) -> u8 {
        self.value[IDX_BLUE]
    }

    /// Sets the blue value.
    ///
    /// `blue` is specified as a `u8` between `0` (0%) and `255` (100%).
    #[inline]
    pub fn set_blue(&mut self, blue: u8) {
        self.value[IDX_BLUE] = blue;
    }

    /// Returns the brightness value.
    #[inline]
    pub fn brightness(&self) -> f32 {
        f32::from(0b0001_1111 & self.value[IDX_BRIGHTNESS]) / 31.0
    }

    /// Sets the brightness value.
    ///
    /// `brightness` is specified as an `f32` between `0.0` (0%) and `1.0` (100%), and is converted to a 5-bit value.
    #[inline]
    pub fn set_brightness(&mut self, brightness: f32) {
        self.value[IDX_BRIGHTNESS] = 0b1110_0000 | ((31.0 * brightness.max(0.0).min(1.0)) as u8);
    }

    /// Sets the red, green and blue values to `0`.
    #[inline]
    pub fn clear(&mut self) {
        self.set_rgb(0, 0, 0);
    }

    #[inline]
    pub(crate) fn bytes(&self) -> &[u8] {
        &self.value
    }
}

impl Default for Pixel {
    fn default() -> Pixel {
        Pixel {
            value: [0b1110_0000 | DEFAULT_BRIGHTNESS, 0, 0, 0],
        }
    }
}
<|endoftext|>


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

use std::fmt;
use std::num::Zero;

use approx::ApproxEq;
use intersect::Intersect;
use num::BaseFloat;
use point::{Point, Point3};
use ray::Ray3;
use vector::{Vector3, Vector4};
use vector::{Vector, EuclideanVector};

/// A 3-dimensional plane formed from the equation: `A*x + B*y + C*z - D = 0`.
///
/// # Fields
///
/// - `n`: a unit vector representing the normal of the plane where:
///   - `n.x`: corresponds to `A` in the plane equation
///   - `n.y`: corresponds to `B` in the plane equation
///   - `n.z`: corresponds to `C` in the plane equation
/// - `d`: the distance value, corresponding to `D` in the plane equation
///
/// # Notes
///
/// The `A*x + B*y + C*z - D = 0` form is preferred over the other common
/// alternative, `A*x + B*y + C*z + D = 0`, because it tends to avoid
/// superfluous negations (see _Real Time Collision Detection_, p. 55).
#[deriving(Clone, PartialEq, Encodable, Decodable)]
pub struct Plane<S> {
    pub n: Vector3<S>,
    pub d: S,
}

impl<S: BaseFloat> Plane<S> {
    /// Construct a plane from a normal vector and a scalar distance. The
    /// plane will be perpendicular to `n`, and `d` units offset from the
    /// origin.
    pub fn new(n: Vector3<S>, d: S) -> Plane<S> {
        Plane { n: n, d: d }
    }

    /// # Arguments
    ///
    /// - `a`: the `x` component of the normal
    /// - `b`: the `y` component of the normal
    /// - `c`: the `z` component of the normal
    /// - `d`: the plane's distance value
    pub fn from_abcd(a: S, b: S, c: S, d: S) -> Plane<S> {
        Plane { n: Vector3::new(a, b, c), d: d }
    }

    /// Construct a plane from the components of a four-dimensional vector
    pub fn from_vector4(v: Vector4<S>) -> Plane<S> {
        match v {
            Vector4 { x, y, z, w } => Plane { n: Vector3::new(x, y, z), d: w },
        }
    }

    /// Constructs a plane that passes through the the three points `a`, `b` and `c`
    pub fn from_points(a: Point3<S>, b: Point3<S>, c: Point3<S>) -> Option<Plane<S>> {
        // create two vectors that run parallel to the plane
        let v0 = b.sub_p(&a);
        let v1 = c.sub_p(&a);

        // find the normal vector that is perpendicular to v1 and v2
        let mut n = v0.cross(&v1);

        if n.approx_eq(&Vector3::zero()) { None }
        else {
            // compute the normal and the distance to the plane
            n.normalize_self();
            let d = -a.dot(&n);

            Some(Plane::new(n, d))
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Ray3<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        match *self {
            (ref p, ref r) => {
                let t = -(p.d + r.origin.dot(&p.n)) / r.direction.dot(&p.n);
                if t < Zero::zero() { None }
                else { Some(r.origin.add_v(&r.direction.mul_s(t))) }
            }
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Ray3<S>>> for (Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Ray3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat + ApproxEq<S>>
ApproxEq<S> for Plane<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Plane<S>, epsilon: &S) -> bool {
        self.n.approx_eq_eps(&other.n, epsilon) &&
        self.d.approx_eq_eps(&other.d, epsilon)
    }
}

impl<S: BaseFloat> fmt::Show for Plane<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:f}x + {:f}y + {:f}z - {:f} = 0",
               self.n.x, self.n.y, self.n.z, self.d)
    }
}
<commit_msg>Added 'from_point_normal'<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt;
use std::num::Zero;

use approx::ApproxEq;
use intersect::Intersect;
use num::BaseFloat;
use point::{Point, Point3};
use ray::Ray3;
use vector::{Vector3, Vector4};
use vector::{Vector, EuclideanVector};

/// A 3-dimensional plane formed from the equation: `A*x + B*y + C*z - D = 0`.
///
/// # Fields
///
/// - `n`: a unit vector representing the normal of the plane where:
///   - `n.x`: corresponds to `A` in the plane equation
///   - `n.y`: corresponds to `B` in the plane equation
///   - `n.z`: corresponds to `C` in the plane equation
/// - `d`: the distance value, corresponding to `D` in the plane equation
///
/// # Notes
///
/// The `A*x + B*y + C*z - D = 0` form is preferred over the other common
/// alternative, `A*x + B*y + C*z + D = 0`, because it tends to avoid
/// superfluous negations (see _Real Time Collision Detection_, p. 55).
#[deriving(Clone, PartialEq, Encodable, Decodable)]
pub struct Plane<S> {
    pub n: Vector3<S>,
    pub d: S,
}

impl<S: BaseFloat> Plane<S> {
    /// Construct a plane from a normal vector and a scalar distance. The
    /// plane will be perpendicular to `n`, and `d` units offset from the
    /// origin.
    pub fn new(n: Vector3<S>, d: S) -> Plane<S> {
        Plane { n: n, d: d }
    }

    /// # Arguments
    ///
    /// - `a`: the `x` component of the normal
    /// - `b`: the `y` component of the normal
    /// - `c`: the `z` component of the normal
    /// - `d`: the plane's distance value
    pub fn from_abcd(a: S, b: S, c: S, d: S) -> Plane<S> {
        Plane { n: Vector3::new(a, b, c), d: d }
    }

    /// Construct a plane from the components of a four-dimensional vector
    pub fn from_vector4(v: Vector4<S>) -> Plane<S> {
        match v {
            Vector4 { x, y, z, w } => Plane { n: Vector3::new(x, y, z), d: w },
        }
    }

    /// Constructs a plane that passes through the the three points `a`, `b` and `c`
    pub fn from_points(a: Point3<S>, b: Point3<S>, c: Point3<S>) -> Option<Plane<S>> {
        // create two vectors that run parallel to the plane
        let v0 = b.sub_p(&a);
        let v1 = c.sub_p(&a);

        // find the normal vector that is perpendicular to v1 and v2
        let mut n = v0.cross(&v1);

        if n.approx_eq(&Vector3::zero()) { None }
        else {
            // compute the normal and the distance to the plane
            n.normalize_self();
            let d = -a.dot(&n);

            Some(Plane::new(n, d))
        }
    }

    /// Construct a plane from a point and a normal vector.
    /// The plane will contain the point `p` and be perpendicular to `n`.
    pub fn from_point_normal(p: Point3<S>, n: Vector3<S>) -> Plane<S> {
        Plane { n: n, d: p.dot(&n) }
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Ray3<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        match *self {
            (ref p, ref r) => {
                let t = -(p.d + r.origin.dot(&p.n)) / r.direction.dot(&p.n);
                if t < Zero::zero() { None }
                else { Some(r.origin.add_v(&r.direction.mul_s(t))) }
            }
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Ray3<S>>> for (Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Ray3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat + ApproxEq<S>>
ApproxEq<S> for Plane<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Plane<S>, epsilon: &S) -> bool {
        self.n.approx_eq_eps(&other.n, epsilon) &&
        self.d.approx_eq_eps(&other.d, epsilon)
    }
}

impl<S: BaseFloat> fmt::Show for Plane<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:f}x + {:f}y + {:f}z - {:f} = 0",
               self.n.x, self.n.y, self.n.z, self.d)
    }
}
<|endoftext|>


<commit_before><commit_msg>Added OSX window generator<commit_after>extern crate cocoa;

use cocoa::base::{selector, id, nil, NO};

use cocoa::foundation::{NSRect, NSPoint, NSSize, NSAutoreleasePool, NSProcessInfo, NSString};

use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSWindow,
                    NSTitledWindowMask, NSBackingStoreBuffered, NSClosableWindowMask,
                    NSResizableWindowMask, NSMiniaturizableWindowMask,
                    NSUnifiedTitleAndToolbarWindowMask, NSMenu, NSMenuItem, NSTabView,
                    NSTabViewItem, NSRunningApplication, NSApplicationActivateIgnoringOtherApps};

fn main() {
    unsafe {
        // create tab view
        let tab_view = NSTabView::new(nil)
            .initWithFrame_(NSRect::new(NSPoint::new(0., 0.), NSSize::new(800., 800.)));

        // create a tab view item
        let tab_view_item = NSTabViewItem::new(nil)
            .initWithIdentifier_(NSString::alloc(nil).init_str("Tab View"));

        tab_view_item.setLabel(NSString::alloc(nil).init_str("Tab View Item"));
        tab_view.addTabViewItem_(tab_view_item);
    }
}

unsafe fn create_window(title: id, content: id) -> id {
    let _pool = NSAutoreleasePool::new(nil);

    let app = NSApp();

    // create a new Menu Bar
    let menubar = NSMenu::new(nil).autorelease();
    let app_menu_item = NSMenuIteem::new(nil).autorelease();
    menubar.addItem_(app_menu_item);

    // app menu
    let app_menu = NSMenu::new(nil).autorelease();
    let exit_prefix = NSString::alloc(nil).init_str("Exit...");
    let exit_title = exit_prefix.stringByAppendingString_(NSProcessInfo::processInfo(nil).procesName());
    let exit_action = selector("terminate(or):");
    let exit_key = NSString::alloc(nil).init_str("e");
    let exit_item = NSMenuItem::alloc(nil)
        .initWithTitle_action_keyEquivalent_(exit_title, exit_action, exit_key)
        .autorelease();
    app_menu.addItem_(exit_item);
    app_menu_item.setSubmenu_(app_menu);

    // draw the window
    let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer(
        NSRect::new(NSPoint::new(0., 0.), NSSize::new(800., 800.)),
        NSTitledWindowMask |
        NSClosableWindowMask |
        NSResizableWindowMask |
        NSMiniaturizableWindowMask |
        NSUnifiedTitleAndToolbarWindowMask,
        NSBackingStoreBuffered,
        NO
    ).autorelease();
    window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
    window.center();

    window.setTitle_(title);
    // window.setTitle_("Test"); for testing
    window.makeKeyAndOrderFront_(nil);

    window.setContentView_(content);
    let current_app = NSRunningApplication::currentApplication(nil);
    current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);

    return app;
}<|endoftext|>