<commit_before>pub const NRBITS: u32 = 8;
pub const TYPEBITS: u32 = 8;

#[cfg(target_arch = "mips")]
mod consts {
    pub const NONE: u8 = 1;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 4;
    pub const SIZEBITS: u8 = 13;
    pub const DIRBITS: u8 = 3;
}
#[cfg(target_arch = "powerpc")]
mod consts {
    pub const NONE: u8 = 1;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 4;
    pub const SIZEBITS: u8 = 13;
    pub const DIRBITS: u8 = 3;
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))]
mod consts {
    pub const NONE: u8 = 0;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 1;
    pub const SIZEBITS: u8 = 14;
    pub const DIRBITS: u8 = 2;
}

pub use self::consts::*;

pub const NRSHIFT: u32 = 0;
pub const TYPESHIFT: u32 = NRSHIFT + NRBITS as u32;
pub const SIZESHIFT: u32 = TYPESHIFT + SIZEBITS as u32;
pub const DIRSHIFT: u32 = SIZESHIFT + DIRBITS as u32;

pub const NRMASK: u32 = (1 << NRBITS) - 1;
pub const TYPEMASK: u32 = (1 << TYPEBITS) - 1;
pub const SIZEMASK: u32 = (1 << SIZEBITS) - 1;
pub const DIRMASK: u32 = (1 << DIRBITS) - 1;

/// Encode an ioctl command.
#[macro_export]
macro_rules! ioc {
    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
    ($dir as u32) << $crate::DIRBITS |
        ($ty as u32) << $crate::TYPEBITS |
        ($nr as u32) << $crate::NRSHIFT |
        ($sz as u32) << $crate::SIZESHIFT)
}

/// Encode an ioctl command that reads.
#[macro_export]
macro_rules! ior {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
#[macro_export]
macro_rules! iow {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
#[macro_export]
macro_rules! iorw {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::READ|$crate::WRITE, $ty, $nr, $sz))
}

/// Declare a wrapper function around an ioctl.
#[macro_export]
macro_rules! ioctl {
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val)
        }
    );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *const $ty) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val)
        }
    );
    (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty) -> $crate::libc::c_int {
            $crate::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val)
        }
    );
    (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty, len: usize) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, len) as $crate::libc::c_ulong, val)
        }
    );
    (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *const $ty, len: usize) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, len) as $crate::libc::c_ulong, val)
        }
    );
    (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *const $ty, len: usize) -> $crate::libc::c_int {
            $crate::ioctl(fd, iorw!($ioty, $nr, len) as $crate::libc::c_ulong, val)
        }
    );
}

/// Extracts the "direction" (read/write/none) from an encoded ioctl command.
#[inline(always)]
pub fn ioc_dir(nr: u32) -> u8 {
    ((nr >> DIRSHIFT) & DIRMASK) as u8
}

/// Extracts the type from an encoded ioctl command.
#[inline(always)]
pub fn ioc_type(nr: u32) -> u32 {
    (nr >> TYPESHIFT) & TYPEMASK
}

/// Extracts the ioctl number from an encoded ioctl command.
#[inline(always)]
pub fn ioc_nr(nr: u32) -> u32 {
    (nr >> NRSHIFT) & NRMASK
}

/// Extracts the size from an encoded ioctl command.
#[inline(always)]
pub fn ioc_size(nr: u32) -> u32 {
    ((nr >> SIZESHIFT) as u32) & SIZEMASK
}

pub const IN: u32 = (WRITE as u32) << DIRSHIFT;
pub const OUT: u32 = (READ as u32) << DIRSHIFT;
pub const INOUT: u32 = ((READ|WRITE) as u32) << DIRSHIFT;
pub const SIZE_MASK: u32 = SIZEMASK << SIZESHIFT;
<commit_msg>[doc] Hide the constants<commit_after>#[doc(hidden)]
pub const NRBITS: u32 = 8;
#[doc(hidden)]
pub const TYPEBITS: u32 = 8;

#[cfg(target_arch = "mips")]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 1;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 4;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 13;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 3;
}
#[cfg(target_arch = "powerpc")]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 1;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 4;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 13;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 3;
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 0;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 1;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 14;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 2;
}

#[doc(hidden)]
pub use self::consts::*;

#[doc(hidden)]
pub const NRSHIFT: u32 = 0;
#[doc(hidden)]
pub const TYPESHIFT: u32 = NRSHIFT + NRBITS as u32;
#[doc(hidden)]
pub const SIZESHIFT: u32 = TYPESHIFT + SIZEBITS as u32;
#[doc(hidden)]
pub const DIRSHIFT: u32 = SIZESHIFT + DIRBITS as u32;

#[doc(hidden)]
pub const NRMASK: u32 = (1 << NRBITS) - 1;
#[doc(hidden)]
pub const TYPEMASK: u32 = (1 << TYPEBITS) - 1;
#[doc(hidden)]
pub const SIZEMASK: u32 = (1 << SIZEBITS) - 1;
#[doc(hidden)]
pub const DIRMASK: u32 = (1 << DIRBITS) - 1;

/// Encode an ioctl command.
#[macro_export]
macro_rules! ioc {
    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
        ($dir as u32) << $crate::DIRBITS |
        ($ty as u32) << $crate::TYPEBITS |
        ($nr as u32) << $crate::NRSHIFT |
        ($sz as u32) << $crate::SIZESHIFT)
}

/// Encode an ioctl command that reads.
#[macro_export]
macro_rules! ior {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
#[macro_export]
macro_rules! iow {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
#[macro_export]
macro_rules! iorw {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::READ|$crate::WRITE, $ty, $nr, $sz))
}

/// Declare a wrapper function around an ioctl.
#[macro_export]
macro_rules! ioctl {
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val)
        }
        );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *const $ty) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val)
        }
        );
    (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty) -> $crate::libc::c_int {
            $crate::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val)
        }
        );
    (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty, len: usize) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, len) as $crate::libc::c_ulong, val)
        }
        );
    (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *const $ty, len: usize) -> $crate::libc::c_int {
            $crate::ioctl(fd, ior!($ioty, $nr, len) as $crate::libc::c_ulong, val)
        }
        );
    (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *const $ty, len: usize) -> $crate::libc::c_int {
            $crate::ioctl(fd, iorw!($ioty, $nr, len) as $crate::libc::c_ulong, val)
        }
        );
}

/// Extracts the "direction" (read/write/none) from an encoded ioctl command.
#[inline(always)]
pub fn ioc_dir(nr: u32) -> u8 {
    ((nr >> DIRSHIFT) & DIRMASK) as u8
}

/// Extracts the type from an encoded ioctl command.
#[inline(always)]
pub fn ioc_type(nr: u32) -> u32 {
    (nr >> TYPESHIFT) & TYPEMASK
}

/// Extracts the ioctl number from an encoded ioctl command.
#[inline(always)]
pub fn ioc_nr(nr: u32) -> u32 {
    (nr >> NRSHIFT) & NRMASK
}

/// Extracts the size from an encoded ioctl command.
#[inline(always)]
pub fn ioc_size(nr: u32) -> u32 {
    ((nr >> SIZESHIFT) as u32) & SIZEMASK
}

#[doc(hidden)]
pub const IN: u32 = (WRITE as u32) << DIRSHIFT;
#[doc(hidden)]
pub const OUT: u32 = (READ as u32) << DIRSHIFT;
#[doc(hidden)]
pub const INOUT: u32 = ((READ|WRITE) as u32) << DIRSHIFT;
#[doc(hidden)]
pub const SIZE_MASK: u32 = SIZEMASK << SIZESHIFT;
<|endoftext|>


<commit_before>const NRBITS: u32 = 8;
const TYPEBITS: u32 = 8;

