<commit_before>
/// Trait for fixed size arrays.
///
/// This trait is implemented for some specific array sizes, see
/// the implementor list below. At the current state of Rust we can't
/// make this fully general for every array size.
///
/// The following crate features add more array sizes (and they are not
/// enabled by default due to their impact on compliation speed).
///
/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented
///   (a few in this range are included by default).
/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented
///   (a few in this range are included by default).
pub unsafe trait Array {
    /// The array’s element type
    type Item;
    /// The smallest type that can index and tell the length of the array.
    #[doc(hidden)]
    type Index: Index;
    /// The array's element capacity
    const CAPACITY: usize;
    fn as_slice(&self) -> &[Self::Item];
    fn as_mut_slice(&mut self) -> &mut [Self::Item];
}

pub trait Index : PartialEq + Copy {
    fn to_usize(self) -> usize;
    fn from(_: usize) -> Self;
}

impl Index for () {
    #[inline(always)]
    fn to_usize(self) -> usize { 0 }
    #[inline(always)]
    fn from(_ix: usize) ->  Self { () }
}

impl Index for bool {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix != 0 }
}

impl Index for u8 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u8 }
}

impl Index for u16 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u16 }
}

impl Index for u32 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u32 }
}

impl Index for usize {
    #[inline(always)]
    fn to_usize(self) -> usize { self }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix }
}

macro_rules! fix_array_impl {
    ($index_type:ty, $len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            type Index = $index_type;
            const CAPACITY: usize = $len;
            #[doc(hidden)]
            #[inline]
            fn as_slice(&self) -> &[Self::Item] { self }
            #[doc(hidden)]
            #[inline]
            fn as_mut_slice(&mut self) -> &mut [Self::Item] { self }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    ($index_type:ty, ) => ();
    ($index_type:ty, $($len:expr,)*) => (
        $(fix_array_impl!($index_type, $len);)*
    );
}

fix_array_impl_recursive!((), 0,);
fix_array_impl_recursive!(bool, 1,);
fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                          15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
                          28, 29, 30, 31, );

#[cfg(not(feature="array-sizes-33-128"))]
fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, );

#[cfg(feature="array-sizes-33-128")]
fix_array_impl_recursive!(u8,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, 128,
);

#[cfg(not(feature="array-sizes-129-255"))]
fix_array_impl_recursive!(u8, 160, 192, 200, 224,);

#[cfg(feature="array-sizes-129-255")]
fix_array_impl_recursive!(u8,
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255,
);

fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,);
// This array size doesn't exist on 16-bit
#[cfg(any(target_pointer_width="32", target_pointer_width="64"))]
fix_array_impl_recursive!(u32, 1 << 16,);

<commit_msg>DOC: Add safety documentation on Array trait<commit_after>
/// Trait for fixed size arrays.
///
/// This trait is implemented for some specific array sizes, see
/// the implementor list below. At the current state of Rust we can't
/// make this fully general for every array size.
///
/// The following crate features add more array sizes (and they are not
/// enabled by default due to their impact on compliation speed).
///
/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented
///   (a few in this range are included by default).
/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented
///   (a few in this range are included by default).
///
/// ## Safety
///
/// If implemented, this trait can only be implmented by fixed-size arrays or
/// types with exactly the representation of a fixed size array (of the right
/// element type and capacity).
///
/// Normally this trait is an implementation detail of arrayvec and doesn't
/// need implementing.
pub unsafe trait Array {
    /// The array’s element type
    type Item;
    /// The smallest type that can index and tell the length of the array.
    #[doc(hidden)]
    type Index: Index;
    /// The array's element capacity
    const CAPACITY: usize;
    fn as_slice(&self) -> &[Self::Item];
    fn as_mut_slice(&mut self) -> &mut [Self::Item];
}

pub trait Index : PartialEq + Copy {
    fn to_usize(self) -> usize;
    fn from(_: usize) -> Self;
}

impl Index for () {
    #[inline(always)]
    fn to_usize(self) -> usize { 0 }
    #[inline(always)]
    fn from(_ix: usize) ->  Self { () }
}

impl Index for bool {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix != 0 }
}

impl Index for u8 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u8 }
}

impl Index for u16 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u16 }
}

impl Index for u32 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u32 }
}

impl Index for usize {
    #[inline(always)]
    fn to_usize(self) -> usize { self }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix }
}

macro_rules! fix_array_impl {
    ($index_type:ty, $len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            type Index = $index_type;
            const CAPACITY: usize = $len;
            #[doc(hidden)]
            #[inline]
            fn as_slice(&self) -> &[Self::Item] { self }
            #[doc(hidden)]
            #[inline]
            fn as_mut_slice(&mut self) -> &mut [Self::Item] { self }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    ($index_type:ty, ) => ();
    ($index_type:ty, $($len:expr,)*) => (
        $(fix_array_impl!($index_type, $len);)*
    );
}

fix_array_impl_recursive!((), 0,);
fix_array_impl_recursive!(bool, 1,);
fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                          15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
                          28, 29, 30, 31, );

#[cfg(not(feature="array-sizes-33-128"))]
fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, );

#[cfg(feature="array-sizes-33-128")]
fix_array_impl_recursive!(u8,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, 128,
);

#[cfg(not(feature="array-sizes-129-255"))]
fix_array_impl_recursive!(u8, 160, 192, 200, 224,);

#[cfg(feature="array-sizes-129-255")]
fix_array_impl_recursive!(u8,
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255,
);

fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,);
// This array size doesn't exist on 16-bit
#[cfg(any(target_pointer_width="32", target_pointer_width="64"))]
fix_array_impl_recursive!(u32, 1 << 16,);

<|endoftext|>


<commit_before>extern crate dbus_bytestream;
use self::dbus_bytestream::connection;
use self::dbus_bytestream::demarshal;

use std::error;
use std::fmt::{Display, Formatter, Result};

#[derive(Debug)]
/// Error states.
pub enum Error {
    /// An invalid reply was received from a method call.
    InvalidReply(String),
    /// An error message from the underlying D-Bus communication.
    ErrorMessage(connection::Error),
    /// An object was added to a signal-receiver server.
    NoServerName,

    /// A server with the given name was already registered.
    ServerAlreadyRegistered(String),
    /// A request for a non-existent server was given.
    NoSuchServer(String),
    /// An object was registered to a path, but it already existed.
    PathAlreadyRegistered(String),
    /// An object was requested to be removed, but it does not exist.
    NoSuchPath(String),
    /// Extracting values from a message body failed.
    ExtractArguments(demarshal::DemarshalError),
    /// An attempt to redefine an interface for an object was made.
    InterfaceAlreadyRegistered(String),
    /// An attempt to add an interface to an object which is finalized was made.
    InterfacesFinalized(String),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match *self {
            Error::InvalidReply(ref desc)               => write!(f, "invalid reply: {}", desc),
            Error::ErrorMessage(ref error)              => write!(f, "dbus error: {:?}", error),
            Error::NoServerName                         => write!(f, "listening server cannot handle methods"),
            Error::ServerAlreadyRegistered(ref server)  => write!(f, "server already registered: {}", server),
            Error::NoSuchServer(ref server)             => write!(f, "no such server: {}", server),
            Error::PathAlreadyRegistered(ref path)      => write!(f, "path already registered: {}", path),
            Error::NoSuchPath(ref path)                 => write!(f, "no such path: {}", path),
            Error::ExtractArguments(ref dmerr)          => write!(f, "failed to extract arguments: {}", dmerr),
            Error::InterfaceAlreadyRegistered(ref name) => write!(f, "interface already registered: {}", name),
            Error::InterfacesFinalized(ref name)        => write!(f, "interfaces have been finalized; cannot add {}", name),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "D-Bus error"
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::ErrorMessage(ref error) => Some(error),
            _ => None,
        }
    }
}

impl From<connection::Error> for Error {
    fn from(error: connection::Error) -> Self {
        Error::ErrorMessage(error)
    }
}

impl From<demarshal::DemarshalError> for Error {
    fn from(error: demarshal::DemarshalError) -> Self {
        Error::ExtractArguments(error)
    }
}
<commit_msg>error: fix a whitespace nit<commit_after>extern crate dbus_bytestream;
use self::dbus_bytestream::connection;
use self::dbus_bytestream::demarshal;

use std::error;
use std::fmt::{Display, Formatter, Result};

#[derive(Debug)]
/// Error states.
pub enum Error {
    /// An invalid reply was received from a method call.
    InvalidReply(String),
    /// An error message from the underlying D-Bus communication.
    ErrorMessage(connection::Error),
    /// An object was added to a signal-receiver server.
    NoServerName,