#[cfg(target_arch = "mips")]
mod consts {
    pub const NONE: u8 = 1;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 4;
    pub const SIZEBITS: u8 = 13;
    pub const DIRBITS: u8 = 3;
}
#[cfg(target_arch = "powerpc")]
mod consts {
    pub const NONE: u8 = 1;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 4;
    pub const SIZEBITS: u8 = 13;
    pub const DIRBITS: u8 = 3;
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))]
mod consts {
    pub const NONE: u8 = 0;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 1;
    pub const SIZEBITS: u8 = 14;
    pub const DIRBITS: u8 = 2;
}

pub use self::consts::*;

pub const NRSHIFT: u32 = 0;
pub const TYPESHIFT: u32 = NRSHIFT + NRBITS as u32;
pub const SIZESHIFT: u32 = TYPESHIFT + SIZEBITS as u32;
pub const DIRSHIFT: u32 = SIZESHIFT + DIRBITS as u32;

pub const NRMASK: u32 = (1 << NRBITS) - 1;
pub const TYPEMASK: u32 = (1 << TYPEBITS) - 1;
pub const SIZEMASK: u32 = (1 << SIZEBITS) - 1;
pub const DIRMASK: u32 = (1 << DIRBITS) - 1;

/// Encode an ioctl command.
#[macro_export]
macro_rules! ioc {
    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
    ($dir as u32) << DIRBITS |
        ($ty as u32) << TYPEBITS |
        ($nr as u32) << NRSHIFT |
        ($sz as u32) << SIZESHIFT)
}

/// Encode an ioctl command that reads.
#[macro_export]
macro_rules! ior {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!(READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
#[macro_export]
macro_rules! iow {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!(WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
#[macro_export]
macro_rules! iorw {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!(READ|WRITE, $ty, $nr, $sz))
}

/// Declare a wrapper function around an ioctl.
#[macro_export]
macro_rules! ioctl {
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: &mut $ty) {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as ::libc::c_ulong, val);
        }
    );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: c_int, val: &$ty) {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as ::libc::c_ulong, val);
        }
    );
}

#[inline(always)]
pub fn ioc_dir(nr: u32) -> u8 {
    ((nr >> DIRSHIFT) & DIRMASK) as u8
}

#[inline(always)]
pub fn ioc_type(nr: u32) -> u32 {
    (nr >> TYPESHIFT) & TYPEMASK
}

#[inline(always)]
pub fn ioc_nr(nr: u32) -> u32 {
    (nr >> NRSHIFT) & NRMASK
}

#[inline(always)]
pub fn ioc_size(nr: u32) -> u32 {
    ((nr >> SIZESHIFT) as u32) & SIZEMASK
}

pub const IN: u32 = (WRITE as u32) << DIRSHIFT;
pub const OUT: u32 = (READ as u32) << DIRSHIFT;
pub const INOUT: u32 = ((READ|WRITE) as u32) << DIRSHIFT;
pub const SIZE_MASK: u32 = SIZEMASK << SIZESHIFT;
<commit_msg>[fix] Don't use references in the ioctl binding<commit_after>const NRBITS: u32 = 8;
const TYPEBITS: u32 = 8;

#[cfg(target_arch = "mips")]
mod consts {
    pub const NONE: u8 = 1;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 4;
    pub const SIZEBITS: u8 = 13;
    pub const DIRBITS: u8 = 3;
}
#[cfg(target_arch = "powerpc")]
mod consts {
    pub const NONE: u8 = 1;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 4;
    pub const SIZEBITS: u8 = 13;
    pub const DIRBITS: u8 = 3;
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))]
mod consts {
    pub const NONE: u8 = 0;
    pub const READ: u8 = 2;
    pub const WRITE: u8 = 1;
    pub const SIZEBITS: u8 = 14;
    pub const DIRBITS: u8 = 2;
}

pub use self::consts::*;

pub const NRSHIFT: u32 = 0;
pub const TYPESHIFT: u32 = NRSHIFT + NRBITS as u32;
pub const SIZESHIFT: u32 = TYPESHIFT + SIZEBITS as u32;
pub const DIRSHIFT: u32 = SIZESHIFT + DIRBITS as u32;

pub const NRMASK: u32 = (1 << NRBITS) - 1;
pub const TYPEMASK: u32 = (1 << TYPEBITS) - 1;
pub const SIZEMASK: u32 = (1 << SIZEBITS) - 1;
pub const DIRMASK: u32 = (1 << DIRBITS) - 1;

/// Encode an ioctl command.
#[macro_export]
macro_rules! ioc {
    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
    ($dir as u32) << DIRBITS |
        ($ty as u32) << TYPEBITS |
        ($nr as u32) << NRSHIFT |
        ($sz as u32) << SIZESHIFT)
}

/// Encode an ioctl command that reads.
#[macro_export]
macro_rules! ior {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!(READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
#[macro_export]
macro_rules! iow {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!(WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
#[macro_export]
macro_rules! iorw {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!(READ|WRITE, $ty, $nr, $sz))
}

/// Declare a wrapper function around an ioctl.
#[macro_export]
macro_rules! ioctl {
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int, val: *mut $ty) {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as ::libc::c_ulong, val);
        }
    );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: c_int, val: *const $ty) {
            $crate::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as ::libc::c_ulong, val);
        }
    );
}

#[inline(always)]
pub fn ioc_dir(nr: u32) -> u8 {
    ((nr >> DIRSHIFT) & DIRMASK) as u8
}

#[inline(always)]
pub fn ioc_type(nr: u32) -> u32 {
    (nr >> TYPESHIFT) & TYPEMASK
}

#[inline(always)]
pub fn ioc_nr(nr: u32) -> u32 {
    (nr >> NRSHIFT) & NRMASK
}

#[inline(always)]
pub fn ioc_size(nr: u32) -> u32 {
    ((nr >> SIZESHIFT) as u32) & SIZEMASK
}

pub const IN: u32 = (WRITE as u32) << DIRSHIFT;
pub const OUT: u32 = (READ as u32) << DIRSHIFT;
pub const INOUT: u32 = ((READ|WRITE) as u32) << DIRSHIFT;
pub const SIZE_MASK: u32 = SIZEMASK << SIZESHIFT;
<|endoftext|>


<commit_before>//! Definition of the triangle shape.

#[cfg(feature = "dim3")]
use std::f64;
use std::mem;
use na::{self, Unit};
use na::Real;
use shape::SupportMap;
use math::{Isometry, Point, Vector};
use utils::IsometryOps;

#[cfg(feature = "dim3")]
use smallvec::SmallVec;
#[cfg(feature = "dim3")]
use shape::{ConvexPolygonalFeature, ConvexPolyhedron, FeatureId};
#[cfg(feature = "dim3")]
use bounding_volume::PolyhedralCone;

/// A triangle shape.
#[derive(PartialEq, Debug, Clone)]
pub struct Triangle<N: Real> {
    a: Point<N>,
    b: Point<N>,
    c: Point<N>,
}

/// Description of the location of a point on a triangle.
#[derive(Copy, Clone, Debug)]
pub enum TrianglePointLocation<N: Real> {
    /// The point lies on a vertex.
    OnVertex(usize),
    /// The point lies on an edge.
    OnEdge(usize, [N; 2]),
    /// The point lies on the triangle interior.
    OnFace([N; 3]),
    /// The point lies on the triangle interior (for "solid" point queries).
    OnSolid,
}

impl<N: Real> TrianglePointLocation<N> {
    /// Returns `true` if the point is located on the relative interior of the triangle.
    pub fn is_on_face(&self) -> bool {
        if let TrianglePointLocation::OnFace(_) = *self {
            true
        } else {
            false
        }
    }
}

impl<N: Real> Triangle<N> {
    /// Creates a triangle from three points.
    #[inline]
    pub fn new(a: Point<N>, b: Point<N>, c: Point<N>) -> Triangle<N> {
        Triangle { a, b, c }
    }

    /// Creates the reference to a triangle from the reference to an array of three points.
    pub fn from_array(arr: &[Point<N>; 3]) -> &Triangle<N> {
        unsafe { mem::transmute(arr) }
    }