    /// A server with the given name was already registered.
    ServerAlreadyRegistered(String),
    /// A request for a non-existent server was given.
    NoSuchServer(String),
    /// An object was registered to a path, but it already existed.
    PathAlreadyRegistered(String),
    /// An object was requested to be removed, but it does not exist.
    NoSuchPath(String),
    /// Extracting values from a message body failed.
    ExtractArguments(demarshal::DemarshalError),
    /// An attempt to redefine an interface for an object was made.
    InterfaceAlreadyRegistered(String),
    /// An attempt to add an interface to an object which is finalized was made.
    InterfacesFinalized(String),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match *self {
            Error::InvalidReply(ref desc)               => write!(f, "invalid reply: {}", desc),
            Error::ErrorMessage(ref error)              => write!(f, "dbus error: {:?}", error),
            Error::NoServerName                         => write!(f, "listening server cannot handle methods"),
            Error::ServerAlreadyRegistered(ref server)  => write!(f, "server already registered: {}", server),
            Error::NoSuchServer(ref server)             => write!(f, "no such server: {}", server),
            Error::PathAlreadyRegistered(ref path)      => write!(f, "path already registered: {}", path),
            Error::NoSuchPath(ref path)                 => write!(f, "no such path: {}", path),
            Error::ExtractArguments(ref dmerr)          => write!(f, "failed to extract arguments: {}", dmerr),
            Error::InterfaceAlreadyRegistered(ref name) => write!(f, "interface already registered: {}", name),
            Error::InterfacesFinalized(ref name)        => write!(f, "interfaces have been finalized; cannot add {}", name),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "D-Bus error"
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::ErrorMessage(ref error) => Some(error),
            _                              => None,
        }
    }
}

impl From<connection::Error> for Error {
    fn from(error: connection::Error) -> Self {
        Error::ErrorMessage(error)
    }
}

impl From<demarshal::DemarshalError> for Error {
    fn from(error: demarshal::DemarshalError) -> Self {
        Error::ExtractArguments(error)
    }
}
<|endoftext|>


<commit_before>extern crate base;
extern crate client;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate server;

use std::io::{self, Write};
use log::LogLevelFilter;

fn main() {
    // Initialize logger (by default error, warning and info logs are shown)
    env_logger::LogBuilder::new()
        .filter(None, LogLevelFilter::Info)
        .parse(&std::env::var("RUST_LOG").unwrap_or("".into()))
        .init()
        .expect("logger initialization failed");

    info!("~~~~~~~~~~ Plantex started ~~~~~~~~~~");
    // deprecated code
    // let res = client::start_game(client::Config::default(),
    // &base::world::NullProvider);
    let res = client::start_game(client::Config::default(),
                                 &base::gen::world::WorldGenerator::with_seed(42));

    // Check if any error occured
    if res.is_err() {
        // Maybe the user disabled all logs, so we mention that the logs
        // contain information about the error.
        writeln!(io::stderr(),
                 "An error occured! Check logs for more information!")
            .expect("write to stderr failed");
        std::process::exit(1);
    }
}
<commit_msg>remove deprecated code<commit_after>extern crate base;
extern crate client;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate server;

use std::io::{self, Write};
use log::LogLevelFilter;

fn main() {
    // Initialize logger (by default error, warning and info logs are shown)
    env_logger::LogBuilder::new()
        .filter(None, LogLevelFilter::Info)
        .parse(&std::env::var("RUST_LOG").unwrap_or("".into()))
        .init()
        .expect("logger initialization failed");

    info!("~~~~~~~~~~ Plantex started ~~~~~~~~~~");
    let res = client::start_game(client::Config::default(),
                                 &base::gen::world::WorldGenerator::with_seed(42));

    // Check if any error occured
    if res.is_err() {
        // Maybe the user disabled all logs, so we mention that the logs
        // contain information about the error.
        writeln!(io::stderr(),
                 "An error occured! Check logs for more information!")
            .expect("write to stderr failed");
        std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>//! The `image` element.

use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::layout::{self, StackingContext};
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::ParseValue;
use crate::rect::Rect;
use crate::session::Session;
use crate::xml::Attributes;

/// The `<image>` element.
///
/// Note that its x/y/width/height are properties in SVG2, so they are
/// defined as part of [the properties machinery](properties.rs).
#[derive(Default)]
pub struct Image {
    aspect: AspectRatio,
    href: Option<String>,
}

impl SetAttributes for Image {
    fn set_attributes(&mut self, attrs: &Attributes, _session: &Session) -> ElementResult {
        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,

                // "path" is used by some older Adobe Illustrator versions
                ref a if is_href(a) || *a == expanded_name!("", "path") => {
                    set_href(a, &mut self.href, value.to_string())
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl Draw for Image {
    fn draw(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes<'_>,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        let surface = match self.href {
            Some(ref url) => match acquired_nodes.lookup_image(url) {
                Ok(surf) => surf,
                Err(e) => {
                    rsvg_log!(
                        draw_ctx.session(),
                        "could not load image \"{}\": {}",
                        url,
                        e
                    );
                    return Ok(draw_ctx.empty_bbox());
                }
            },
            None => return Ok(draw_ctx.empty_bbox()),
        };

        let values = cascaded.get();

        let view_params = draw_ctx.get_view_params();
        let params = NormalizeParams::new(values, &view_params);

        let x = values.x().0.to_user(&params);
        let y = values.y().0.to_user(&params);

        let w = match values.width().0 {
            LengthOrAuto::Length(l) => l.to_user(&params),
            LengthOrAuto::Auto => surface.width() as f64,
        };
        let h = match values.height().0 {
            LengthOrAuto::Length(l) => l.to_user(&params),
            LengthOrAuto::Auto => surface.height() as f64,
        };

        let is_visible = values.is_visible();

        let rect = Rect::new(x, y, x + w, y + h);

        let overflow = values.overflow();

        let image = layout::Image {
            surface,
            is_visible,
            rect,
            aspect: self.aspect,
            overflow,
        };

        let elt = node.borrow_element();
        let stacking_ctx = StackingContext::new(
            draw_ctx.session(),
            acquired_nodes,
            &elt,
            values.transform(),
            values,
        );

        draw_ctx.draw_image(&image, &stacking_ctx, acquired_nodes, values, clipping)
    }
}
<commit_msg>image.rs: use set_attribute()<commit_after>//! The `image` element.

use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{set_attribute, Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::layout::{self, StackingContext};
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::ParseValue;
use crate::rect::Rect;
use crate::session::Session;
use crate::xml::Attributes;

/// The `<image>` element.
///
/// Note that its x/y/width/height are properties in SVG2, so they are
/// defined as part of [the properties machinery](properties.rs).
#[derive(Default)]
pub struct Image {
    aspect: AspectRatio,
    href: Option<String>,
}

impl SetAttributes for Image {
    fn set_attributes(&mut self, attrs: &Attributes, session: &Session) -> ElementResult {
        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "preserveAspectRatio") => {
                    set_attribute(&mut self.aspect, attr.parse(value), session)
                }

                // "path" is used by some older Adobe Illustrator versions
                ref a if is_href(a) || *a == expanded_name!("", "path") => {
                    set_href(a, &mut self.href, value.to_string())
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl Draw for Image {
    fn draw(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes<'_>,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        let surface = match self.href {
            Some(ref url) => match acquired_nodes.lookup_image(url) {
                Ok(surf) => surf,
                Err(e) => {
                    rsvg_log!(
                        draw_ctx.session(),
                        "could not load image \"{}\": {}",
                        url,
                        e
                    );
                    return Ok(draw_ctx.empty_bbox());
                }
            },
            None => return Ok(draw_ctx.empty_bbox()),
        };

        let values = cascaded.get();

        let view_params = draw_ctx.get_view_params();
        let params = NormalizeParams::new(values, &view_params);

        let x = values.x().0.to_user(&params);
        let y = values.y().0.to_user(&params);

        let w = match values.width().0 {
            LengthOrAuto::Length(l) => l.to_user(&params),
            LengthOrAuto::Auto => surface.width() as f64,
        };
        let h = match values.height().0 {
            LengthOrAuto::Length(l) => l.to_user(&params),
            LengthOrAuto::Auto => surface.height() as f64,
        };

        let is_visible = values.is_visible();

        let rect = Rect::new(x, y, x + w, y + h);

        let overflow = values.overflow();

        let image = layout::Image {
            surface,
            is_visible,
            rect,
            aspect: self.aspect,
            overflow,
        };

        let elt = node.borrow_element();
        let stacking_ctx = StackingContext::new(
            draw_ctx.session(),
            acquired_nodes,
            &elt,
            values.transform(),
            values,
        );

        draw_ctx.draw_image(&image, &stacking_ctx, acquired_nodes, values, clipping)
    }
}
<|endoftext|>


<commit_before>//  K8055.rs is a library for controlling the Vellemann K8055 USB IO card from rust.
//  Copyright (C) 2014 Falco Hirschenberger <falco.hirschenberger@gmail.com>
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License along
//  with this program; if not, write to the Free Software Foundation, Inc.,
//  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

//! Driver library for controlling the *Vellemann K8055(N)* USB digital and analog IO-cards.
//!
//! See the Vellemann [Homepage](http://www.velleman.eu/products/view/?id=351346) for the
//! hardware specification.

#![crate_type = "lib"]
extern crate libc;
extern crate usb;
extern crate serialize;

use std::iter::range_inclusive;
use std::fmt::{Show, Formatter, Error};
use std::default::Default;
use usb::libusb;

/// Analog values in the range (0-255).
#[deriving(PartialEq, PartialOrd, Show, Copy)]
pub enum AnalogChannel {
      A1(u8),
      A2(u8)
}

bitflags!(
#[doc = "
The digital channel values.

Can be combined with bitoperations.

    let dc = D1 & D2 & D3;

See the bitflags documentation for more information.
"]
  flags DigitalChannel: u8 {
#[doc = "All flags set to `off`"]
    const DZERO = 0,
    const D1 = 1,
    const D2 = 2,
    const D3 = 4,
    const D4 = 8,
    const D5 = 16,
    const D6 = 32,
    const D7 = 64,
    const D8 = 128,
#[doc = "All flags set to `on`"]
    const DALL = 255
  }
)

bitflags!(
#[doc = "
Adresses of the different cards that can be controlled.

See the jumper setting on your card for the correct address.
"]
    flags CardAddress: uint {
#[doc = "Use card `0x5500` (see jumper settings)"]
        const CARD_1 = 0x5500,
#[doc = "Use card `0x5501` (see jumper settings)"]
        const CARD_2 = 0x5501,
#[doc = "Use card `0x5502` (see jumper settings)"]
        const CARD_3 = 0x5502,
#[doc = "Use card `0x5503` (see jumper settings)"]
        const CARD_4 = 0x5503,
#[doc = "Automatically selects the first card found on the system"]
        const CARD_ANY = 0x0
    }
)

static VENDOR_ID: uint = 0x10cfu;

#[deriving(Show)]
enum Packet {
    Reset,
    SetAnalogDigital(u8, u8, u8),
    Status(u8, u8, u8, u8)
}

#[deriving(Default)]
struct State {
    dig: u8,
    ana1: u8,
    ana2: u8
}

/// Object controlling one Vellemann K8055 card.
pub struct K8055 {
    dev: usb::Device,
    hd: Option<usb::DeviceHandle>,
    state: State
}

impl K8055 {
    /// Create a new K8055 instance with the first card found on the system.
    ///
    /// May return `None` if no card was found connected to the system.
    pub fn new() -> Option<K8055> {
        K8055::new_addr(CARD_ANY)
    }

    /// Create a new K8055 instance with a specific card address.
    ///
    /// See the hardware jumpers on the card for your card's address. May return `None` if no card
    /// with the address `addr` can be found connected to the system.
    pub fn new_addr(addr: CardAddress) -> Option<K8055> {
        let c = usb::Context::new();
        let d = if addr == CARD_ANY {
            K8055::find_any_k8055(&c)
        } else {
            c.find_by_vid_pid(VENDOR_ID, addr.bits)
        };

        if d.is_some() {
            return Some(K8055{ dev: d.unwrap(), hd: None, state: Default::default() })
        } else {
            return None
        }
    }

    /// Open the device for starting IO operations.
    ///
    /// Returns `true` if the device was successfully opened or is already open. Returns `false`
    /// if the device can't be opened.
    pub fn open(&mut self) -> bool {
      // device already open
      if self.hd.is_some() { return true }
      match self.dev.open() {
          Ok(h) => {
              self.hd = Some(h);
              return true
          }
          Err(_) => return false
      }
    }

    /// Set all analog and digital values to zero.
    pub fn reset(&mut self) -> bool {
        self.write(&Packet::SetAnalogDigital(0u8, 0u8, 0u8))
    }

// digital

    /// Write the digital value `d` to the outports.
    ///
    /// Leaves the analog values untouched. Returns `false` on failure.
    pub fn write_digital_out(&mut self, d: DigitalChannel) -> bool {
        let p = &Packet::SetAnalogDigital(d.bits, self.state.ana1, self.state.ana2);
        self.write(p)
    }

    /// Write the masked digital value `d` to the outports.
    ///
    /// Masks `d` with `mask` to only affect bits which are `on` in the mask.
    /// Leaves the analog values untouched. Returns `false` on failure.
    pub fn write_digital_out_mask(&mut self, d: DigitalChannel, mask: DigitalChannel) -> bool {
        self.write_digital_out(d & mask)
    }

    /// Return the bits that are currently set on the digital out channel.
    pub fn get_digital_out(&mut self) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap()
    }

    /// Return the bits that are currently set on the digital out channel, masked with `mask`.
    pub fn get_digital_out_mask(&mut self, d: DigitalChannel) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap() & d
    }

    /// Read the digital in channel.
    ///
    /// Returns `None` on failure
    pub fn read_digital_in(&mut self) -> Option<DigitalChannel> {
        match self.read() {
            Some(Packet::Status(dig, _, _, _)) => Some(DigitalChannel::from_bits(dig).unwrap()),
            _ => None
        }
    }

    /// Read the digital in channel masked with `mask`.
    ///
    /// Returns `None` on failure
    pub fn read_digital_in_mask(&mut self, mask: DigitalChannel) -> Option<DigitalChannel> {
        match self.read_digital_in() {
            Some(c) => Some(c & mask),
            _ => None
        }
    }

// analog
    /// Write the analog value `a` to the given outport.
    ///
    /// Leaves the digital values untouched. Returns `false` on failure.
    pub fn write_analog_out(&mut self, a: AnalogChannel) -> bool {
      let p = match a {
          AnalogChannel::A1(v) => Packet::SetAnalogDigital(self.state.dig, v, self.state.ana2),
          AnalogChannel::A2(v) => Packet::SetAnalogDigital(self.state.dig, self.state.ana1, v)
      };
      self.write(&p)
    }

    /// Return the analog channel 1 out value
    pub fn get_analog_out1(&mut self) -> AnalogChannel {
        AnalogChannel::A1(self.state.ana1)
    }

    /// Return the analog channel 2 out value
    pub fn get_analog_out2(&mut self) -> AnalogChannel {
        AnalogChannel::A2(self.state.ana2)
    }

    /// Read the analog channel 1 input value.
    ///
    /// Returns `None` on failure.
    pub fn read_analog_in1(&mut self) -> Option<AnalogChannel> {
        match self.read() {
            Some(Packet::Status(_, _, a1, _)) => Some(AnalogChannel::A1(a1)),
            _ => None
        }
    }

    /// Read the analog channel 2 input value.
    ///
    /// Returns `None` on failure.
    pub fn read_analog_in2(&mut self) -> Option<AnalogChannel> {
        match self.read() {
            Some(Packet::Status(_, _, _, a2)) => Some(AnalogChannel::A2(a2)),
            _ => None
        }
    }

// private
    fn find_any_k8055(c: &usb::Context) -> Option<usb::Device> {
        for pid in range_inclusive(CARD_1.bits, CARD_4.bits) {
          let d = c.find_by_vid_pid(VENDOR_ID, pid);
          if d.is_some() { return d }
        }
        None
    }

    fn write(&mut self, p: &Packet) -> bool {
        match self.hd {
          Some(ref hd) => {
              K8055::detach_and_claim(hd);
              let data = match K8055::encode(p) {
                  Some(d) => d,
                  None => return false
              };

              match hd.write(0x1, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, &data) {
                  Ok(_) => {
                      // update the internal state on output changes
                      match *p {
                          Packet::SetAnalogDigital(d, a1, a2) => {
                              self.state = State{dig: d, ana1: a1, ana2: a2};
                          }
                          _ => ()
                      }
                      return true
                  }
                  Err(_) => return false
              }
          }
          None => return false
        }
    }

    fn read(&mut self) -> Option<Packet> {
        match self.hd {
          Some(ref hd) => {
            K8055::detach_and_claim(hd);
            match hd.read(0x81, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, 8) {
              Ok(data) => K8055::decode(data.as_slice()),
              Err(_) => None
            }
          }
          None => None
        }
    }

    fn encode(p: &Packet) -> Option<[u8, ..8]> {
      match *p {
          Packet::Reset => Some([0u8, ..8]),
          Packet::SetAnalogDigital(dig, ana1, ana2) => Some([5u8, dig, ana1, ana2,
                                                             0u8, 0u8, 0u8, 0u8]),
          _ => None
      }
    }

    fn decode(d: &[u8]) -> Option<Packet> {
       match d {
          [dig, st, ana1, ana2, _, _, _, _] => Some(Packet::Status(dig, st, ana1, ana2)),
          _ => None
       }
    }

    fn detach_and_claim(hd: &usb::DeviceHandle ) {
      unsafe {
        if libusb::libusb_kernel_driver_active(hd.ptr(), 0) == 1 {
          if libusb::libusb_detach_kernel_driver(hd.ptr(), 0) != 0 {
            panic!("Can't detach usb kernel driver");
          }
        }
      }
      hd.claim_interface(0u);
    }

}

impl Show for K8055 {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
      write!(f, "K8055( bus: {}, address: {} )", self.dev.bus(), self.dev.address())
    }
}

#[test()]
fn find_and_open() {
  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(K8055::new_addr(CARD_2).is_none());
  assert!(K8055::new_addr(CARD_3).is_none());
  assert!(K8055::new_addr(CARD_4).is_none());
}

#[test()]
fn write_and_read_digital() {
  use std::io::timer::sleep;
  use std::time::duration::Duration;

  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_digital_out() == DZERO);
  for i in range(0u, 8) {
    assert!(k.write_digital_out(DigitalChannel::from_bits(1u8<<i).unwrap()));
    assert!(k.get_digital_out() == DigitalChannel::from_bits(1u8<<i).unwrap());
    sleep(Duration::milliseconds(100));
  }
  assert!(k.reset());
  assert!(k.get_digital_out() == DZERO);

  assert!(k.write_digital_out_mask(D1 | D2 | D3, D2));
  assert!(k.get_digital_out() == D2);
  assert!(k.reset());
  sleep(Duration::milliseconds(1000));
}

#[test()]
fn write_and_read_analog() {
  use std::io::timer::sleep;
  use std::time::duration::Duration;

  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_analog_out1() == AnalogChannel::A1(0u8));
  assert!(k.get_analog_out2() == AnalogChannel::A2(0u8));
  for i in range(0u8, 255) {
    assert!(k.write_analog_out(AnalogChannel::A1(i)));
    assert!(k.write_analog_out(AnalogChannel::A2(255-i)));
    sleep(Duration::milliseconds(10));
  }
  assert!(k.reset());
  sleep(Duration::milliseconds(1000));
}
<commit_msg>Update to current rust<commit_after>//  K8055.rs is a library for controlling the Vellemann K8055 USB IO card from rust.
//  Copyright (C) 2014 Falco Hirschenberger <falco.hirschenberger@gmail.com>
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License along
//  with this program; if not, write to the Free Software Foundation, Inc.,
//  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

//! Driver library for controlling the *Vellemann K8055(N)* USB digital and analog IO-cards.
//!
//! See the Vellemann [Homepage](http://www.velleman.eu/products/view/?id=351346) for the
//! hardware specification.
#![feature(slicing_syntax)]

#![crate_type = "lib"]
extern crate libc;
extern crate usb;
extern crate serialize;

use std::iter::range_inclusive;
use std::fmt::{Show, Formatter, Error};
use std::default::Default;
use usb::libusb;

/// Analog values in the range (0-255).
#[derive(PartialEq, PartialOrd, Show, Copy)]
pub enum AnalogChannel {
      A1(u8),
      A2(u8)
}

bitflags!(
#[doc = "
The digital channel values.

Can be combined with bitoperations.

    let dc = D1 & D2 & D3;

See the bitflags documentation for more information.
"]
  flags DigitalChannel: u8 {
#[doc = "All flags set to `off`"]
    const DZERO = 0,
    const D1 = 1,
    const D2 = 2,
    const D3 = 4,
    const D4 = 8,
    const D5 = 16,
    const D6 = 32,
    const D7 = 64,
    const D8 = 128,
#[doc = "All flags set to `on`"]
    const DALL = 255
  }
);

bitflags!(
#[doc = "
Adresses of the different cards that can be controlled.

See the jumper setting on your card for the correct address.
"]
    flags CardAddress: uint {
#[doc = "Use card `0x5500` (see jumper settings)"]
        const CARD_1 = 0x5500,
#[doc = "Use card `0x5501` (see jumper settings)"]
        const CARD_2 = 0x5501,
#[doc = "Use card `0x5502` (see jumper settings)"]
        const CARD_3 = 0x5502,
#[doc = "Use card `0x5503` (see jumper settings)"]
        const CARD_4 = 0x5503,
#[doc = "Automatically selects the first card found on the system"]
        const CARD_ANY = 0x0
    }
);

static VENDOR_ID: uint = 0x10cfu;

#[derive(Show)]
enum Packet {
    Reset,
    SetAnalogDigital(u8, u8, u8),
    Status(u8, u8, u8, u8)
}

#[derive(Default)]
struct State {
    dig: u8,
    ana1: u8,
    ana2: u8
}

/// Object controlling one Vellemann K8055 card.
pub struct K8055 {
    dev: usb::Device,
    hd: Option<usb::DeviceHandle>,
    state: State
}

impl K8055 {
    /// Create a new K8055 instance with the first card found on the system.
    ///
    /// May return `None` if no card was found connected to the system.
    pub fn new() -> Option<K8055> {
        K8055::new_addr(CARD_ANY)
    }

    /// Create a new K8055 instance with a specific card address.
    ///
    /// See the hardware jumpers on the card for your card's address. May return `None` if no card
    /// with the address `addr` can be found connected to the system.
    pub fn new_addr(addr: CardAddress) -> Option<K8055> {
        let c = usb::Context::new();
        let d = if addr == CARD_ANY {
            K8055::find_any_k8055(&c)
        } else {
            c.find_by_vid_pid(VENDOR_ID, addr.bits)
        };

        if d.is_some() {
            return Some(K8055{ dev: d.unwrap(), hd: None, state: Default::default() })
        } else {
            return None
        }
    }

    /// Open the device for starting IO operations.
    ///
    /// Returns `true` if the device was successfully opened or is already open. Returns `false`
    /// if the device can't be opened.
    pub fn open(&mut self) -> bool {
      // device already open
      if self.hd.is_some() { return true }
      match self.dev.open() {
          Ok(h) => {
              self.hd = Some(h);
              return true
          }
          Err(_) => return false
      }
    }

    /// Set all analog and digital values to zero.
    pub fn reset(&mut self) -> bool {
        self.write(&Packet::SetAnalogDigital(0u8, 0u8, 0u8))
    }

// digital

    /// Write the digital value `d` to the outports.
    ///
    /// Leaves the analog values untouched. Returns `false` on failure.
    pub fn write_digital_out(&mut self, d: DigitalChannel) -> bool {
        let p = &Packet::SetAnalogDigital(d.bits, self.state.ana1, self.state.ana2);
        self.write(p)
    }

    /// Write the masked digital value `d` to the outports.
    ///
    /// Masks `d` with `mask` to only affect bits which are `on` in the mask.
    /// Leaves the analog values untouched. Returns `false` on failure.
    pub fn write_digital_out_mask(&mut self, d: DigitalChannel, mask: DigitalChannel) -> bool {
        self.write_digital_out(d & mask)
    }

    /// Return the bits that are currently set on the digital out channel.
    pub fn get_digital_out(&mut self) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap()
    }

    /// Return the bits that are currently set on the digital out channel, masked with `mask`.
    pub fn get_digital_out_mask(&mut self, d: DigitalChannel) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap() & d
    }

    /// Read the digital in channel.
    ///
    /// Returns `None` on failure
    pub fn read_digital_in(&mut self) -> Option<DigitalChannel> {
        match self.read() {
            Some(Packet::Status(dig, _, _, _)) => Some(DigitalChannel::from_bits(dig).unwrap()),
            _ => None
        }
    }

    /// Read the digital in channel masked with `mask`.
    ///
    /// Returns `None` on failure
    pub fn read_digital_in_mask(&mut self, mask: DigitalChannel) -> Option<DigitalChannel> {
        match self.read_digital_in() {
            Some(c) => Some(c & mask),
            _ => None
        }
    }