    /// The fist point of this triangle.
    #[inline]
    pub fn a(&self) -> &Point<N> {
        &self.a
    }

    /// The second point of this triangle.
    #[inline]
    pub fn b(&self) -> &Point<N> {
        &self.b
    }

    /// The third point of this triangle.
    #[inline]
    pub fn c(&self) -> &Point<N> {
        &self.c
    }

    /// Reference to an array containing the three vertices of this triangle.
    #[inline]
    pub fn as_array(&self) -> &[Point<N>; 3] {
        unsafe { mem::transmute(self) }
    }

    /// The normal of this triangle assuming it is oriented ccw.
    ///
    /// The normal points such that it is collinear to `AB × AC` (where `×` denotes the cross
    /// product).
    #[inline]
    pub fn normal(&self) -> Option<Unit<Vector<N>>> {
        Unit::try_new(self.scaled_normal(), N::default_epsilon())
    }

    /// A vector normal of this triangle.
    ///
    /// The vector points such that it is collinear to `AB × AC` (where `×` denotes the cross
    /// product).
    #[inline]
    pub fn scaled_normal(&self) -> Vector<N> {
        let ab = self.b - self.a;
        let ac = self.c - self.a;
        ab.cross(&ac)
    }
}

impl<N: Real> SupportMap<N> for Triangle<N> {
    #[inline]
    fn support_point(&self, m: &Isometry<N>, dir: &Vector<N>) -> Point<N> {
        let local_dir = m.inverse_transform_vector(dir);

        let d1 = na::dot(&self.a().coords, &local_dir);
        let d2 = na::dot(&self.b().coords, &local_dir);
        let d3 = na::dot(&self.c().coords, &local_dir);

        let res = if d1 > d2 {
            if d1 > d3 {
                self.a()
            } else {
                self.c()
            }
        } else {
            if d2 > d3 {
                self.b()
            } else {
                self.c()
            }
        };

        m * res
    }
}

#[cfg(feature = "dim3")]
impl<N: Real> ConvexPolyhedron<N> for Triangle<N> {
    fn vertex(&self, id: FeatureId) -> Point<N> {
        match id.unwrap_vertex() {
            0 => self.a,
            1 => self.b,
            2 => self.c,
            _ => panic!("Triangle vertex index out of bounds."),
        }
    }
    fn edge(&self, id: FeatureId) -> (Point<N>, Point<N>, FeatureId, FeatureId) {
        match id.unwrap_edge() {
            0 => (self.a, self.b, FeatureId::Vertex(0), FeatureId::Vertex(1)),
            2 => (self.b, self.c, FeatureId::Vertex(1), FeatureId::Vertex(2)),
            3 => (self.c, self.a, FeatureId::Vertex(2), FeatureId::Vertex(0)),
            _ => panic!("Triangle edge index out of bounds."),
        }
    }

    fn face(&self, id: FeatureId, face: &mut ConvexPolygonalFeature<N>) {
        face.clear();

        if let Some(normal) = self.normal() {
            face.set_feature_id(id);

            match id.unwrap_face() {
                0 => {
                    face.push(self.a, FeatureId::Vertex(0));
                    face.push(self.b, FeatureId::Vertex(1));
                    face.push(self.c, FeatureId::Vertex(2));
                    face.push_edge_feature_id(FeatureId::Edge(0));
                    face.push_edge_feature_id(FeatureId::Edge(1));
                    face.push_edge_feature_id(FeatureId::Edge(2));
                    face.set_normal(normal);
                }
                1 => {
                    face.push(self.a, FeatureId::Vertex(0));
                    face.push(self.c, FeatureId::Vertex(2));
                    face.push(self.b, FeatureId::Vertex(1));
                    face.push_edge_feature_id(FeatureId::Edge(2));
                    face.push_edge_feature_id(FeatureId::Edge(1));
                    face.push_edge_feature_id(FeatureId::Edge(0));
                    face.set_normal(-normal);
                }
                _ => unreachable!(),
            }

            face.recompute_edge_normals();
        } else {
            face.push(self.a, FeatureId::Vertex(0));
            face.set_feature_id(FeatureId::Vertex(0));
        }
    }

    fn normal_cone(&self, feature: FeatureId) -> PolyhedralCone<N> {
        if let Some(normal) = self.normal() {
            match feature {
                FeatureId::Vertex(id2) => {
                    let vtx = self.as_array();
                    let mut generators = SmallVec::new();
                    let id1 = if id2 == 0 { 2 } else { id2 - 1 };
                    let id3 = (id2 + 1) % 3;

                    if let Some(side1) = Unit::try_new(vtx[id2] - vtx[id1], N::default_epsilon()) {
                        generators.push(side1);
                    }
                    generators.push(-normal);
                    if let Some(side2) = Unit::try_new(vtx[id3] - vtx[id2], N::default_epsilon()) {
                        generators.push(side2);
                    }
                    generators.push(normal);

                    // FIXME: is it meaningful not to push the sides if the triangle is degenerate?

                    PolyhedralCone::Span(generators)
                }
                FeatureId::Edge(id1) => {
                    // FIXME: We should be able to do much better here.
                    let id2 = (id1 + 1) % 3;
                    let vtx = self.as_array();
                    let mut generators = SmallVec::new();

                    if let Some(side) = Unit::try_new(vtx[id2] - vtx[id1], N::default_epsilon()) {
                        generators.push(side);
                        generators.push(-normal);
                        generators.push(side);
                        generators.push(normal);
                    } else {
                        // FIXME: is this meaningful?
                        generators.push(-normal);
                        generators.push(normal);
                    }

                    PolyhedralCone::Span(generators)
                }
                FeatureId::Face(0) => PolyhedralCone::HalfLine(normal),
                FeatureId::Face(1) => PolyhedralCone::HalfLine(-normal),
                _ => panic!("Invalid feature ID."),
            }
        } else {
            PolyhedralCone::Full
        }
    }

    fn support_face_toward(
        &self,
        m: &Isometry<N>,
        dir: &Unit<Vector<N>>,
        face: &mut ConvexPolygonalFeature<N>,
    ) {
        let normal = self.scaled_normal();

        if na::dot(&normal, &*dir) >= na::zero() {
            ConvexPolyhedron::<N>::face(self, FeatureId::Face(0), face);
        } else {
            ConvexPolyhedron::<N>::face(self, FeatureId::Face(1), face);
        }
        face.transform_by(m)
    }

    fn support_feature_toward(
        &self,
        transform: &Isometry<N>,
        dir: &Unit<Vector<N>>,
        _angle: N,
        out: &mut ConvexPolygonalFeature<N>,
    ) {
        out.clear();
        // FIXME: actualy find the support feature.
        self.support_face_toward(transform, dir, out)
    }

    fn support_feature_id_toward(&self, local_dir: &Unit<Vector<N>>) -> FeatureId {
        if let Some(normal) = self.normal() {
            let eps: N = na::convert(f64::consts::PI / 180.0);
            let ceps = eps.cos();

            let normal_dot = local_dir.dot(&*normal);
            if normal_dot >= ceps {
                FeatureId::Face(0)
            } else if normal_dot <= -ceps {
                FeatureId::Face(1)
            } else {
                let dot1 = local_dir.dot(&self.a.coords);
                let dot2 = local_dir.dot(&self.b.coords);
                let dot3 = local_dir.dot(&self.c.coords);

                if dot1 > dot2 {
                    if dot1 > dot3 {
                        FeatureId::Vertex(0)
                    } else {
                        FeatureId::Vertex(2)
                    }
                } else if dot2 > dot3 {
                    FeatureId::Vertex(1)
                } else {
                    FeatureId::Vertex(2)
                }
            }
        } else {
            FeatureId::Vertex(0)
        }
    }
}
<commit_msg>Fix edge FeatureId indexing for triangles.<commit_after>//! Definition of the triangle shape.

#[cfg(feature = "dim3")]
use std::f64;
use std::mem;
use na::{self, Unit};
use na::Real;
use shape::SupportMap;
use math::{Isometry, Point, Vector};
use utils::IsometryOps;