// analog
    /// Write the analog value `a` to the given outport.
    ///
    /// Leaves the digital values untouched. Returns `false` on failure.
    pub fn write_analog_out(&mut self, a: AnalogChannel) -> bool {
      let p = match a {
          AnalogChannel::A1(v) => Packet::SetAnalogDigital(self.state.dig, v, self.state.ana2),
          AnalogChannel::A2(v) => Packet::SetAnalogDigital(self.state.dig, self.state.ana1, v)
      };
      self.write(&p)
    }

    /// Return the analog channel 1 out value
    pub fn get_analog_out1(&mut self) -> AnalogChannel {
        AnalogChannel::A1(self.state.ana1)
    }

    /// Return the analog channel 2 out value
    pub fn get_analog_out2(&mut self) -> AnalogChannel {
        AnalogChannel::A2(self.state.ana2)
    }

    /// Read the analog channel 1 input value.
    ///
    /// Returns `None` on failure.
    pub fn read_analog_in1(&mut self) -> Option<AnalogChannel> {
        match self.read() {
            Some(Packet::Status(_, _, a1, _)) => Some(AnalogChannel::A1(a1)),
            _ => None
        }
    }

    /// Read the analog channel 2 input value.
    ///
    /// Returns `None` on failure.
    pub fn read_analog_in2(&mut self) -> Option<AnalogChannel> {
        match self.read() {
            Some(Packet::Status(_, _, _, a2)) => Some(AnalogChannel::A2(a2)),
            _ => None
        }
    }