#[cfg(feature = "dim3")]
use smallvec::SmallVec;
#[cfg(feature = "dim3")]
use shape::{ConvexPolygonalFeature, ConvexPolyhedron, FeatureId};
#[cfg(feature = "dim3")]
use bounding_volume::PolyhedralCone;

/// A triangle shape.
#[derive(PartialEq, Debug, Clone)]
pub struct Triangle<N: Real> {
    a: Point<N>,
    b: Point<N>,
    c: Point<N>,
}

/// Description of the location of a point on a triangle.
#[derive(Copy, Clone, Debug)]
pub enum TrianglePointLocation<N: Real> {
    /// The point lies on a vertex.
    OnVertex(usize),
    /// The point lies on an edge.
    OnEdge(usize, [N; 2]),
    /// The point lies on the triangle interior.
    OnFace([N; 3]),
    /// The point lies on the triangle interior (for "solid" point queries).
    OnSolid,
}

impl<N: Real> TrianglePointLocation<N> {
    /// Returns `true` if the point is located on the relative interior of the triangle.
    pub fn is_on_face(&self) -> bool {
        if let TrianglePointLocation::OnFace(_) = *self {
            true
        } else {
            false
        }
    }
}

impl<N: Real> Triangle<N> {
    /// Creates a triangle from three points.
    #[inline]
    pub fn new(a: Point<N>, b: Point<N>, c: Point<N>) -> Triangle<N> {
        Triangle { a, b, c }
    }

    /// Creates the reference to a triangle from the reference to an array of three points.
    pub fn from_array(arr: &[Point<N>; 3]) -> &Triangle<N> {
        unsafe { mem::transmute(arr) }
    }

    /// The fist point of this triangle.
    #[inline]
    pub fn a(&self) -> &Point<N> {
        &self.a
    }

    /// The second point of this triangle.
    #[inline]
    pub fn b(&self) -> &Point<N> {
        &self.b
    }

    /// The third point of this triangle.
    #[inline]
    pub fn c(&self) -> &Point<N> {
        &self.c
    }

    /// Reference to an array containing the three vertices of this triangle.
    #[inline]
    pub fn as_array(&self) -> &[Point<N>; 3] {
        unsafe { mem::transmute(self) }
    }

    /// The normal of this triangle assuming it is oriented ccw.
    ///
    /// The normal points such that it is collinear to `AB × AC` (where `×` denotes the cross
    /// product).
    #[inline]
    pub fn normal(&self) -> Option<Unit<Vector<N>>> {
        Unit::try_new(self.scaled_normal(), N::default_epsilon())
    }

    /// A vector normal of this triangle.
    ///
    /// The vector points such that it is collinear to `AB × AC` (where `×` denotes the cross
    /// product).
    #[inline]
    pub fn scaled_normal(&self) -> Vector<N> {
        let ab = self.b - self.a;
        let ac = self.c - self.a;
        ab.cross(&ac)
    }
}

impl<N: Real> SupportMap<N> for Triangle<N> {
    #[inline]
    fn support_point(&self, m: &Isometry<N>, dir: &Vector<N>) -> Point<N> {
        let local_dir = m.inverse_transform_vector(dir);

        let d1 = na::dot(&self.a().coords, &local_dir);
        let d2 = na::dot(&self.b().coords, &local_dir);
        let d3 = na::dot(&self.c().coords, &local_dir);

        let res = if d1 > d2 {
            if d1 > d3 {
                self.a()
            } else {
                self.c()
            }
        } else {
            if d2 > d3 {
                self.b()
            } else {
                self.c()
            }
        };

        m * res
    }
}

#[cfg(feature = "dim3")]
impl<N: Real> ConvexPolyhedron<N> for Triangle<N> {
    fn vertex(&self, id: FeatureId) -> Point<N> {
        match id.unwrap_vertex() {
            0 => self.a,
            1 => self.b,
            2 => self.c,
            _ => panic!("Triangle vertex index out of bounds."),
        }
    }
    fn edge(&self, id: FeatureId) -> (Point<N>, Point<N>, FeatureId, FeatureId) {
        match id.unwrap_edge() {
            0 => (self.a, self.b, FeatureId::Vertex(0), FeatureId::Vertex(1)),
            1 => (self.b, self.c, FeatureId::Vertex(1), FeatureId::Vertex(2)),
            2 => (self.c, self.a, FeatureId::Vertex(2), FeatureId::Vertex(0)),
            _ => panic!("Triangle edge index out of bounds."),
        }
    }

    fn face(&self, id: FeatureId, face: &mut ConvexPolygonalFeature<N>) {
        face.clear();

        if let Some(normal) = self.normal() {
            face.set_feature_id(id);

            match id.unwrap_face() {
                0 => {
                    face.push(self.a, FeatureId::Vertex(0));
                    face.push(self.b, FeatureId::Vertex(1));
                    face.push(self.c, FeatureId::Vertex(2));
                    face.push_edge_feature_id(FeatureId::Edge(0));
                    face.push_edge_feature_id(FeatureId::Edge(1));
                    face.push_edge_feature_id(FeatureId::Edge(2));
                    face.set_normal(normal);
                }
                1 => {
                    face.push(self.a, FeatureId::Vertex(0));
                    face.push(self.c, FeatureId::Vertex(2));
                    face.push(self.b, FeatureId::Vertex(1));
                    face.push_edge_feature_id(FeatureId::Edge(2));
                    face.push_edge_feature_id(FeatureId::Edge(1));
                    face.push_edge_feature_id(FeatureId::Edge(0));
                    face.set_normal(-normal);
                }
                _ => unreachable!(),
            }

            face.recompute_edge_normals();
        } else {
            face.push(self.a, FeatureId::Vertex(0));
            face.set_feature_id(FeatureId::Vertex(0));
        }
    }

    fn normal_cone(&self, feature: FeatureId) -> PolyhedralCone<N> {
        if let Some(normal) = self.normal() {
            match feature {
                FeatureId::Vertex(id2) => {
                    let vtx = self.as_array();
                    let mut generators = SmallVec::new();
                    let id1 = if id2 == 0 { 2 } else { id2 - 1 };
                    let id3 = (id2 + 1) % 3;

                    if let Some(side1) = Unit::try_new(vtx[id2] - vtx[id1], N::default_epsilon()) {
                        generators.push(side1);
                    }
                    generators.push(-normal);
                    if let Some(side2) = Unit::try_new(vtx[id3] - vtx[id2], N::default_epsilon()) {
                        generators.push(side2);
                    }
                    generators.push(normal);

                    // FIXME: is it meaningful not to push the sides if the triangle is degenerate?

                    PolyhedralCone::Span(generators)
                }
                FeatureId::Edge(id1) => {
                    // FIXME: We should be able to do much better here.
                    let id2 = (id1 + 1) % 3;
                    let vtx = self.as_array();
                    let mut generators = SmallVec::new();

                    if let Some(side) = Unit::try_new(vtx[id2] - vtx[id1], N::default_epsilon()) {
                        generators.push(side);
                        generators.push(-normal);
                        generators.push(side);
                        generators.push(normal);
                    } else {
                        // FIXME: is this meaningful?
                        generators.push(-normal);
                        generators.push(normal);
                    }

                    PolyhedralCone::Span(generators)
                }
                FeatureId::Face(0) => PolyhedralCone::HalfLine(normal),
                FeatureId::Face(1) => PolyhedralCone::HalfLine(-normal),
                _ => panic!("Invalid feature ID."),
            }
        } else {
            PolyhedralCone::Full
        }
    }

    fn support_face_toward(
        &self,
        m: &Isometry<N>,
        dir: &Unit<Vector<N>>,
        face: &mut ConvexPolygonalFeature<N>,
    ) {
        let normal = self.scaled_normal();

        if na::dot(&normal, &*dir) >= na::zero() {
            ConvexPolyhedron::<N>::face(self, FeatureId::Face(0), face);
        } else {
            ConvexPolyhedron::<N>::face(self, FeatureId::Face(1), face);
        }
        face.transform_by(m)
    }

    fn support_feature_toward(
        &self,
        transform: &Isometry<N>,
        dir: &Unit<Vector<N>>,
        _angle: N,
        out: &mut ConvexPolygonalFeature<N>,
    ) {
        out.clear();
        // FIXME: actualy find the support feature.
        self.support_face_toward(transform, dir, out)
    }

    fn support_feature_id_toward(&self, local_dir: &Unit<Vector<N>>) -> FeatureId {
        if let Some(normal) = self.normal() {
            let eps: N = na::convert(f64::consts::PI / 180.0);
            let ceps = eps.cos();

            let normal_dot = local_dir.dot(&*normal);
            if normal_dot >= ceps {
                FeatureId::Face(0)
            } else if normal_dot <= -ceps {
                FeatureId::Face(1)
            } else {
                let dot1 = local_dir.dot(&self.a.coords);
                let dot2 = local_dir.dot(&self.b.coords);
                let dot3 = local_dir.dot(&self.c.coords);

                if dot1 > dot2 {
                    if dot1 > dot3 {
                        FeatureId::Vertex(0)
                    } else {
                        FeatureId::Vertex(2)
                    }
                } else if dot2 > dot3 {
                    FeatureId::Vertex(1)
                } else {
                    FeatureId::Vertex(2)
                }
            }
        } else {
            FeatureId::Vertex(0)
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io::IoResult;
use std::io::stdio::{self, StdWriter};
use board::{Board, Edge, Side};
use geom::{Geom, Point, UP, LEFT};
use term::{self, Terminal, StdTerminal};
use term::color::{self, Color};

enum Output<T> {
    Pretty(Box<StdTerminal>),
    Raw(T)
}

fn side_to_color(ty: Option<Side>) -> (Color, Color) {
    match ty {
        Some(Side::In)  => (color::BRIGHT_YELLOW, color::BLACK),
        Some(Side::Out) => (color::BLACK,         color::BRIGHT_WHITE),
        None            => (color::BRIGHT_WHITE,  color::BLACK),
    }
}

struct Printer<'a> {
    output: Output<StdWriter>,
    board: &'a Board
}

impl<'a> Printer<'a> {
    fn new(board: &'a Board) -> Printer<'a> {
        let output = if stdio::stdout_raw().isatty() {
            match term::stdout() {
                Some(t) => Output::Pretty(t),
                None    => Output::Raw(stdio::stdout_raw())
            }
        } else {
            Output::Raw(stdio::stdout_raw())
        };
        Printer { output: output, board: board }
    }

    fn write_pretty(&mut self, ty: Option<Side>, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write(s.as_bytes()));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }
    fn write_pretty_fmt(&mut self, ty: Option<Side>, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write_fmt(fmt));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }
    fn write_plain(&mut self, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write(s.as_bytes()),
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }

    fn write_plain_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write_fmt(fmt),
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }

    fn print(&mut self) -> IoResult<()> {
        let row = self.board.row();
        try!(self.label_row());
        for y in (0 .. row) {
            try!(self.edge_row(y));
            try!(self.cell_row(y));
        }
        try!(self.edge_row(row));
        try!(self.label_row());
        Ok(())
    }

    fn label_row(&mut self) -> IoResult<()> {
        try!(self.write_plain("  "));
        for x in 0 .. self.board.column() {
            try!(self.write_plain_fmt(format_args!(" {:2}", x)));
        }
        try!(self.write_plain("\n"));
        Ok(())
    }

    fn edge_row(&mut self, y: i32) -> IoResult<()> {
        let col = self.board.column();
        try!(self.write_plain("  "));
        for x in (0 .. col) {
            try!(self.corner(Point(y, x)));
            try!(self.edge_h(Point(y, x)));
        }
        try!(self.corner(Point(y, col)));
        try!(self.write_plain("\n"));
        Ok(())
    }

    fn cell_row(&mut self, y: i32) -> IoResult<()> {
        let col = self.board.column();
        try!(self.write_plain_fmt(format_args!("{:2}", y)));
        for x in (0 .. col) {
            try!(self.edge_v(Point(y, x)));
            try!(self.cell(Point(y, x)));
        }
        try!(self.edge_v(Point(y, col)));
        try!(self.write_plain_fmt(format_args!("{:2}\n", y)));
        Ok(())
    }

    fn corner(&mut self, p: Point) -> IoResult<()> {
        let l = p + LEFT;
        let u = p + UP;
        let is_same_all =
            (self.board.edge_h()[p] == Some(Edge::Cross)) &&
            (self.board.edge_h()[l] == Some(Edge::Cross)) &&
            (self.board.edge_v()[p] == Some((Edge::Cross))) &&
            (self.board.edge_v()[u] == Some((Edge::Cross)));

        let ty = if is_same_all {
            self.board.side()[p]
        } else {
            None
        };
        let is_h = self.board.edge_h()[p] == Some(Edge::Line) &&
            self.board.edge_h()[l] == Some(Edge::Line);
        let is_v = self.board.edge_v()[p] == Some(Edge::Line) &&
            self.board.edge_v()[u] == Some(Edge::Line);

        if is_same_all {
            try!(self.write_pretty(ty, "."));
        } else if is_h {
            try!(self.write_pretty(ty, "-"));
        } else if is_v {
            try!(self.write_pretty(ty, "|"));
        } else {
            try!(self.write_pretty(ty, "+"));
        }
        Ok(())
    }

    fn edge_h(&mut self, p: Point) -> IoResult<()> {
        let (s, ty) = match self.board.edge_h()[p] {
            Some(Edge::Cross) => (" ", self.board.side()[p]),
            Some(Edge::Line)  => ("-", None),
            None => ("~", None)
        };
        try!(self.write_pretty_fmt(ty, format_args!("{}{}", s, s)));
        Ok(())
    }

    fn edge_v(&mut self, p: Point) -> IoResult<()> {
        let (s, ty) = match self.board.edge_v()[p] {
            Some(Edge::Cross) => (" ", self.board.side()[p]),
            Some(Edge::Line)  => ("|", None),
            None => ("?", None)
        };
        try!(self.write_pretty(ty, s));
        Ok(())
    }

    fn cell(&mut self, p: Point) -> IoResult<()> {
        let ty = self.board.side()[p];
        match self.board[p] {
            Some(x) => try!(self.write_pretty_fmt(ty, format_args!("{} ", x))),
            None    => try!(self.write_pretty(ty, "  "))
        }
        Ok(())
    }
}

pub fn print(board: &Board) -> IoResult<()> {
    Printer::new(board).print()
}

<commit_msg>pprint: some refactoring<commit_after>use std::fmt;
use std::io::IoResult;
use std::io::stdio::{self, StdWriter};
use board::{Board, Edge, Side};
use geom::{Geom, Point, UP, LEFT};
use term::{self, Terminal, StdTerminal};
use term::color::{self, Color};

enum Output<T> {
    Pretty(Box<StdTerminal>),
    Raw(T)
}

fn side_to_color(ty: Option<Side>) -> (Color, Color) {
    match ty {
        Some(Side::In)  => (color::BRIGHT_YELLOW, color::BLACK),
        Some(Side::Out) => (color::BLACK,         color::BRIGHT_WHITE),
        None            => (color::BRIGHT_WHITE,  color::BLACK),
    }
}

struct Printer<'a> {
    output: Output<StdWriter>
}

impl<'a> Printer<'a> {
    fn new() -> Printer<'a> {
        let output = if stdio::stdout_raw().isatty() {
            match term::stdout() {
                Some(t) => Output::Pretty(t),
                None    => Output::Raw(stdio::stdout_raw())
            }
        } else {
            Output::Raw(stdio::stdout_raw())
        };
        Printer { output: output }
    }

    fn write_pretty(&mut self, ty: Option<Side>, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write(s.as_bytes()));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }
    fn write_pretty_fmt(&mut self, ty: Option<Side>, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write_fmt(fmt));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }
    fn write_plain(&mut self, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write(s.as_bytes()),
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }

    fn write_plain_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write_fmt(fmt),
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }
}