// private
    fn find_any_k8055(c: &usb::Context) -> Option<usb::Device> {
        for pid in range_inclusive(CARD_1.bits, CARD_4.bits) {
          let d = c.find_by_vid_pid(VENDOR_ID, pid);
          if d.is_some() { return d }
        }
        None
    }

    fn write(&mut self, p: &Packet) -> bool {
        match self.hd {
          Some(ref hd) => {
              K8055::detach_and_claim(hd);
              let data = match K8055::encode(p) {
                  Some(d) => d,
                  None => return false
              };

              match hd.write(0x1, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, &data, 1000) {
                  Ok(_) => {
                      // update the internal state on output changes
                      match *p {
                          Packet::SetAnalogDigital(d, a1, a2) => {
                              self.state = State{dig: d, ana1: a1, ana2: a2};
                          }
                          _ => ()
                      }
                      return true
                  }
                  Err(_) => return false
              }
          }
          None => return false
        }
    }

    fn read(&mut self) -> Option<Packet> {
        match self.hd {
          Some(ref hd) => {
            K8055::detach_and_claim(hd);
            match hd.read(0x81, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, 8, 1000) {
              Ok(data) => K8055::decode(data.as_slice()),
              Err(_) => None
            }
          }
          None => None
        }
    }

    fn encode(p: &Packet) -> Option<[u8; 8]> {
      match *p {
          Packet::Reset => Some([0u8; 8]),
          Packet::SetAnalogDigital(dig, ana1, ana2) => Some([5u8, dig, ana1, ana2,
                                                             0u8, 0u8, 0u8, 0u8]),
          _ => None
      }
    }

    fn decode(d: &[u8]) -> Option<Packet> {
       match d {
          [dig, st, ana1, ana2, _, _, _, _] => Some(Packet::Status(dig, st, ana1, ana2)),
          _ => None
       }
    }

    fn detach_and_claim(hd: &usb::DeviceHandle ) {
      unsafe {
        if libusb::libusb_kernel_driver_active(hd.ptr(), 0) == 1 {
          if libusb::libusb_detach_kernel_driver(hd.ptr(), 0) != 0 {
            panic!("Can't detach usb kernel driver");
          }
        }
      }
      hd.claim_interface(0u);
    }

}

impl Show for K8055 {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
      write!(f, "K8055( bus: {}, address: {} )", self.dev.bus(), self.dev.address())
    }
}

#[test()]
fn find_and_open() {
  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(K8055::new_addr(CARD_2).is_none());
  assert!(K8055::new_addr(CARD_3).is_none());
  assert!(K8055::new_addr(CARD_4).is_none());
}

#[test()]
fn write_and_read_digital() {
  use std::io::timer::sleep;
  use std::time::duration::Duration;

  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_digital_out() == DZERO);
  for i in range(0u, 8) {
    assert!(k.write_digital_out(DigitalChannel::from_bits(1u8<<i).unwrap()));
    assert!(k.get_digital_out() == DigitalChannel::from_bits(1u8<<i).unwrap());
    sleep(Duration::milliseconds(100));
  }
  assert!(k.reset());
  assert!(k.get_digital_out() == DZERO);

  assert!(k.write_digital_out_mask(D1 | D2 | D3, D2));
  assert!(k.get_digital_out() == D2);
  assert!(k.reset());
  sleep(Duration::milliseconds(1000));
}

#[test()]
fn write_and_read_analog() {
  use std::io::timer::sleep;
  use std::time::duration::Duration;

  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_analog_out1() == AnalogChannel::A1(0u8));
  assert!(k.get_analog_out2() == AnalogChannel::A2(0u8));
  for i in range(0u8, 255) {
    assert!(k.write_analog_out(AnalogChannel::A1(i)));
    assert!(k.write_analog_out(AnalogChannel::A2(255-i)));
    sleep(Duration::milliseconds(10));
  }
  assert!(k.reset());
  sleep(Duration::milliseconds(1000));
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

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 new() -> 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,
}

impl Turn {
    pub fn switch_turns(&mut self) {
        *self = match *self {
            Turn::White => Turn::Black,
            Turn::Black => Turn::White,
        }
    }
}