struct Table;
impl Table {
    fn pprint(printer: &mut Printer, board: &Board) -> IoResult<()> {
        let row = board.row();
        try!(LabelRow::pprint(printer, board));
        for y in (0 .. row) {
            try!(EdgeRow::pprint(printer, board, y));
            try!(CellRow::pprint(printer, board, y));
        }
        try!(EdgeRow::pprint(printer, board, row));
        try!(LabelRow::pprint(printer, board));
        Ok(())
    }
}

struct LabelRow;
impl LabelRow {
    fn pprint(printer: &mut Printer, board: &Board) -> IoResult<()> {
        try!(printer.write_plain("  "));
        for x in 0 .. board.column() {
            try!(printer.write_plain_fmt(format_args!(" {:2}", x)));
        }
        try!(printer.write_plain("\n"));
        Ok(())
   }
}

struct EdgeRow;
impl EdgeRow {
    fn pprint(printer: &mut Printer, board: &Board, y: i32) -> IoResult<()> {
        let col = board.column();
        try!(printer.write_plain("  "));
        for x in (0 .. col) {
            try!(Corner::pprint(printer, board, Point(y, x)));
            try!(EdgeH::pprint(printer, board, Point(y, x)));
        }
        try!(Corner::pprint(printer, board, Point(y, col)));
        try!(printer.write_plain("\n"));
        Ok(())
    }
}

struct CellRow;
impl CellRow {
    fn pprint(printer: &mut Printer, board: &Board, y: i32) -> IoResult<()> {
        let col = board.column();
        try!(printer.write_plain_fmt(format_args!("{:2}", y)));
        for x in (0 .. col) {
            try!(EdgeV::pprint(printer, board, Point(y, x)));
            try!(Cell::pprint(printer, board, Point(y, x)));
        }
        try!(EdgeV::pprint(printer, board, Point(y, col)));
        try!(printer.write_plain_fmt(format_args!("{:2}\n", y)));
        Ok(())
    }
}

struct Corner;
impl Corner {
    fn pprint(printer: &mut Printer, board: &Board, p: Point) -> IoResult<()> {
        let l = p + LEFT;
        let u = p + UP;
        let is_same_all =
            (board.edge_h()[p] == Some(Edge::Cross)) &&
            (board.edge_h()[l] == Some(Edge::Cross)) &&
            (board.edge_v()[p] == Some((Edge::Cross))) &&
            (board.edge_v()[u] == Some((Edge::Cross)));

        let ty = if is_same_all {
            board.side()[p]
        } else {
            None
        };
        let is_h = board.edge_h()[p] == Some(Edge::Line) &&
            board.edge_h()[l] == Some(Edge::Line);
        let is_v = board.edge_v()[p] == Some(Edge::Line) &&
            board.edge_v()[u] == Some(Edge::Line);

        if is_same_all {
            try!(printer.write_pretty(ty, "."));
        } else if is_h {
            try!(printer.write_pretty(ty, "-"));
        } else if is_v {
            try!(printer.write_pretty(ty, "|"));
        } else {
            try!(printer.write_pretty(ty, "+"));
        }
        Ok(())
    }
}

struct EdgeH;
impl EdgeH {
    fn pprint(printer: &mut Printer, board: &Board, p: Point) -> IoResult<()> {
        let (s, ty) = match board.edge_h()[p] {
            Some(Edge::Cross) => (" ", board.side()[p]),
            Some(Edge::Line)  => ("-", None),
            None => ("~", None)
        };
        try!(printer.write_pretty_fmt(ty, format_args!("{}{}", s, s)));
        Ok(())
    }
}

struct EdgeV;
impl EdgeV {
    fn pprint(printer: &mut Printer, board: &Board, p: Point) -> IoResult<()> {
        let (s, ty) = match board.edge_v()[p] {
            Some(Edge::Cross) => (" ", board.side()[p]),
            Some(Edge::Line)  => ("|", None),
            None => ("?", None)
        };
        try!(printer.write_pretty(ty, s));
        Ok(())
    }
}

struct Cell;
impl Cell {
    fn pprint(printer: &mut Printer, board: &Board, p: Point) -> IoResult<()> {
        let ty = board.side()[p];
        match board[p] {
            Some(x) => try!(printer.write_pretty_fmt(ty, format_args!("{} ", x))),
            None    => try!(printer.write_pretty(ty, "  "))
        }
        Ok(())
    }
}

pub fn print(board: &Board) -> IoResult<()> {
    Table::pprint(&mut Printer::new(), board)
}

<|endoftext|>


<commit_before>pub struct Column;
<commit_msg>added types to columns<commit_after>use super::types::Types;

pub struct Column {
    col_type: Types
}

impl Column {
    pub fn new(c_type: Types) -> Self {
        Column { col_type: c_type }
    }

    pub fn size(&self) -> u32 {
        self.col_type.size()
    }
}
<|endoftext|>


<commit_before>#![cfg(test)]
use std::cell::RefCell;
use std::rc::Rc;

use alloc::AllocBox;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use js_types::js_var::{JsKey, JsPtrEnum, JsType, JsVar};
use js_types::binding::Binding;

pub fn make_str(s: &str) -> (JsVar, JsPtrEnum, Binding) {
    let var = JsVar::new(JsType::JsPtr);
    let bnd = var.binding.clone();
    (var, JsPtrEnum::JsStr(JsStrStruct::new(s)), bnd)
}

pub fn make_num(i: f64) -> JsVar {
    JsVar::new(JsType::JsNum(i))
}

pub fn make_obj(kvs: Vec<(JsKey, JsVar, Option<JsPtrEnum>)>, heap: Rc<RefCell<AllocBox>>) -> (JsVar, JsPtrEnum, Binding) {
    let var = JsVar::new(JsType::JsPtr);
    let bnd = var.binding.clone();
    (var, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs, &mut *heap.borrow_mut())), bnd)
}

pub fn make_alloc_box() -> Rc<RefCell<AllocBox>> {
    Rc::new(RefCell::new(AllocBox::new()))
}

<commit_msg>Update test_utils to use new JsPtrTag type<commit_after>#![cfg(test)]
use std::cell::RefCell;
use std::rc::Rc;

use alloc::AllocBox;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use js_types::js_var::{JsKey, JsPtrEnum, JsPtrTag, JsType, JsVar};
use js_types::binding::Binding;

pub fn make_str(s: &str) -> (JsVar, JsPtrEnum, Binding) {
    let var = JsVar::new(JsType::JsPtr(JsPtrTag::JsStr));
    let bnd = var.binding.clone();
    (var, JsPtrEnum::JsStr(JsStrStruct::new(s)), bnd)
}

pub fn make_num(i: f64) -> JsVar {
    JsVar::new(JsType::JsNum(i))
}

pub fn make_obj(kvs: Vec<(JsKey, JsVar, Option<JsPtrEnum>)>, heap: Rc<RefCell<AllocBox>>) -> (JsVar, JsPtrEnum, Binding) {
    let var = JsVar::new(JsType::JsPtr(JsPtrTag::JsObj));
    let bnd = var.binding.clone();
    (var, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs, &mut *heap.borrow_mut())), bnd)
}

pub fn make_alloc_box() -> Rc<RefCell<AllocBox>> {
    Rc::new(RefCell::new(AllocBox::new()))
}

<|endoftext|>


<commit_before>use conduit::{Handler, Method};

use cargo_registry::category::{Category, EncodableCategory, EncodableCategoryWithSubcategories};

#[derive(Deserialize)]
struct CategoryList {
    categories: Vec<EncodableCategory>,
    meta: CategoryMeta,
}
#[derive(Deserialize)]
struct CategoryMeta {
    total: i32,
}
#[derive(Deserialize)]
struct GoodCategory {
    category: EncodableCategory,
}
#[derive(Deserialize)]
struct CategoryWithSubcategories {
    category: EncodableCategoryWithSubcategories,
}

#[test]
fn index() {
    let (_b, app, middle) = ::app();
    let mut req = ::req(app.clone(), Method::Get, "/api/v1/categories");

    // List 0 categories if none exist
    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryList = ::json(&mut response);
    assert_eq!(json.categories.len(), 0);
    assert_eq!(json.meta.total, 0);

    // Create a category and a subcategory
    {
        let conn = t!(app.diesel_database.get());
        ::new_category("foo", "foo")
            .create_or_update(&conn)
            .unwrap();
        ::new_category("foo::bar", "foo::bar")
            .create_or_update(&conn)
            .unwrap();
    }

    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryList = ::json(&mut response);

    // Only the top-level categories should be on the page
    assert_eq!(json.categories.len(), 1);
    assert_eq!(json.meta.total, 1);
    assert_eq!(json.categories[0].category, "foo");
}

#[test]
fn show() {
    let (_b, app, middle) = ::app();

    // Return not found if a category doesn't exist
    let mut req = ::req(app.clone(), Method::Get, "/api/v1/categories/foo-bar");
    let response = t_resp!(middle.call(&mut req));
    assert_eq!(response.status.0, 404);

    // Create a category and a subcategory
    {
        let conn = t!(app.diesel_database.get());

        t!(::new_category("Foo Bar", "foo-bar").create_or_update(&conn));
        t!(::new_category("Foo Bar::Baz", "foo-bar::baz").create_or_update(&conn));
    }

    // The category and its subcategories should be in the json
    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryWithSubcategories = ::json(&mut response);
    assert_eq!(json.category.category, "Foo Bar");
    assert_eq!(json.category.slug, "foo-bar");
    assert_eq!(json.category.subcategories.len(), 1);
    assert_eq!(json.category.subcategories[0].category, "Foo Bar::Baz");
}

#[test]
fn update_crate() {
    let (_b, app, middle) = ::app();
    let mut req = ::req(app.clone(), Method::Get, "/api/v1/categories/foo");
    macro_rules! cnt {
        ($req: expr, $cat: expr) => {{
            $req.with_path(&format!("/api/v1/categories/{}", $cat));
            let mut response = ok_resp!(middle.call($req));
            ::json::<GoodCategory>(&mut response).category.crates_cnt as usize
        }}
    }

    let krate = {
        let conn = t!(app.diesel_database.get());
        let user = t!(::new_user("foo").create_or_update(&conn));
        t!(::new_category("cat1", "cat1").create_or_update(&conn));
        t!(::new_category("Category 2", "category-2").create_or_update(&conn));
        ::CrateBuilder::new("foo_crate", user.id).expect_build(&conn)
    };

    // Updating with no categories has no effect
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &[]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Happy path adding one category
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &["cat1"]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Replacing one category with another
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &["category-2"]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 1);

    // Removing one category
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &[]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Adding 2 categories
    Category::update_crate(
        &app.diesel_database.get().unwrap(),
        &krate,
        &["cat1", "category-2"],
    ).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 1);

    // Removing all categories
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &[]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Attempting to add one valid category and one invalid category
    let invalid_categories = Category::update_crate(
        &app.diesel_database.get().unwrap(),
        &krate,
        &["cat1", "catnope"],
    ).unwrap();
    assert_eq!(invalid_categories, vec!["catnope"]);
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Does not add the invalid category to the category list
    // (unlike the behavior of keywords)
    req.with_path("/api/v1/categories");
    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryList = ::json(&mut response);
    assert_eq!(json.categories.len(), 2);
    assert_eq!(json.meta.total, 2);

    // Attempting to add a category by display text; must use slug
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &["Category 2"]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Add a category and its subcategory
    {
        let conn = t!(app.diesel_database.get());
        t!(::new_category("cat1::bar", "cat1::bar").create_or_update(
            &conn,
        ));
        Category::update_crate(&conn, &krate, &["cat1", "cat1::bar"]).unwrap();
    }
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "cat1::bar"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 0);
}

#[test]
fn category_slugs_returns_all_slugs_in_alphabetical_order() {
    let (_b, app, middle) = ::app();
    {
        let conn = app.diesel_database.get().unwrap();
        ::new_category("Foo", "foo").find_or_create(&conn).unwrap();
        ::new_category("Bar", "bar").find_or_create(&conn).unwrap();
    }

    let mut req = ::req(app, Method::Get, "/api/v1/category_slugs");

    #[derive(RustcDecodable, Debug, PartialEq)]
    struct Slug {
        id: String,
        slug: String,
    }

    #[derive(RustcDecodable, Debug, PartialEq)]
    struct Slugs {
        category_slugs: Vec<Slug>,
    }

    let response = ::json(&mut ok_resp!(middle.call(&mut req)));
    let expected_response = Slugs {
        category_slugs: vec![
            Slug {
                id: "bar".into(),
                slug: "bar".into(),
            },
            Slug {
                id: "foo".into(),
                slug: "foo".into(),
            },
        ],
    };
    assert_eq!(expected_response, response);
}
<commit_msg>Switch find_or_create to create_or_update<commit_after>use conduit::{Handler, Method};

use cargo_registry::category::{Category, EncodableCategory, EncodableCategoryWithSubcategories};

#[derive(Deserialize)]
struct CategoryList {
    categories: Vec<EncodableCategory>,
    meta: CategoryMeta,
}
#[derive(Deserialize)]
struct CategoryMeta {
    total: i32,
}
#[derive(Deserialize)]
struct GoodCategory {
    category: EncodableCategory,
}
#[derive(Deserialize)]
struct CategoryWithSubcategories {
    category: EncodableCategoryWithSubcategories,
}

#[test]
fn index() {
    let (_b, app, middle) = ::app();
    let mut req = ::req(app.clone(), Method::Get, "/api/v1/categories");

    // List 0 categories if none exist
    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryList = ::json(&mut response);
    assert_eq!(json.categories.len(), 0);
    assert_eq!(json.meta.total, 0);

    // Create a category and a subcategory
    {
        let conn = t!(app.diesel_database.get());
        ::new_category("foo", "foo")
            .create_or_update(&conn)
            .unwrap();
        ::new_category("foo::bar", "foo::bar")
            .create_or_update(&conn)
            .unwrap();
    }

    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryList = ::json(&mut response);

    // Only the top-level categories should be on the page
    assert_eq!(json.categories.len(), 1);
    assert_eq!(json.meta.total, 1);
    assert_eq!(json.categories[0].category, "foo");
}

#[test]
fn show() {
    let (_b, app, middle) = ::app();

    // Return not found if a category doesn't exist
    let mut req = ::req(app.clone(), Method::Get, "/api/v1/categories/foo-bar");
    let response = t_resp!(middle.call(&mut req));
    assert_eq!(response.status.0, 404);

    // Create a category and a subcategory
    {
        let conn = t!(app.diesel_database.get());

        t!(::new_category("Foo Bar", "foo-bar").create_or_update(&conn));
        t!(::new_category("Foo Bar::Baz", "foo-bar::baz").create_or_update(&conn));
    }

    // The category and its subcategories should be in the json
    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryWithSubcategories = ::json(&mut response);
    assert_eq!(json.category.category, "Foo Bar");
    assert_eq!(json.category.slug, "foo-bar");
    assert_eq!(json.category.subcategories.len(), 1);
    assert_eq!(json.category.subcategories[0].category, "Foo Bar::Baz");
}