pub struct Board {
    /*
                ____
               /    \
          ____/  +y  \____
         /    \      /    \
        /      \____/  +x  \
        \      /    \      /
         \____/      \____/
         /    \      /    \
        /  -x  \____/      \
        \      /    \      /
         \____/  -y  \____/
              \      /
               \____/

        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,
        because a ragged array won't work (since each row would have to be a different type).

        See http://www.redblobgames.com/grids/hexagons/#coordinates-axial for more info.
    */
    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, Debug, PartialEq)]
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 = Board {
            board: [[None; 5]; 5]
        };

        // (0, 0) is the only empty hex.
        board.set_hex(&HexCoord::new(0, 0), Some([Field::Empty; 6]));

        // All other hexes have exactly two pieces on them in the starting position.
        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.set_hex(&HexCoord::new(x, y), Some(hex));
        }

        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!(
                "Cannot get field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    fn set_field(&mut self, coord: &FieldCoord, field: Field) {
        match *self.get_hex(&coord.to_hex()) {
            Some(mut hex) => hex[coord.f as usize] = field,
            None => panic!(
                "Cannot set field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    /// 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::new(coord.x, coord.y, (coord.f + 1) % 6),
            FieldCoord::new(coord.x, coord.y, (coord.f + 5) % 6),
        ];

        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) {
        assert_eq!(
            self.get_field(from),
            &Field::Piece,
            "There is no piece at {:?} to move",
            from
        );
        assert!(
            self.get_field_vertex_neighbors(from).contains(to),
            "Cannot move piece at {:?} to non-(vertex neighbor) {:?}",
            from,
            to
        );
        assert_eq!(
            self.get_field(to),
            &Field::Empty,
            "Cannot move piece at {:?} to occupied neighbor {:?}",
            from,
            to
        );

        self.set_field(from, Field::Empty);
        self.set_field(to, Field::Piece);
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        assert_eq!(
            self.get_field(coord),
            &Field::Piece,
            "There is no piece at {:?} to remove",
            coord
        );
        self.set_field(coord, Field::Empty);
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        &self.board[(coord.x + 2) as usize][(coord.y + 2) as usize]
    }
    fn set_hex(&mut self, coord: &HexCoord, hex: Option<Hex>) {
        self.board[(coord.x + 2) as usize][(coord.y + 2) as usize] = hex;
    }
    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 {
        match *self.get_hex(coord) {
            Some(hex) => if hex.iter().any(|&f| f == Field::Piece) {
                return false;
            },
            None => panic!("The hex at {:?} has already been removed", coord),
        }

        let neighbor_idxs: Vec<u32> = coord.get_neighbors().iter().map(|&(i, _)| i).collect();
        let neighbor_idxs_slice = neighbor_idxs.as_slice();

        match neighbor_idxs_slice.len() {
            0 => panic!("A hex at {:?} is empty and has no neighbors", coord),
            1 => true,
            2 => {
                let valid_idx_combos = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [0, 5]];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            3 => {
                let valid_idx_combos = [
                    [0, 1, 2],
                    [1, 2, 3],
                    [2, 3, 4],
                    [3, 4, 5],
                    [0, 4, 5],
                    [0, 1, 5],
                ];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            _ => false,
        }
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        assert!(
            self.is_hex_removable(coord),
            "Cannot remove the hex at {:?} which is {:?} and has {} neighbors",
            coord,
            self.get_hex(coord),
            self.get_hex_neighbors(coord).len(),
        );
        self.set_hex(coord, None);
    }
    /// > extant (adj.): Still in existence; not destroyed, lost, or extinct (The Free Dictionary)
    ///
    /// Return the coordinates of the hexes that have not been removed yet.
    pub fn extant_hexes(&self) -> Vec<HexCoord> {
        let mut coords = vec![];

        for x in -2..3 {
            for y in -2..3 {
                if HexCoord::is_valid_coord(x, y) {
                    let coord = HexCoord::new(x, y);
                    if self.get_hex(&coord).is_some() {
                        coords.push(coord);
                    }
                }
            }
        }
        coords
    }
}

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

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

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

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!(Self::is_valid_coord(x, y));
        HexCoord { x, y }
    }
    pub fn x(&self) -> i32 {
        self.x
    }
    pub fn y(&self) -> i32 {
        self.y
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    pub fn is_valid_coord(x: i32, y: i32) -> bool {
        (x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2
    }
    // 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>Refactor HexCoord::get_neighbors into Board::get_hex_neighbors<commit_after>/*
 * Copyright (C) 2017 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

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 new() -> 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,
}

impl Turn {
    pub fn switch_turns(&mut self) {
        *self = match *self {
            Turn::White => Turn::Black,
            Turn::Black => Turn::White,
        }
    }
}

pub struct Board {
    /*
                ____
               /    \
          ____/  +y  \____
         /    \      /    \
        /      \____/  +x  \
        \      /    \      /
         \____/      \____/
         /    \      /    \
        /  -x  \____/      \
        \      /    \      /
         \____/  -y  \____/
              \      /
               \____/

        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,
        because a ragged array won't work (since each row would have to be a different type).

        See http://www.redblobgames.com/grids/hexagons/#coordinates-axial for more info.
    */
    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, Debug, PartialEq)]
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 = Board {
            board: [[None; 5]; 5]
        };

        // (0, 0) is the only empty hex.
        board.set_hex(&HexCoord::new(0, 0), Some([Field::Empty; 6]));

        // All other hexes have exactly two pieces on them in the starting position.
        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.set_hex(&HexCoord::new(x, y), Some(hex));
        }

        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!(
                "Cannot get field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    fn set_field(&mut self, coord: &FieldCoord, field: Field) {
        match *self.get_hex(&coord.to_hex()) {
            Some(mut hex) => hex[coord.f as usize] = field,
            None => panic!(
                "Cannot set field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    /// 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::new(coord.x, coord.y, (coord.f + 1) % 6),
            FieldCoord::new(coord.x, coord.y, (coord.f + 5) % 6),
        ];

        for (i, neighbor) in self.get_hex_neighbors(&coord.to_hex()) {
            if coord.f == i {
                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) {
        assert_eq!(
            self.get_field(from),
            &Field::Piece,
            "There is no piece at {:?} to move",
            from
        );
        assert!(
            self.get_field_vertex_neighbors(from).contains(to),
            "Cannot move piece at {:?} to non-(vertex neighbor) {:?}",
            from,
            to
        );
        assert_eq!(
            self.get_field(to),
            &Field::Empty,
            "Cannot move piece at {:?} to occupied neighbor {:?}",
            from,
            to
        );

        self.set_field(from, Field::Empty);
        self.set_field(to, Field::Piece);
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        assert_eq!(
            self.get_field(coord),
            &Field::Piece,
            "There is no piece at {:?} to remove",
            coord
        );
        self.set_field(coord, Field::Empty);
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        &self.board[(coord.x + 2) as usize][(coord.y + 2) as usize]
    }
    fn set_hex(&mut self, coord: &HexCoord, hex: Option<Hex>) {
        self.board[(coord.x + 2) as usize][(coord.y + 2) as usize] = hex;
    }
    // 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_hex_neighbors(&self, coord: &HexCoord) -> Vec<(u32, HexCoord)> {
        let neighbors = [
            (coord.x, coord.y + 1),
            (coord.x + 1, coord.y),
            (coord.x + 1, coord.y - 1),
            (coord.x, coord.y - 1),
            (coord.x - 1, coord.y),
            (coord.x - 1, coord.y + 1),
        ];

        neighbors
            .iter()
            .enumerate()
            .filter(|&(_, &(x, y))| HexCoord::is_valid_coord(x, y))
            .filter_map(|(i, &(x, y))| {
                let coord = HexCoord::new(x, y);
                match *self.get_hex(&coord) {
                    Some(_) => Some((i as u32, coord)),
                    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 self.get_hex_neighbors(coord) {
            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 {
        match *self.get_hex(coord) {
            Some(hex) => if hex.iter().any(|&f| f == Field::Piece) {
                return false;
            },
            None => panic!("The hex at {:?} has already been removed", coord),
        }

        let neighbor_idxs: Vec<u32> = self.get_hex_neighbors(coord).iter().map(|&(i, _)| i).collect();
        let neighbor_idxs_slice = neighbor_idxs.as_slice();

        match neighbor_idxs_slice.len() {
            0 => panic!("A hex at {:?} is empty and has no neighbors", coord),
            1 => true,
            2 => {
                let valid_idx_combos = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [0, 5]];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            3 => {
                let valid_idx_combos = [
                    [0, 1, 2],
                    [1, 2, 3],
                    [2, 3, 4],
                    [3, 4, 5],
                    [0, 4, 5],
                    [0, 1, 5],
                ];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            _ => false,
        }
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        assert!(
            self.is_hex_removable(coord),
            "Cannot remove the hex at {:?} which is {:?} and has {} neighbors",
            coord,
            self.get_hex(coord),
            self.get_hex_neighbors(coord).len(),
        );
        self.set_hex(coord, None);
    }
    /// > extant (adj.): Still in existence; not destroyed, lost, or extinct (The Free Dictionary)
    ///
    /// Return the coordinates of the hexes that have not been removed yet.
    pub fn extant_hexes(&self) -> Vec<HexCoord> {
        let mut coords = vec![];

        for x in -2..3 {
            for y in -2..3 {
                if HexCoord::is_valid_coord(x, y) {
                    let coord = HexCoord::new(x, y);
                    if self.get_hex(&coord).is_some() {
                        coords.push(coord);
                    }
                }
            }
        }
        coords
    }
}

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

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

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

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!(Self::is_valid_coord(x, y));
        HexCoord { x, y }
    }
    pub fn x(&self) -> i32 {
        self.x
    }
    pub fn y(&self) -> i32 {
        self.y
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    pub fn is_valid_coord(x: i32, y: i32) -> bool {
        (x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2
    }
}
<|endoftext|>


<commit_before>use rs_es::query::Filter;
use rs_es::units::JsonVal;

pub trait VectorOfTerms<T> {
  /// Extract the elements inside `Vec<T>` into `Vec<Filter>`, if present.
  /// Every element will be mapped into a `JsonVal`.
  fn build_terms(key: &str, values: &Vec<T>) -> Vec<Filter>;
}

macro_rules! build_vector_of_terms_impl {
  ($t:ty) => {
    impl VectorOfTerms<$t> for Filter {
      fn build_terms(key: &str, values: &Vec<$t>) -> Vec<Filter> {
        if values.is_empty() {
          return vec![];
        }

        vec![
          Filter::build_terms(key, values.iter()
                                         .map(|v| JsonVal::from(v.clone()))
                                         .collect::<Vec<JsonVal>>()).build()
        ]
      }
    }
  }
}

build_vector_of_terms_impl!(i32);
build_vector_of_terms_impl!(String);

#[cfg(test)]
mod tests {
  use terms::*;
  use rs_es::query::Filter;
  use rustc_serialize::json::ToJson;

  #[test]
  fn test_vector_of_terms() {
    assert!(<Filter as VectorOfTerms<String>>::build_terms("work_roles", &vec![])
                                              .is_empty());

    {
      let filters = <Filter as VectorOfTerms<String>>::build_terms(
                      "work_roles", &vec![String::from("Fullstack")]);
      assert_eq!(filters[0].to_json().to_string(),
                  String::from("{\"terms\":{\"work_roles\":[\"Fullstack\"]}}"));
    }

    {
      let filters = <Filter as VectorOfTerms<i32>>::build_terms(
                  "work_roles", &vec![1]);
      assert_eq!(filters[0].to_json().to_string(),
                  String::from("{\"terms\":{\"work_roles\":[1]}}"));
    }
  }
}
<commit_msg>terms: use to_owned() instead of String::from()<commit_after>use rs_es::query::Filter;
use rs_es::units::JsonVal;

pub trait VectorOfTerms<T> {
  /// Extract the elements inside `Vec<T>` into `Vec<Filter>`, if present.
  /// Every element will be mapped into a `JsonVal`.
  fn build_terms(key: &str, values: &Vec<T>) -> Vec<Filter>;
}

macro_rules! build_vector_of_terms_impl {
  ($t:ty) => {
    impl VectorOfTerms<$t> for Filter {
      fn build_terms(key: &str, values: &Vec<$t>) -> Vec<Filter> {
        if values.is_empty() {
          return vec![];
        }

        vec![
          Filter::build_terms(key, values.iter()
                                         .map(|v| JsonVal::from(v.clone()))
                                         .collect::<Vec<JsonVal>>()).build()
        ]
      }
    }
  }
}

build_vector_of_terms_impl!(i32);
build_vector_of_terms_impl!(String);

#[cfg(test)]
mod tests {
  use terms::*;
  use rs_es::query::Filter;
  use rustc_serialize::json::ToJson;

  #[test]
  fn test_vector_of_terms() {
    assert!(<Filter as VectorOfTerms<String>>::build_terms("work_roles", &vec![])
                                              .is_empty());

    {
      let filters = <Filter as VectorOfTerms<String>>::build_terms(
                      "work_roles", &vec!["Fullstack".to_owned()]);
      assert_eq!(filters[0].to_json().to_string(),
                  "{\"terms\":{\"work_roles\":[\"Fullstack\"]}}".to_owned());
    }

    {
      let filters = <Filter as VectorOfTerms<i32>>::build_terms(
                  "work_roles", &vec![1]);
      assert_eq!(filters[0].to_json().to_string(), "{\"terms\":{\"work_roles\":[1]}}".to_owned());
    }
  }
}
<|endoftext|>


<commit_before>
use std::cmp::Ordering::{self, Less, Equal, Greater};
use std::f32::consts::PI;
use num::{Float, NumCast, PrimInt, ToPrimitive};

/// Clamp a value between a given min and max.
pub fn clamp<T: PartialOrd>(n: T, min: T, max: T) -> T {
    if n < min { min } else if n > max { max } else { n }
}

/// Clamp a f32 between 0f32 and 1f32.
pub fn clampf32(f: f32) -> f32 {
    if f < 0f32 { 0f32 } else if f > 1f32 { 1f32 } else { f }
}

/// Compare two f64s and return an Ordering.
pub fn compare_f64s(a: f64, b: f64) -> Ordering {
    if a > b { Greater }
    else if a < b { Less }
    else { Equal }
}

/// Convert turns to radians.
pub fn turns<F: Float + NumCast>(t: F) -> F {
    let f: F = NumCast::from(2.0 * PI).unwrap();
    f * t
}

/// Convert degrees to radians.
pub fn degrees<F: Float + NumCast>(d: F) -> F {
    d * NumCast::from(PI / 180.0).unwrap()
}

/// The modulo function.
#[inline]
pub fn modulo<I: PrimInt>(a: I, b: I) -> I {
    match a % b {
        r if (r > I::zero() && b < I::zero())
          || (r < I::zero() && b > I::zero()) => (r + b),
        r                                         => r,
    }
}

/// Modulo float.
pub fn fmod(f: f32, n: i32) -> f32 {
    let i = f.floor() as i32;
    modulo(i, n) as f32 + f - i as f32
}

/// Return the max between to floats.
pub fn max(a: f32, b: f32) -> f32 {
    if a >= b { a } else { b }
}

/// Return the min between to floats.
pub fn min(a: f32, b: f32) -> f32 {
    if a <= b { a } else { b }
}

/// Get value percentage between max and min.
pub fn percentage<T: Float + NumCast>(value: T, min: T, max: T) -> f32 {
    let v: f32 = NumCast::from(value).unwrap();
    let mn: f32 = NumCast::from(min).unwrap();
    let mx: f32 = NumCast::from(max).unwrap();
    (v - mn) / (mx - mn)
}

/// Adjust the value to the given percentage.
pub fn value_from_perc<T: Float + NumCast + ToPrimitive>(perc: f32, min: T, max: T) -> T {
    let f: f32 = (max - min).to_f32().unwrap() * perc;
    min + NumCast::from(f).unwrap()
}

/// Map a value from a given range to a new given range.
pub fn map_range<X: Float + NumCast, Y: Float + NumCast>
(val: X, in_min: X, in_max: X, out_min: Y, out_max: Y) -> Y {
    let val_f: f64 = NumCast::from(val).unwrap();
    let in_min_f: f64 = NumCast::from(in_min).unwrap();
    let in_max_f: f64 = NumCast::from(in_max).unwrap();
    let out_min_f: f64 = NumCast::from(out_min).unwrap();
    let out_max_f: f64 = NumCast::from(out_max).unwrap();
    NumCast::from(
        (val_f - in_min_f) / (in_max_f - in_min_f) * (out_max_f - out_min_f) + out_min_f
    ).unwrap()
}

/// Get a suitable string from the value, its max and the pixel range.
pub fn val_to_string<T: ToString + NumCast>
(val: T, max: T, val_rng: T, pixel_range: usize) -> String {
    let mut s = val.to_string();
    let decimal = s.chars().position(|ch| ch == '.');
    match decimal {
        None => s,
        Some(idx) => {
            // Find the minimum string length by determing
            // what power of ten both the max and range are.
            let val_rng_f: f64 = NumCast::from(val_rng).unwrap();
            let max_f: f64 = NumCast::from(max).unwrap();
            let mut n: f64 = 0.0;
            let mut pow_ten = 0.0;
            while pow_ten < val_rng_f || pow_ten < max_f {
                pow_ten = (10.0).powf(n);
                n += 1.0
            }
            let min_string_len = n as usize + 1;

            // Find out how many pixels there are to actually use
            // and judge a reasonable precision from this.
            let mut n = 1;
            while 10us.pow(n) < pixel_range { n += 1 }
            let precision = n as usize;

            // Truncate the length to the pixel precision as
            // long as this doesn't cause it to be smaller
            // than the necessary decimal place.
            let mut truncate_len = min_string_len + (precision - 1);
            if idx + precision < truncate_len { truncate_len = idx + precision }
            if s.len() > truncate_len { s.truncate(truncate_len) }
            s
        }
    }
}

<commit_msg>Removed deprecated suffix<commit_after>
use std::cmp::Ordering::{self, Less, Equal, Greater};
use std::f32::consts::PI;
use num::{Float, NumCast, PrimInt, ToPrimitive};

/// Clamp a value between a given min and max.
pub fn clamp<T: PartialOrd>(n: T, min: T, max: T) -> T {
    if n < min { min } else if n > max { max } else { n }
}

/// Clamp a f32 between 0f32 and 1f32.
pub fn clampf32(f: f32) -> f32 {
    if f < 0f32 { 0f32 } else if f > 1f32 { 1f32 } else { f }
}

/// Compare two f64s and return an Ordering.
pub fn compare_f64s(a: f64, b: f64) -> Ordering {
    if a > b { Greater }
    else if a < b { Less }
    else { Equal }
}

/// Convert turns to radians.
pub fn turns<F: Float + NumCast>(t: F) -> F {
    let f: F = NumCast::from(2.0 * PI).unwrap();
    f * t
}

/// Convert degrees to radians.
pub fn degrees<F: Float + NumCast>(d: F) -> F {
    d * NumCast::from(PI / 180.0).unwrap()
}

/// The modulo function.
#[inline]
pub fn modulo<I: PrimInt>(a: I, b: I) -> I {
    match a % b {
        r if (r > I::zero() && b < I::zero())
          || (r < I::zero() && b > I::zero()) => (r + b),
        r                                         => r,
    }
}

/// Modulo float.
pub fn fmod(f: f32, n: i32) -> f32 {
    let i = f.floor() as i32;
    modulo(i, n) as f32 + f - i as f32
}

/// Return the max between to floats.
pub fn max(a: f32, b: f32) -> f32 {
    if a >= b { a } else { b }
}

/// Return the min between to floats.
pub fn min(a: f32, b: f32) -> f32 {
    if a <= b { a } else { b }
}

/// Get value percentage between max and min.
pub fn percentage<T: Float + NumCast>(value: T, min: T, max: T) -> f32 {
    let v: f32 = NumCast::from(value).unwrap();
    let mn: f32 = NumCast::from(min).unwrap();
    let mx: f32 = NumCast::from(max).unwrap();
    (v - mn) / (mx - mn)
}

/// Adjust the value to the given percentage.
pub fn value_from_perc<T: Float + NumCast + ToPrimitive>(perc: f32, min: T, max: T) -> T {
    let f: f32 = (max - min).to_f32().unwrap() * perc;
    min + NumCast::from(f).unwrap()
}

/// Map a value from a given range to a new given range.
pub fn map_range<X: Float + NumCast, Y: Float + NumCast>
(val: X, in_min: X, in_max: X, out_min: Y, out_max: Y) -> Y {
    let val_f: f64 = NumCast::from(val).unwrap();
    let in_min_f: f64 = NumCast::from(in_min).unwrap();
    let in_max_f: f64 = NumCast::from(in_max).unwrap();
    let out_min_f: f64 = NumCast::from(out_min).unwrap();
    let out_max_f: f64 = NumCast::from(out_max).unwrap();
    NumCast::from(
        (val_f - in_min_f) / (in_max_f - in_min_f) * (out_max_f - out_min_f) + out_min_f
    ).unwrap()
}

/// Get a suitable string from the value, its max and the pixel range.
pub fn val_to_string<T: ToString + NumCast>
(val: T, max: T, val_rng: T, pixel_range: usize) -> String {
    let mut s = val.to_string();
    let decimal = s.chars().position(|ch| ch == '.');
    match decimal {
        None => s,
        Some(idx) => {
            // Find the minimum string length by determing
            // what power of ten both the max and range are.
            let val_rng_f: f64 = NumCast::from(val_rng).unwrap();
            let max_f: f64 = NumCast::from(max).unwrap();
            let mut n: f64 = 0.0;
            let mut pow_ten = 0.0;
            while pow_ten < val_rng_f || pow_ten < max_f {
                pow_ten = (10.0).powf(n);
                n += 1.0
            }
            let min_string_len = n as usize + 1;

            // Find out how many pixels there are to actually use
            // and judge a reasonable precision from this.
            let mut n = 1;
            while 10.pow(n) < pixel_range { n += 1 }
            let precision = n as usize;

            // Truncate the length to the pixel precision as
            // long as this doesn't cause it to be smaller
            // than the necessary decimal place.
            let mut truncate_len = min_string_len + (precision - 1);
            if idx + precision < truncate_len { truncate_len = idx + precision }
            if s.len() > truncate_len { s.truncate(truncate_len) }
            s
        }
    }
}

<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate libc;

use native::ProtobufObj;
use protobuf::error::ProtobufError;
use protobuf::Message;

use std::raw::{Repr, Slice};
use std::vec::Vec;

/// Returns a wrapped represtation of the supplied vector as protobuf
/// data.
fn slice_to_pb(buffer: &[u8]) -> ProtobufObj {
    let repr = buffer.repr();
    ProtobufObj {
        data: repr.data as *mut libc::c_void,
        size: repr.len as u64
    }
}

/// Returns an unwrapped represtation of the supplied protobuf data
/// as a vector of bytes.
fn pb_to_slice(pb: &ProtobufObj) -> &[u8] {
    unsafe {
        // std::raw::Slice is internal representation of a slice,
        // so we just construct it manually and reinterpret it as an &[u8]
        ::std::mem::transmute(
            Slice {
                data: pb.data as *const u8,
                len: pb.size as uint
            }
        )
    }
}

/// Returns the result of serializing the supplied protobuf message
pub fn serialize(proto: &Message) -> Result<ProtobufObj, ProtobufError> {
    proto.write_to_bytes().map(|buffer: Vec<u8>| {
        slice_to_pb(buffer.as_slice())
    })
}

/// Returns the result of deserializing the supplied protobuf data
/// into the supplied message.
pub fn deserialize<'a, T: Message>(
    obj: &ProtobufObj,
    proto: &'a mut T) -> Result<&'a mut T, ProtobufError> {
    let slice = pb_to_slice(obj);
    try!(proto.merge_from_bytes(slice));
    Ok(proto)
}

<commit_msg>Reordered pb utils.<commit_after>#![allow(dead_code)]

extern crate libc;

use native::ProtobufObj;
use protobuf::error::ProtobufError;
use protobuf::Message;

use std::raw::{Repr, Slice};
use std::vec::Vec;

/// Returns the result of serializing the supplied protobuf message
pub fn serialize(proto: &Message) -> Result<ProtobufObj, ProtobufError> {
    proto.write_to_bytes().map(|buffer: Vec<u8>| {
        slice_to_pb(buffer.as_slice())
    })
}

/// Returns the result of deserializing the supplied protobuf data
/// into the supplied message.
pub fn deserialize<'a, T: Message>(
    obj: &ProtobufObj,
    proto: &'a mut T) -> Result<&'a mut T, ProtobufError> {
    let slice = pb_to_slice(obj);
    try!(proto.merge_from_bytes(slice));
    Ok(proto)
}

/// Returns a wrapped represtation of the supplied vector as protobuf
/// data.
fn slice_to_pb(buffer: &[u8]) -> ProtobufObj {
    let repr = buffer.repr();
    ProtobufObj {
        data: repr.data as *mut libc::c_void,
        size: repr.len as u64
    }
}

/// Returns an unwrapped represtation of the supplied protobuf data
/// as a vector of bytes.
fn pb_to_slice(pb: &ProtobufObj) -> &[u8] {
    unsafe {
        // std::raw::Slice is internal representation of a slice,
        // so we just construct it manually and reinterpret it as an &[u8]
        ::std::mem::transmute(
            Slice {
                data: pb.data as *const u8,
                len: pb.size as uint
            }
        )
    }
}

<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate sdl2_window;
extern crate gfx_device_gl;
extern crate gfx_graphics;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use piston::window::{ Window, WindowSettings, Size, OpenGLWindow };
use gfx_graphics::gfx::traits::*;
use gfx_graphics::{ Gfx2d, Texture, gfx, TextureSettings };
use sdl2_window::{ Sdl2Window, OpenGL };

fn main() {
    use graphics::draw_state::BlendPreset;

    println!("Press A to change blending");

    let mut window = Sdl2Window::new(
        OpenGL::_3_2,
        WindowSettings::new(
            "gfx_graphics: draw_state_test".to_string(),
            Size { width: 300, height: 300 }
        )
        .exit_on_esc(true)
    );

    let mut device = gfx_device_gl::GlDevice::new(|s| window.get_proc_address(s));
    let size = window.size();
    let frame = gfx::Frame::new(size.width as u16, size.height as u16);
    let mut renderer = device.create_renderer();

    let rust_logo = Texture::from_path(&mut device,
                                       &Path::new("./assets/rust.png"),
                                       &TextureSettings::new()).unwrap();
    let mut g2d = Gfx2d::new(&mut device);
    let mut blend = BlendPreset::Alpha;
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;
        use piston::input::*;

        if let Some(_) = e.render_args() {
            use graphics::*;

            g2d.draw(&mut renderer, &frame, |c, g| {
                let transform = c.transform.trans(100.0, 100.0);

                clear([0.8, 0.8, 0.8, 1.0], g);
                Rectangle::new([1.0, 0.0, 0.0, 1.0])
                    .draw([0.0, 0.0, 100.0, 100.0],
                          &c.draw_state,
                          c.transform,
                          g);

                let draw_state = c.draw_state.blend(blend);
                Rectangle::new([0.5, 1.0, 0.0, 0.3])
                    .draw([50.0, 50.0, 100.0, 100.0],
                          &draw_state,
                          c.transform,
                          g);
                Image::new().draw(&rust_logo, &c.draw_state, transform, g);
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
        }

        if let Some(Button::Keyboard(Key::A)) = e.press_args() {
            blend = match blend {
                BlendPreset::Alpha => BlendPreset::Add,
                BlendPreset::Add => BlendPreset::Multiply,
                BlendPreset::Multiply => BlendPreset::Invert,
                BlendPreset::Invert => BlendPreset::Alpha,
            };
            println!("Changed blending to {:?}", blend);
        }

        if let Some(_) = e.after_render_args() {
            device.after_frame();
        }
    }
}
<commit_msg>Added scissor clipping<commit_after>extern crate piston;
extern crate graphics;
extern crate sdl2_window;
extern crate gfx_device_gl;
extern crate gfx_graphics;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use piston::window::{ Window, WindowSettings, Size, OpenGLWindow };
use gfx_graphics::gfx::traits::*;
use gfx_graphics::{ Gfx2d, Texture, gfx, TextureSettings };
use sdl2_window::{ Sdl2Window, OpenGL };

fn main() {
    use graphics::draw_state::BlendPreset;

    println!("Press A to change blending");

    let mut window = Sdl2Window::new(
        OpenGL::_3_2,
        WindowSettings::new(
            "gfx_graphics: draw_state_test".to_string(),
            Size { width: 300, height: 300 }
        )
        .exit_on_esc(true)
    );

    let mut device = gfx_device_gl::GlDevice::new(|s| window.get_proc_address(s));
    let size = window.size();
    let frame = gfx::Frame::new(size.width as u16, size.height as u16);
    let mut renderer = device.create_renderer();

    let rust_logo = Texture::from_path(&mut device,
                                       &Path::new("./assets/rust.png"),
                                       &TextureSettings::new()).unwrap();
    let mut g2d = Gfx2d::new(&mut device);
    let mut blend = BlendPreset::Alpha;
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;
        use piston::input::*;

        if let Some(_) = e.render_args() {
            use graphics::*;

            g2d.draw(&mut renderer, &frame, |c, g| {
                let transform = c.transform.trans(100.0, 100.0);

                clear([0.8, 0.8, 0.8, 1.0], g);
                Rectangle::new([1.0, 0.0, 0.0, 1.0])
                    .draw([0.0, 0.0, 100.0, 100.0],
                          &c.draw_state,
                          c.transform,
                          g);

                let draw_state = c.draw_state.blend(blend);
                Rectangle::new([0.5, 1.0, 0.0, 0.3])
                    .draw([50.0, 50.0, 100.0, 100.0],
                          &draw_state,
                          c.transform,
                          g);

                let clipped = DrawState { scissor: Some(
                    ::graphics::draw_state::target::Rect { x: 100, y: 100, w: 100, h: 100 }
                ), ..c.draw_state };
                Image::new().draw(&rust_logo, &clipped, transform, g);
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
        }

        if let Some(Button::Keyboard(Key::A)) = e.press_args() {
            blend = match blend {
                BlendPreset::Alpha => BlendPreset::Add,
                BlendPreset::Add => BlendPreset::Multiply,
                BlendPreset::Multiply => BlendPreset::Invert,
                BlendPreset::Invert => BlendPreset::Alpha,
            };
            println!("Changed blending to {:?}", blend);
        }

        if let Some(_) = e.after_render_args() {
            device.after_frame();
        }
    }
}
<|endoftext|>