#[test]
fn update_crate() {
    let (_b, app, middle) = ::app();
    let mut req = ::req(app.clone(), Method::Get, "/api/v1/categories/foo");
    macro_rules! cnt {
        ($req: expr, $cat: expr) => {{
            $req.with_path(&format!("/api/v1/categories/{}", $cat));
            let mut response = ok_resp!(middle.call($req));
            ::json::<GoodCategory>(&mut response).category.crates_cnt as usize
        }}
    }

    let krate = {
        let conn = t!(app.diesel_database.get());
        let user = t!(::new_user("foo").create_or_update(&conn));
        t!(::new_category("cat1", "cat1").create_or_update(&conn));
        t!(::new_category("Category 2", "category-2").create_or_update(&conn));
        ::CrateBuilder::new("foo_crate", user.id).expect_build(&conn)
    };

    // Updating with no categories has no effect
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &[]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Happy path adding one category
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &["cat1"]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Replacing one category with another
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &["category-2"]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 1);

    // Removing one category
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &[]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Adding 2 categories
    Category::update_crate(
        &app.diesel_database.get().unwrap(),
        &krate,
        &["cat1", "category-2"],
    ).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 1);

    // Removing all categories
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &[]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Attempting to add one valid category and one invalid category
    let invalid_categories = Category::update_crate(
        &app.diesel_database.get().unwrap(),
        &krate,
        &["cat1", "catnope"],
    ).unwrap();
    assert_eq!(invalid_categories, vec!["catnope"]);
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Does not add the invalid category to the category list
    // (unlike the behavior of keywords)
    req.with_path("/api/v1/categories");
    let mut response = ok_resp!(middle.call(&mut req));
    let json: CategoryList = ::json(&mut response);
    assert_eq!(json.categories.len(), 2);
    assert_eq!(json.meta.total, 2);

    // Attempting to add a category by display text; must use slug
    Category::update_crate(&app.diesel_database.get().unwrap(), &krate, &["Category 2"]).unwrap();
    assert_eq!(cnt!(&mut req, "cat1"), 0);
    assert_eq!(cnt!(&mut req, "category-2"), 0);

    // Add a category and its subcategory
    {
        let conn = t!(app.diesel_database.get());
        t!(::new_category("cat1::bar", "cat1::bar").create_or_update(
            &conn,
        ));
        Category::update_crate(&conn, &krate, &["cat1", "cat1::bar"]).unwrap();
    }
    assert_eq!(cnt!(&mut req, "cat1"), 1);
    assert_eq!(cnt!(&mut req, "cat1::bar"), 1);
    assert_eq!(cnt!(&mut req, "category-2"), 0);
}

#[test]
fn category_slugs_returns_all_slugs_in_alphabetical_order() {
    let (_b, app, middle) = ::app();
    {
        let conn = app.diesel_database.get().unwrap();
        ::new_category("Foo", "foo").create_or_update(&conn).unwrap();
        ::new_category("Bar", "bar").create_or_update(&conn).unwrap();
    }

    let mut req = ::req(app, Method::Get, "/api/v1/category_slugs");

    #[derive(RustcDecodable, Debug, PartialEq)]
    struct Slug {
        id: String,
        slug: String,
    }

    #[derive(RustcDecodable, Debug, PartialEq)]
    struct Slugs {
        category_slugs: Vec<Slug>,
    }

    let response = ::json(&mut ok_resp!(middle.call(&mut req)));
    let expected_response = Slugs {
        category_slugs: vec![
            Slug {
                id: "bar".into(),
                slug: "bar".into(),
            },
            Slug {
                id: "foo".into(),
                slug: "foo".into(),
            },
        ],
    };
    assert_eq!(expected_response, response);
}
<|endoftext|>


<commit_before>//! TODO Documentation
use std::{fmt, panic};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_key_state, wlr_keyboard, wlr_keyboard_get_modifiers,
                  wlr_keyboard_led, wlr_keyboard_led_update, wlr_keyboard_modifier,
                  wlr_keyboard_set_keymap};

use xkbcommon::xkb::Keymap;

use InputDevice;

/// The maximum number of keycodes stored in a `Keyboard`.
pub const WLR_KEYBOARD_KEYS_CAP: usize = 32;

pub type KeyState = wlr_key_state;

#[derive(Debug)]
pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

#[derive(Debug)]
pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                Some(Keyboard { liveliness: Some(Rc::new(AtomicBool::new(false))),
                                device: InputDevice::from_ptr(device),
                                keyboard })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr() }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    /// Update the LED lights using the provided bitmap.
    ///
    /// 1 means one, 0 means off.
    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    /// Get the modifiers that are currently pressed on the keyboard.
    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe {
            KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard))
        }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl KeyboardHandle {
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::DoubleUpgrade)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut keyboard))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}
<commit_msg>Added Keyboard::get_{keymap,xkb_state}<commit_after>//! TODO Documentation
use std::{fmt, panic};
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_key_state, wlr_keyboard, wlr_keyboard_get_modifiers,
                  wlr_keyboard_led, wlr_keyboard_led_update, wlr_keyboard_modifier,
                  wlr_keyboard_set_keymap};

use xkbcommon::xkb::{self, Keymap};

use InputDevice;

/// The maximum number of keycodes stored in a `Keyboard`.
pub const WLR_KEYBOARD_KEYS_CAP: usize = 32;

pub type KeyState = wlr_key_state;

pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard,
    /// The keymap used by wlroots.
    /// Stored here so that we can ensure you can only borrow the keymap
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    keymap: Option<ManuallyDrop<Keymap>>,
    /// The keyboard state used by wlroots.
    /// Stored here so that we can ensure you can only borrow the state
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    #[allow(dead_code)]
    xkb_state: Option<ManuallyDrop<xkb::State>>
}

pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard,
    /// The keymap used by wlroots.
    /// Stored here so that we can ensure you can only borrow the keymap
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    #[allow(dead_code)]
    keymap: Option<ManuallyDrop<Keymap>>,
    /// The keyboard state used by wlroots.
    /// Stored here so that we can ensure you can only borrow the state
    /// as long as the keyboard.
    ///
    /// NOTE We have it marked as manually drop because otherwise
    /// we'd unref it twice (once here and again in wlroots).
    #[allow(dead_code)]
    xkb_state: Option<ManuallyDrop<xkb::State>>
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                Some(Keyboard { liveliness: Some(Rc::new(AtomicBool::new(false))),
                                device: InputDevice::from_ptr(device),
                                keyboard,
                                keymap: None,
                                xkb_state: None })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr(),
                   keymap: None,
                   xkb_state: None }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    /// Get the XKB keymap associated with this `Keyboard`.
    pub fn get_keymap(&mut self) -> Option<&Keymap> {
        unsafe {
            let keymap_ptr = (*self.keyboard).keymap as *mut _;
            if keymap_ptr.is_null() {
                None
            } else {
                self.keymap = Some(ManuallyDrop::new(Keymap::from_raw_ptr(keymap_ptr)));
                self.keymap.as_ref().map(Deref::deref)
            }
        }
    }

    /// Get the XKB state associated with this `Keyboard`.
    pub fn get_xkb_state(&mut self) -> Option<&xkb::State> {
        unsafe {
            let xkb_state_ptr = (*self.keyboard).xkb_state as *mut _;
            if xkb_state_ptr.is_null() {
                None
            } else {
                self.xkb_state = Some(ManuallyDrop::new(xkb::State::from_raw_ptr(xkb_state_ptr)));
                self.xkb_state.as_ref().map(Deref::deref)
            }
        }
    }

    /// Update the LED lights using the provided bitmap.
    ///
    /// 1 means one, 0 means off.
    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    /// Get the modifiers that are currently pressed on the keyboard.
    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe {
            KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard))
        }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard,
                         keymap: None,
                         xkb_state: None }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl fmt::Debug for Keyboard {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f,
               "Keyboard {{ device: {:?}, keyboard: {:?} }}",
               self.device, self.keyboard)
    }
}

impl KeyboardHandle {
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::DoubleUpgrade)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut keyboard))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

impl fmt::Debug for KeyboardHandle {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f,
               "Keyboard {{ device: {:?}, keyboard: {:?} }}",
               self.device, self.keyboard)
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}
<|endoftext|>