<commit_before>#![warn(trivial_casts, trivial_numeric_casts, unused_import_braces, unused_qualifications)]

extern crate cocoa;
extern crate core_foundation;
extern crate metal_sys;
#[macro_use]
extern crate objc;

#[macro_use]
mod raw;

#[macro_use]
mod internal;

mod argument;
mod array_type;
mod blit_command_encoder;
mod buffer;
mod command_buffer;
mod command_queue;
mod compile_options;
mod compute_command_encoder;
mod constants;
mod device;
mod drawable;
mod error;
mod function;
mod library;
mod objc_bringup;
mod parallel_render_command_encoder;
mod render_command_encoder;
mod render_pass_attachment_descriptor;
mod render_pass_color_attachment_descriptor;
mod render_pass_depth_attachment_descriptor;
mod render_pass_descriptor;
mod render_pass_stencil_attachment_descriptor;
mod resource;
mod struct_member;
mod struct_type;
mod texture;
mod value_types;

pub mod sys {
    pub use metal_sys::*;
}

pub use argument::{Argument, ArgumentAccess, ArgumentType, DataType};
pub use array_type::ArrayType;
pub use blit_command_encoder::BlitCommandEncoder;
pub use buffer::Buffer;
pub use command_buffer::{CommandBuffer, CommandBufferError};
pub use command_queue::{CommandQueue, CommandQueueError};
pub use compile_options::{CompileOptions, LanguageVersion, PreprocessorMacroValue,
                          SpecificLanguageVersion};
pub use compute_command_encoder::ComputeCommandEncoder;
pub use constants::{CompareFunction, PipelineOption, PixelFormat};
pub use device::{Device, DeviceError, FeatureSet};
pub use drawable::Drawable;
pub use error::NSError;
pub use function::{Function, FunctionType};
pub use library::{Library, LibraryError, LibraryErrorType};
pub use parallel_render_command_encoder::ParallelRenderCommandEncoder;
pub use raw::{AsRaw, FromRaw, FromRawError, IntoRaw};
pub use render_command_encoder::RenderCommandEncoder;
pub use render_pass_attachment_descriptor::{LoadAction, RenderPassAttachmentDescriptor,
                                            StoreAction};
pub use render_pass_color_attachment_descriptor::{RenderPassColorAttachmentDescriptor,
                                                  RenderPassColorAttachmentDescriptorArray};
pub use render_pass_depth_attachment_descriptor::RenderPassDepthAttachmentDescriptor;
pub use render_pass_descriptor::RenderPassDescriptor;
pub use render_pass_stencil_attachment_descriptor::RenderPassStencilAttachmentDescriptor;
pub use resource::{CpuCacheMode, PurgeableState, Resource, StorageMode};
pub use struct_member::StructMember;
pub use struct_type::StructType;
pub use texture::{Texture, TextureType, TextureUsage};
pub use value_types::{ClearColor, Origin, Region, ScissorRect, Size, Viewport};
<commit_msg>Export stubs<commit_after>#![warn(trivial_casts, trivial_numeric_casts, unused_import_braces, unused_qualifications)]

extern crate cocoa;
extern crate core_foundation;
extern crate metal_sys;
#[macro_use]
extern crate objc;

#[macro_use]
mod raw;

#[macro_use]
mod internal;

mod argument;
mod array_type;
mod blit_command_encoder;
mod buffer;
mod command_buffer;
mod command_queue;
mod compile_options;
mod compute_command_encoder;
mod constants;
mod device;
mod drawable;
mod error;
mod function;
mod library;
mod objc_bringup;
mod parallel_render_command_encoder;
mod render_command_encoder;
mod render_pass_attachment_descriptor;
mod render_pass_color_attachment_descriptor;
mod render_pass_depth_attachment_descriptor;
mod render_pass_descriptor;
mod render_pass_stencil_attachment_descriptor;
mod resource;
mod struct_member;
mod struct_type;
mod texture;
mod value_types;

pub mod sys {
    pub use metal_sys::*;
}

pub use argument::{Argument, ArgumentAccess, ArgumentType, DataType};
pub use array_type::ArrayType;
pub use blit_command_encoder::BlitCommandEncoder;
pub use buffer::Buffer;
pub use command_buffer::{CommandBuffer, CommandBufferError};
pub use command_queue::{CommandQueue, CommandQueueError};
pub use compile_options::{CompileOptions, LanguageVersion, PreprocessorMacroValue,
                          SpecificLanguageVersion};
pub use compute_command_encoder::ComputeCommandEncoder;
pub use constants::{CompareFunction, PipelineOption, PixelFormat};
pub use device::{Device, DeviceError, FeatureSet};
pub use drawable::Drawable;
pub use error::NSError;
pub use function::{Function, FunctionType};
pub use library::{Library, LibraryError, LibraryErrorType};
pub use parallel_render_command_encoder::ParallelRenderCommandEncoder;
pub use raw::{AsRaw, FromRaw, FromRawError, IntoRaw};
pub use render_command_encoder::RenderCommandEncoder;
pub use render_pass_attachment_descriptor::{LoadAction, RenderPassAttachmentDescriptor,
                                            StoreAction};
pub use render_pass_color_attachment_descriptor::{RenderPassColorAttachmentDescriptor,
                                                  RenderPassColorAttachmentDescriptorArray};
pub use render_pass_depth_attachment_descriptor::RenderPassDepthAttachmentDescriptor;
pub use render_pass_descriptor::RenderPassDescriptor;
pub use render_pass_stencil_attachment_descriptor::RenderPassStencilAttachmentDescriptor;
pub use resource::{CpuCacheMode, PurgeableState, Resource, ResourceOptions, StorageMode};
pub use struct_member::StructMember;
pub use struct_type::StructType;
pub use texture::{Texture, TextureDescriptor, TextureType, TextureUsage};
pub use value_types::{ClearColor, Origin, Region, ScissorRect, Size, Viewport};
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::winbase::STD_INPUT_HANDLE
    };
    unsafe {
        let handle = kernel32::GetStdHandle(handle);
        let mut out = 0;
        kernel32::GetConsoleMode(handle, &mut out) != 0
    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_test() {
        assert!(is(Stream::Stdout))
    }
}
<commit_msg>test all three streams<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::winbase::STD_INPUT_HANDLE
    };
    unsafe {
        let handle = kernel32::GetStdHandle(handle);
        let mut out = 0;
        kernel32::GetConsoleMode(handle, &mut out) != 0
    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::STD_INPUT_HANDLE
    };

    unsafe {
        let std_handle = kernel32::GetStdHandle(handle);
        match stream {
            Stream::Stdin => {
                let mut out = 0;
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                winapi::INVALID_HANDLE_VALUE == std_handle,
                kernel32::GetConsoleMode(std_handle, &mut out),
                kernel32::GetLastError());
                kernel32::GetConsoleMode(std_handle, &mut out) != 0
            },
            _ => {
                let mut buffer_info = unsafe { ::std::mem::uninitialized() };
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                winapi::INVALID_HANDLE_VALUE == std_handle,
                kernel32::GetConsoleMode(std_handle, &mut buffer_info),
                kernel32::GetLastError());
                kernel32::GetConsoleMode(std_handle, &mut buffer_info) != 0
            }
        }

    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<commit_msg>actually use GetConsoleScreenBufferInfo<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::STD_INPUT_HANDLE
    };

    unsafe {
        let std_handle = kernel32::GetStdHandle(handle);
        match stream {
            Stream::Stdin => {
                let mut out = 0;
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                winapi::INVALID_HANDLE_VALUE == std_handle,
                kernel32::GetConsoleMode(std_handle, &mut out),
                kernel32::GetLastError());
                kernel32::GetConsoleMode(std_handle, &mut out) != 0
            },
            _ => {
                let mut buffer_info = unsafe { ::std::mem::uninitialized() };
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                winapi::INVALID_HANDLE_VALUE == std_handle,
                kernel32::GetConsoleScreenBufferInfo(std_handle, &mut buffer_info),
                kernel32::GetLastError());
                kernel32::GetConsoleScreenBufferInfo(std_handle, &mut buffer_info) != 0
            }
        }

    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<|endoftext|>


<commit_before>#![doc(
    html_logo_url = "https://cdn.rawgit.com/urschrei/polylabel-rs/7a07336e85572eb5faaf0657c2383d7de5620cd8/ell.svg",
    html_root_url = "https://urschrei.github.io/polylabel-rs/"
)]
//! This crate provides a Rust implementation of the [Polylabel](https://github.com/mapbox/polylabel) algorithm
//! for finding the optimum position of a polygon label.
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::iter::Sum;

extern crate num_traits;
use self::num_traits::{Float, FromPrimitive, Signed};

extern crate geo;
use self::geo::prelude::*;
use self::geo::{Point, Polygon};

mod ffi;
pub use ffi::{polylabel_ffi, Array, Position, WrapperArray};

#[doc(hidden)]
#[allow(dead_code)]
pub extern "C" fn spare() {
    println!("");
}

/// Represention of a Quadtree node's cells. A node contains four Qcells.
#[derive(Debug)]
struct Qcell<T>
where
    T: Float + Signed,
{
    // The cell's centroid
    centroid: Point<T>,
    // Half of the parent node's extent
    extent: T,
    // Distance from centroid to polygon
    distance: T,
    // Maximum distance to polygon within a cell
    max_distance: T,
}

impl<T> Qcell<T>
where
    T: Float + Signed,
{
    fn new(x: T, y: T, h: T, distance: T, max_distance: T) -> Qcell<T> {
        Qcell {
            centroid: Point::new(x, y),
            extent: h,
            distance,
            max_distance,
        }
    }
}

impl<T> Ord for Qcell<T>
where
    T: Float + Signed,
{
    fn cmp(&self, other: &Qcell<T>) -> std::cmp::Ordering {
        self.max_distance.partial_cmp(&other.max_distance).unwrap()
    }
}
impl<T> PartialOrd for Qcell<T>
where
    T: Float + Signed,
{
    fn partial_cmp(&self, other: &Qcell<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl<T> Eq for Qcell<T> where T: Float + Signed {}
impl<T> PartialEq for Qcell<T>
where
    T: Float + Signed,
{
    fn eq(&self, other: &Qcell<T>) -> bool
    where
        T: Float,
    {
        self.max_distance == other.max_distance
    }
}

/// Signed distance from a Qcell's centroid to a Polygon's outline
/// Returned value is negative if the point is outside the polygon's exterior ring
fn signed_distance<T>(x: &T, y: &T, polygon: &Polygon<T>) -> T
where
    T: Float,
{
    let point = Point::new(*x, *y);
    let inside = polygon.contains(&point);
    // Use LineString distance, because Polygon distance returns 0.0 for inside
    let distance = point.euclidean_distance(&polygon.exterior);
    if inside {
        distance
    } else {
        -distance
    }
}

/// Add a new Quadtree node made up of four `Qcell`s to the binary heap
fn add_quad<T>(
    mpq: &mut BinaryHeap<Qcell<T>>,
    cell: &Qcell<T>,
    new_height: &T,
    polygon: &Polygon<T>,
) where
    T: Float + Signed,
{
    let two = T::one() + T::one();
    let centroid_x = cell.centroid.x();
    let centroid_y = cell.centroid.y();
    for combo in &[
        (centroid_x - *new_height, centroid_y - *new_height),
        (centroid_x + *new_height, centroid_y - *new_height),
        (centroid_x - *new_height, centroid_y + *new_height),
        (centroid_x + *new_height, centroid_y + *new_height),
    ] {
        let mut new_dist = signed_distance(&combo.0, &combo.1, polygon);
        mpq.push(Qcell::new(
            combo.0,
            combo.1,
            *new_height,
            new_dist,
            new_dist + *new_height * two.sqrt(),
        ));
    }
}

/// Calculate a Polygon's ideal label position by calculating its ✨pole of inaccessibility✨
///
/// The calculation uses an [iterative grid-based algorithm](https://github.com/mapbox/polylabel#how-the-algorithm-works).
///
/// # Examples
///
/// ```
/// use polylabel::polylabel;
/// extern crate geo;
/// use self::geo::{Point, LineString, Polygon};
///
/// // An approximate `L` shape
/// let coords = vec![
///    (0.0, 0.0),
///    (4.0, 0.0),
///    (4.0, 1.0),
///    (1.0, 1.0),
///    (1.0, 4.0),
///    (0.0, 4.0),
///    (0.0, 0.0)];
///
/// let poly = Polygon::new(coords.into(), vec![]);
///
/// // Its centroid lies outside the polygon
/// assert_eq!(poly.centroid(), Point::new(1.3571428571428572, 1.3571428571428572));
///
/// let label_position = polylabel(&poly, &1.0);
/// // Optimum label position is inside the polygon
/// assert_eq!(label_position, Point::new(0.5625, 0.5625));
/// ```
///
pub fn polylabel<T>(polygon: &Polygon<T>, tolerance: &T) -> Point<T>
where
    T: Float + FromPrimitive + Signed + Sum,
{
    // special case for degenerate polygons
    if polygon.area() == T::zero() {
        return Point::new(T::zero(), T::zero());
    }
    let two = T::one() + T::one();
    // Initial best cell values
    let centroid = polygon.centroid().unwrap();
    let bbox = polygon.bounding_rect().unwrap();
    let width = bbox.max.x - bbox.min.x;
    let height = bbox.max.y - bbox.min.y;
    let cell_size = width.min(height);
    // Special case for degenerate polygons
    if cell_size == T::zero() {
        return Point::new(bbox.min.x, bbox.min.y);
    }
    let mut h = cell_size / two;
    let distance = signed_distance(&centroid.x(), &centroid.y(), polygon);
    let max_distance = distance + T::zero() * two.sqrt();

    let mut best_cell = Qcell::new(
        centroid.x(),
        centroid.y(),
        T::zero(),
        distance,
        max_distance,
    );

    // special case for rectangular polygons
    let bbox_cell_dist = signed_distance(
        &(bbox.min.x + width / two),
        &(bbox.min.y + height / two),
        polygon,
    );
    let bbox_cell = Qcell {
        centroid: Point::new(bbox.min.x + width / two, bbox.min.y + height / two),
        extent: T::zero(),
        distance: bbox_cell_dist,
        max_distance: bbox_cell_dist + T::zero() * two.sqrt(),
    };

    if bbox_cell.distance > best_cell.distance {
        best_cell = bbox_cell;
    }

    // Priority queue
    let mut cell_queue: BinaryHeap<Qcell<T>> = BinaryHeap::new();
    // Build an initial quadtree node, which covers the Polygon
    let mut x = bbox.min.x;
    let mut y;
    while x < bbox.max.x {
        y = bbox.min.y;
        while y < bbox.max.y {
            let latest_dist = signed_distance(&(x + h), &(y + h), polygon);
            cell_queue.push(Qcell {
                centroid: Point::new(x + h, y + h),
                extent: h,
                distance: latest_dist,
                max_distance: latest_dist + h * two.sqrt(),
            });
            y = y + cell_size;
        }
        x = x + cell_size;
    }
    // Now try to find better solutions
    while !cell_queue.is_empty() {
        let cell = cell_queue.pop().unwrap();
        // Update the best cell if we find a cell with greater distance
        if cell.distance > best_cell.distance {
            best_cell.centroid = Point::new(cell.centroid.x(), cell.centroid.y());
            best_cell.extent = cell.extent;
            best_cell.distance = cell.distance;
            best_cell.max_distance = cell.max_distance;
        }
        // Bail out of this iteration if we can't find a better solution
        if cell.max_distance - best_cell.distance <= *tolerance {
            continue;
        }
        // Otherwise, add a new quadtree node and start again
        h = cell.extent / two;
        add_quad(&mut cell_queue, &cell, &h, polygon);
    }
    // We've exhausted the queue, so return the best solution we've found
    Point::new(best_cell.centroid.x(), best_cell.centroid.y())
}

#[cfg(test)]
mod tests {
    use super::{polylabel, Qcell};
    use geo::prelude::*;
    use geo::{Point, Polygon};
    use std::collections::BinaryHeap;
    #[test]
    // polygons are those used in Shapely's tests
    fn test_polylabel() {
        let coords = include!("poly1.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &10.000);
        assert_eq!(res, Point::new(59.35615556364569, 121.83919629746435));
    }
    #[test]
    // does a concave polygon contain the calculated point?
    // relevant because the centroid lies outside the polygon in this case
    fn test_concave() {
        let coords = include!("poly2.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &1.0);
        assert!(poly.contains(&res));
    }
    #[test]
    fn test_london() {
        let coords = include!("poly3.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &0.001);
        assert_eq!(res, Point::new(-0.45556816445920356, 51.54848888202887));
    }
    #[test]
    fn polygon_l_test() {
        // an L shape
        let coords = vec![
            (0.0, 0.0),
            (4.0, 0.0),
            (4.0, 1.0),
            (1.0, 1.0),
            (1.0, 4.0),
            (0.0, 4.0),
            (0.0, 0.0),
        ];
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &0.10);
        assert_eq!(res, Point::new(0.5625, 0.5625));
    }
    #[test]
    fn degenerate_polygon_test() {
        let a_coords = vec![(0.0, 0.0), (1.0, 0.0), (2.0, 0.0), (0.0, 0.0)];
        let a_poly = Polygon::new(a_coords.into(), vec![]);
        let a_res = polylabel(&a_poly, &1.0);
        assert_eq!(a_res, Point::new(0.0, 0.0));
    }
    #[test]
    fn degenerate_polygon_test_2() {
        let b_coords = vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)];
        let b_poly = Polygon::new(b_coords.into(), vec![]);
        let b_res = polylabel(&b_poly, &1.0);
        assert_eq!(b_res, Point::new(0.0, 0.0));
    }
    #[test]
    // Is our priority queue behaving as it should?
    fn test_queue() {
        let a = Qcell {
            centroid: Point::new(1.0, 2.0),
            extent: 3.0,
            distance: 4.0,
            max_distance: 8.0,
        };
        let b = Qcell {
            centroid: Point::new(1.0, 2.0),
            extent: 3.0,
            distance: 4.0,
            max_distance: 7.0,
        };
        let c = Qcell {
            centroid: Point::new(1.0, 2.0),
            extent: 3.0,
            distance: 4.0,
            max_distance: 9.0,
        };
        let mut v = vec![];
        v.push(a);
        v.push(b);
        v.push(c);
        let mut q = BinaryHeap::from(v);
        assert_eq!(q.pop().unwrap().max_distance, 9.0);
        assert_eq!(q.pop().unwrap().max_distance, 8.0);
        assert_eq!(q.pop().unwrap().max_distance, 7.0);
    }
}
<commit_msg>2018 edition fixes<commit_after>#![doc(
    html_logo_url = "https://cdn.rawgit.com/urschrei/polylabel-rs/7a07336e85572eb5faaf0657c2383d7de5620cd8/ell.svg",
    html_root_url = "https://urschrei.github.io/polylabel-rs/"
)]
//! This crate provides a Rust implementation of the [Polylabel](https://github.com/mapbox/polylabel) algorithm
//! for finding the optimum position of a polygon label.
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::iter::Sum;

extern crate num_traits;
use self::num_traits::{Float, FromPrimitive, Signed};

extern crate geo;
use self::geo::prelude::*;
use self::geo::{Point, Polygon};

mod ffi;
pub use crate::ffi::{polylabel_ffi, Array, Position, WrapperArray};

#[doc(hidden)]
#[allow(dead_code)]
pub extern "C" fn spare() {
    println!("");
}

/// Represention of a Quadtree node's cells. A node contains four Qcells.
#[derive(Debug)]
struct Qcell<T>
where
    T: Float + Signed,
{
    // The cell's centroid
    centroid: Point<T>,
    // Half of the parent node's extent
    extent: T,
    // Distance from centroid to polygon
    distance: T,
    // Maximum distance to polygon within a cell
    max_distance: T,
}

impl<T> Qcell<T>
where
    T: Float + Signed,
{
    fn new(x: T, y: T, h: T, distance: T, max_distance: T) -> Qcell<T> {
        Qcell {
            centroid: Point::new(x, y),
            extent: h,
            distance,
            max_distance,
        }
    }
}

impl<T> Ord for Qcell<T>
where
    T: Float + Signed,
{
    fn cmp(&self, other: &Qcell<T>) -> std::cmp::Ordering {
        self.max_distance.partial_cmp(&other.max_distance).unwrap()
    }
}
impl<T> PartialOrd for Qcell<T>
where
    T: Float + Signed,
{
    fn partial_cmp(&self, other: &Qcell<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl<T> Eq for Qcell<T> where T: Float + Signed {}
impl<T> PartialEq for Qcell<T>
where
    T: Float + Signed,
{
    fn eq(&self, other: &Qcell<T>) -> bool
    where
        T: Float,
    {
        self.max_distance == other.max_distance
    }
}

/// Signed distance from a Qcell's centroid to a Polygon's outline
/// Returned value is negative if the point is outside the polygon's exterior ring
fn signed_distance<T>(x: &T, y: &T, polygon: &Polygon<T>) -> T
where
    T: Float,
{
    let point = Point::new(*x, *y);
    let inside = polygon.contains(&point);
    // Use LineString distance, because Polygon distance returns 0.0 for inside
    let distance = point.euclidean_distance(&polygon.exterior);
    if inside {
        distance
    } else {
        -distance
    }
}

/// Add a new Quadtree node made up of four `Qcell`s to the binary heap
fn add_quad<T>(
    mpq: &mut BinaryHeap<Qcell<T>>,
    cell: &Qcell<T>,
    new_height: &T,
    polygon: &Polygon<T>,
) where
    T: Float + Signed,
{
    let two = T::one() + T::one();
    let centroid_x = cell.centroid.x();
    let centroid_y = cell.centroid.y();
    for combo in &[
        (centroid_x - *new_height, centroid_y - *new_height),
        (centroid_x + *new_height, centroid_y - *new_height),
        (centroid_x - *new_height, centroid_y + *new_height),
        (centroid_x + *new_height, centroid_y + *new_height),
    ] {
        let mut new_dist = signed_distance(&combo.0, &combo.1, polygon);
        mpq.push(Qcell::new(
            combo.0,
            combo.1,
            *new_height,
            new_dist,
            new_dist + *new_height * two.sqrt(),
        ));
    }
}

/// Calculate a Polygon's ideal label position by calculating its ✨pole of inaccessibility✨
///
/// The calculation uses an [iterative grid-based algorithm](https://github.com/mapbox/polylabel#how-the-algorithm-works).
///
/// # Examples
///
/// ```
/// use polylabel::polylabel;
/// extern crate geo;
/// use self::geo::{Point, LineString, Polygon};
///
/// // An approximate `L` shape
/// let coords = vec![
///    (0.0, 0.0),
///    (4.0, 0.0),
///    (4.0, 1.0),
///    (1.0, 1.0),
///    (1.0, 4.0),
///    (0.0, 4.0),
///    (0.0, 0.0)];
///
/// let poly = Polygon::new(coords.into(), vec![]);
///
/// // Its centroid lies outside the polygon
/// assert_eq!(poly.centroid(), Point::new(1.3571428571428572, 1.3571428571428572));
///
/// let label_position = polylabel(&poly, &1.0);
/// // Optimum label position is inside the polygon
/// assert_eq!(label_position, Point::new(0.5625, 0.5625));
/// ```
///
pub fn polylabel<T>(polygon: &Polygon<T>, tolerance: &T) -> Point<T>
where
    T: Float + FromPrimitive + Signed + Sum,
{
    // special case for degenerate polygons
    if polygon.area() == T::zero() {
        return Point::new(T::zero(), T::zero());
    }
    let two = T::one() + T::one();
    // Initial best cell values
    let centroid = polygon.centroid().unwrap();
    let bbox = polygon.bounding_rect().unwrap();
    let width = bbox.max.x - bbox.min.x;
    let height = bbox.max.y - bbox.min.y;
    let cell_size = width.min(height);
    // Special case for degenerate polygons
    if cell_size == T::zero() {
        return Point::new(bbox.min.x, bbox.min.y);
    }
    let mut h = cell_size / two;
    let distance = signed_distance(&centroid.x(), &centroid.y(), polygon);
    let max_distance = distance + T::zero() * two.sqrt();

    let mut best_cell = Qcell::new(
        centroid.x(),
        centroid.y(),
        T::zero(),
        distance,
        max_distance,
    );

    // special case for rectangular polygons
    let bbox_cell_dist = signed_distance(
        &(bbox.min.x + width / two),
        &(bbox.min.y + height / two),
        polygon,
    );
    let bbox_cell = Qcell {
        centroid: Point::new(bbox.min.x + width / two, bbox.min.y + height / two),
        extent: T::zero(),
        distance: bbox_cell_dist,
        max_distance: bbox_cell_dist + T::zero() * two.sqrt(),
    };

    if bbox_cell.distance > best_cell.distance {
        best_cell = bbox_cell;
    }

    // Priority queue
    let mut cell_queue: BinaryHeap<Qcell<T>> = BinaryHeap::new();
    // Build an initial quadtree node, which covers the Polygon
    let mut x = bbox.min.x;
    let mut y;
    while x < bbox.max.x {
        y = bbox.min.y;
        while y < bbox.max.y {
            let latest_dist = signed_distance(&(x + h), &(y + h), polygon);
            cell_queue.push(Qcell {
                centroid: Point::new(x + h, y + h),
                extent: h,
                distance: latest_dist,
                max_distance: latest_dist + h * two.sqrt(),
            });
            y = y + cell_size;
        }
        x = x + cell_size;
    }
    // Now try to find better solutions
    while !cell_queue.is_empty() {
        let cell = cell_queue.pop().unwrap();
        // Update the best cell if we find a cell with greater distance
        if cell.distance > best_cell.distance {
            best_cell.centroid = Point::new(cell.centroid.x(), cell.centroid.y());
            best_cell.extent = cell.extent;
            best_cell.distance = cell.distance;
            best_cell.max_distance = cell.max_distance;
        }
        // Bail out of this iteration if we can't find a better solution
        if cell.max_distance - best_cell.distance <= *tolerance {
            continue;
        }
        // Otherwise, add a new quadtree node and start again
        h = cell.extent / two;
        add_quad(&mut cell_queue, &cell, &h, polygon);
    }
    // We've exhausted the queue, so return the best solution we've found
    Point::new(best_cell.centroid.x(), best_cell.centroid.y())
}

#[cfg(test)]
mod tests {
    use super::{polylabel, Qcell};
    use geo::prelude::*;
    use geo::{Point, Polygon};
    use std::collections::BinaryHeap;
    #[test]
    // polygons are those used in Shapely's tests
    fn test_polylabel() {
        let coords = include!("poly1.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &10.000);
        assert_eq!(res, Point::new(59.35615556364569, 121.83919629746435));
    }
    #[test]
    // does a concave polygon contain the calculated point?
    // relevant because the centroid lies outside the polygon in this case
    fn test_concave() {
        let coords = include!("poly2.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &1.0);
        assert!(poly.contains(&res));
    }
    #[test]
    fn test_london() {
        let coords = include!("poly3.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &0.001);
        assert_eq!(res, Point::new(-0.45556816445920356, 51.54848888202887));
    }
    #[test]
    fn polygon_l_test() {
        // an L shape
        let coords = vec![
            (0.0, 0.0),
            (4.0, 0.0),
            (4.0, 1.0),
            (1.0, 1.0),
            (1.0, 4.0),
            (0.0, 4.0),
            (0.0, 0.0),
        ];
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &0.10);
        assert_eq!(res, Point::new(0.5625, 0.5625));
    }
    #[test]
    fn degenerate_polygon_test() {
        let a_coords = vec![(0.0, 0.0), (1.0, 0.0), (2.0, 0.0), (0.0, 0.0)];
        let a_poly = Polygon::new(a_coords.into(), vec![]);
        let a_res = polylabel(&a_poly, &1.0);
        assert_eq!(a_res, Point::new(0.0, 0.0));
    }
    #[test]
    fn degenerate_polygon_test_2() {
        let b_coords = vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)];
        let b_poly = Polygon::new(b_coords.into(), vec![]);
        let b_res = polylabel(&b_poly, &1.0);
        assert_eq!(b_res, Point::new(0.0, 0.0));
    }
    #[test]
    // Is our priority queue behaving as it should?
    fn test_queue() {
        let a = Qcell {
            centroid: Point::new(1.0, 2.0),
            extent: 3.0,
            distance: 4.0,
            max_distance: 8.0,
        };
        let b = Qcell {
            centroid: Point::new(1.0, 2.0),
            extent: 3.0,
            distance: 4.0,
            max_distance: 7.0,
        };
        let c = Qcell {
            centroid: Point::new(1.0, 2.0),
            extent: 3.0,
            distance: 4.0,
            max_distance: 9.0,
        };
        let mut v = vec![];
        v.push(a);
        v.push(b);
        v.push(c);
        let mut q = BinaryHeap::from(v);
        assert_eq!(q.pop().unwrap().max_distance, 9.0);
        assert_eq!(q.pop().unwrap().max_distance, 8.0);
        assert_eq!(q.pop().unwrap().max_distance, 7.0);
    }
}
<|endoftext|>


<commit_before>extern crate itertools;
extern crate unicode_segmentation;
extern crate unicode_normalization;

#[macro_use]
extern crate lazy_static;

mod utils;
mod suffix;
mod nickname;
mod title;
mod surname;
mod initials;
mod namecase;
mod namelike;

use itertools::Itertools;
use utils::*;
use namecase::namecase;
use unicode_segmentation::UnicodeSegmentation;
use std::ascii::AsciiExt;

pub struct Name {
  pub given_name: Option<String>,
  pub surname: String,
  pub middle_names: Option<String>,
  pub first_initial: char,
  pub middle_initials: Option<String>,
}

// Strip suffixes and titles, and find the start of the surname.
// These tasks are intrinsically connected because commas may indicate
// either a sort-ordered surname ("Smith, John") or a suffix ("John Smith, esq")
//
// This is where the meat of the parsing takes place
fn name_words_and_surname_index(name: &str, mixed_case: bool) -> (Vec<&str>, usize) {
    let mut words: Vec<&str> = Vec::new();
    let mut surname_index = 0;

    // Strip suffixes and then flip remaining words around (remaining) comma
    for (i, part) in name.split(",").enumerate() {
        if i > 1 {
            // Anything after the second comma is a suffix
            break;
        }
        else if i == 0 || words.is_empty() {
            // We're in the surname part (if the format is "Smith, John"),
            // or the only actual name part (if the format is "John Smith,
            // esq." or just "John Smith")
            for word in part.split_whitespace() {
                if first_alphabetical_char(word).is_none() {
                    continue;
                } else if word.chars().all( |c| !c.is_ascii() ) {
                    // Trust unicode word boundaries, because we've got nothing better
                    words.extend(word.unicode_words());
                } else {
                    // Don't trust unicode word boundaries, because they'll split hyphenated names
                    // and names with apostrophes
                    words.push(word);
                }
            }
        }
        else {
            // We already processed one comma-separated part, which may
            // have been the surname (if this is the given name), or the full
            // name (if this is a suffix)
            let mut given_middle_or_suffix_words: Vec<&str> = Vec::new();
            for word in part.split_whitespace() {
                if first_alphabetical_char(word).is_none() {
                    continue;
                } else if word.chars().all( |c| !c.is_ascii() ) {
                    // Trust unicode word boundaries, because we've got nothing better
                    given_middle_or_suffix_words.extend(word.unicode_words());
                } else {
                    // Don't trust unicode word boundaries, because they'll split hyphenated names
                    // and names with apostrophes
                    given_middle_or_suffix_words.push(word);
                }
            }

            while !given_middle_or_suffix_words.is_empty() {
                let word = given_middle_or_suffix_words.pop().unwrap();

                let is_suffix = suffix::is_suffix(word);

                // Preserve parseability: don't strip an apparent suffix
                // that might still be part of the name, if it would take
                // the name below 2 words
                let keep_it_anyway =
                    is_suffix &&
                    given_middle_or_suffix_words.len() + words.len() < 2 &&
                    (initials::is_initials(word, mixed_case) || namelike::is_name(word, false));

                if !is_suffix || keep_it_anyway {
                    surname_index += 1;
                    words.insert(0, word)
                }
            }
        }
    }

    // Strip non-comma-separated suffixes (e.g. "John Smith Jr.")
    while !words.is_empty() {
        {
            let word = words.last().unwrap();
            if !suffix::is_suffix(word) {
                break
            }

            // Preserve parseability: don't strip an apparent suffix
            // that might still be part of the name, if it would take
            // the name below 2 words
            let keep_it_anyway = words.len() <= 2 &&
                (initials::is_initials(word, mixed_case) || namelike::is_name(word, true));
            if keep_it_anyway {
                break
            }
        }

        words.pop();
    }

    // Check for title as prefix (e.g. "Dr. John Smith" or "Right Hon. John Smith")
    let mut prefix_len = words.len() - 1;
    while prefix_len > 0 {
        if title::is_title(&words[0..prefix_len]) {
            for _ in 0..prefix_len {
                let word = words[0];

                // Preserve parseability: don't strip an apparent title part
                // that might still be part of the name, if it would take
                // the name below 2 words
                //
                // However, only allow initials, not namelike strings; nothing
                // we'll recognize as a title is a likely given name
                let keep_it_anyway = words.len() <= 2 &&
                    initials::is_initials(word, mixed_case);

                if !keep_it_anyway {
                    words.remove(0);
                    if surname_index > 0 {
                        surname_index -= 1;
                    }
                }
            }

            break
        }
        prefix_len -= 1;
    }

    if words.len() > 1 && (surname_index <= 0 || surname_index >= words.len()) {
        // We didn't get the surname from the formatting (e.g. "Smith, John"),
        // so we have to guess it
        surname_index = surname::find_surname_index(&words, mixed_case);
    }

    (words, surname_index)
}

impl Name {
    pub fn parse(name: &str) -> Option<Name> {
        if first_alphabetical_char(name).is_none() {
            return None
        }

        let mixed_case = is_mixed_case(name);
        let name = nickname::strip_nickname(name);
        let (words, surname_index) = name_words_and_surname_index(&name, mixed_case);

        if words.len() < 2 {
            // We need at least a first and last name, or we can't tell which we have
            return None;
        }

        let first_initial = first_alphabetical_char(words[0])
            .unwrap()
            .to_uppercase()
            .next()
            .unwrap();

        // TODO Benchmark special casing 2-word-remaining names to avoid initializing vectors

        // Take the remaining words, and strip out the initials (if present;
        // only allow one block of initials) and the first name (if present),
        // and whatever's left are the middle names
        let mut given_name = None;
        let mut middle_names: Vec<&str> = Vec::new();
        let mut middle_initials = String::new();

        if words[surname_index..].iter().all( |w| !namelike::is_name(w, true) ) {
            return None;
        }

        for (i, word) in words[0..surname_index].iter().enumerate() {
            if initials::is_initials(word, mixed_case) {
                let start = if i == 0 { 1 } else { 0 };
                if word.len() > start {
                    middle_initials.extend(
                        word
                            .chars()
                            .skip(start)
                            .filter( |c| c.is_alphabetic() )
                            .filter_map( |w| w.to_uppercase().next() ));
                }
            } else if given_name.is_none() {
                given_name = Some(word.to_string());
            } else {
                middle_names.push(word);
                middle_initials.push(
                    first_alphabetical_char(word)
                        .unwrap()
                        .to_uppercase()
                        .next()
                        .unwrap());
            }
        }

        let given_name =
            if given_name.is_none() || mixed_case {
                given_name
            } else {
                Some(namecase(&given_name.unwrap(), false))
            };

        let middle_names =
            if middle_names.is_empty() {
                None
            } else if mixed_case {
                Some(middle_names.join(" "))
            } else {
                Some(middle_names.iter().map( |w| namecase(w, false) ).join(" "))
            };

        let middle_initials =
            if middle_initials.is_empty() {
                None
            } else {
                Some(middle_initials)
            };

        let surname =
            if mixed_case {
                words[surname_index..].iter().join(" ")
            } else {
                let last_surname_word_ix = words.len() - surname_index - 1;
                words[surname_index..]
                    .iter()
                    .enumerate()
                    .map( |(i, w)| namecase(w, i < last_surname_word_ix) )
                    .join(" ")
            };

        Some(Name {
            first_initial: first_initial,
            given_name: given_name,
            surname: surname,
            middle_names: middle_names,
            middle_initials: middle_initials,
        })
    }

    pub fn display(&self) -> String {
        match self.given_name {
            Some(ref name) => {
                format!("{} {}", name, self.surname)
            }
            None => {
                format!("{}. {}", self.first_initial, self.surname)
            }
        }
    }
}
<commit_msg>Add TODO<commit_after>extern crate itertools;
extern crate unicode_segmentation;
extern crate unicode_normalization;

#[macro_use]
extern crate lazy_static;

mod utils;
mod suffix;
mod nickname;
mod title;
mod surname;
mod initials;
mod namecase;
mod namelike;

use itertools::Itertools;
use utils::*;
use namecase::namecase;
use unicode_segmentation::UnicodeSegmentation;
use std::ascii::AsciiExt;

pub struct Name {
  pub given_name: Option<String>,
  pub surname: String,
  pub middle_names: Option<String>,
  pub first_initial: char,
  pub middle_initials: Option<String>,
}

// Strip suffixes and titles, and find the start of the surname.
// These tasks are intrinsically connected because commas may indicate
// either a sort-ordered surname ("Smith, John") or a suffix ("John Smith, esq")
//
// This is where the meat of the parsing takes place
//
// TODO Consider a refactoring that uses split_word_bounds(), and might
// merge nickname removal into the main parse loop
fn name_words_and_surname_index(name: &str, mixed_case: bool) -> (Vec<&str>, usize) {
    let mut words: Vec<&str> = Vec::new();
    let mut surname_index = 0;

    // Strip suffixes and then flip remaining words around (remaining) comma
    for (i, part) in name.split(",").enumerate() {
        if i > 1 {
            // Anything after the second comma is a suffix
            break;
        }
        else if i == 0 || words.is_empty() {
            // We're in the surname part (if the format is "Smith, John"),
            // or the only actual name part (if the format is "John Smith,
            // esq." or just "John Smith")
            for word in part.split_whitespace() {
                if first_alphabetical_char(word).is_none() {
                    continue;
                } else if word.chars().all( |c| !c.is_ascii() ) {
                    // Trust unicode word boundaries, because we've got nothing better
                    words.extend(word.unicode_words());
                } else {
                    // Don't trust unicode word boundaries, because they'll split hyphenated names
                    // and names with apostrophes
                    words.push(word);
                }
            }
        }
        else {
            // We already processed one comma-separated part, which may
            // have been the surname (if this is the given name), or the full
            // name (if this is a suffix)
            let mut given_middle_or_suffix_words: Vec<&str> = Vec::new();
            for word in part.split_whitespace() {
                if first_alphabetical_char(word).is_none() {
                    continue;
                } else if word.chars().all( |c| !c.is_ascii() ) {
                    // Trust unicode word boundaries, because we've got nothing better
                    given_middle_or_suffix_words.extend(word.unicode_words());
                } else {
                    // Don't trust unicode word boundaries, because they'll split hyphenated names
                    // and names with apostrophes
                    given_middle_or_suffix_words.push(word);
                }
            }

            while !given_middle_or_suffix_words.is_empty() {
                let word = given_middle_or_suffix_words.pop().unwrap();

                let is_suffix = suffix::is_suffix(word);

                // Preserve parseability: don't strip an apparent suffix
                // that might still be part of the name, if it would take
                // the name below 2 words
                let keep_it_anyway =
                    is_suffix &&
                    given_middle_or_suffix_words.len() + words.len() < 2 &&
                    (initials::is_initials(word, mixed_case) || namelike::is_name(word, false));

                if !is_suffix || keep_it_anyway {
                    surname_index += 1;
                    words.insert(0, word)
                }
            }
        }
    }

    // Strip non-comma-separated suffixes (e.g. "John Smith Jr.")
    while !words.is_empty() {
        {
            let word = words.last().unwrap();
            if !suffix::is_suffix(word) {
                break
            }

            // Preserve parseability: don't strip an apparent suffix
            // that might still be part of the name, if it would take
            // the name below 2 words
            let keep_it_anyway = words.len() <= 2 &&
                (initials::is_initials(word, mixed_case) || namelike::is_name(word, true));
            if keep_it_anyway {
                break
            }
        }

        words.pop();
    }

    // Check for title as prefix (e.g. "Dr. John Smith" or "Right Hon. John Smith")
    let mut prefix_len = words.len() - 1;
    while prefix_len > 0 {
        if title::is_title(&words[0..prefix_len]) {
            for _ in 0..prefix_len {
                let word = words[0];

                // Preserve parseability: don't strip an apparent title part
                // that might still be part of the name, if it would take
                // the name below 2 words
                //
                // However, only allow initials, not namelike strings; nothing
                // we'll recognize as a title is a likely given name
                let keep_it_anyway = words.len() <= 2 &&
                    initials::is_initials(word, mixed_case);

                if !keep_it_anyway {
                    words.remove(0);
                    if surname_index > 0 {
                        surname_index -= 1;
                    }
                }
            }

            break
        }
        prefix_len -= 1;
    }

    if words.len() > 1 && (surname_index <= 0 || surname_index >= words.len()) {
        // We didn't get the surname from the formatting (e.g. "Smith, John"),
        // so we have to guess it
        surname_index = surname::find_surname_index(&words, mixed_case);
    }

    (words, surname_index)
}

impl Name {
    pub fn parse(name: &str) -> Option<Name> {
        if first_alphabetical_char(name).is_none() {
            return None
        }

        let mixed_case = is_mixed_case(name);
        let name = nickname::strip_nickname(name);
        let (words, surname_index) = name_words_and_surname_index(&name, mixed_case);

        if words.len() < 2 {
            // We need at least a first and last name, or we can't tell which we have
            return None;
        }

        let first_initial = first_alphabetical_char(words[0])
            .unwrap()
            .to_uppercase()
            .next()
            .unwrap();

        // TODO Benchmark special casing 2-word-remaining names to avoid initializing vectors

        // Take the remaining words, and strip out the initials (if present;
        // only allow one block of initials) and the first name (if present),
        // and whatever's left are the middle names
        let mut given_name = None;
        let mut middle_names: Vec<&str> = Vec::new();
        let mut middle_initials = String::new();

        if words[surname_index..].iter().all( |w| !namelike::is_name(w, true) ) {
            return None;
        }

        for (i, word) in words[0..surname_index].iter().enumerate() {
            if initials::is_initials(word, mixed_case) {
                let start = if i == 0 { 1 } else { 0 };
                if word.len() > start {
                    middle_initials.extend(
                        word
                            .chars()
                            .skip(start)
                            .filter( |c| c.is_alphabetic() )
                            .filter_map( |w| w.to_uppercase().next() ));
                }
            } else if given_name.is_none() {
                given_name = Some(word.to_string());
            } else {
                middle_names.push(word);
                middle_initials.push(
                    first_alphabetical_char(word)
                        .unwrap()
                        .to_uppercase()
                        .next()
                        .unwrap());
            }
        }

        let given_name =
            if given_name.is_none() || mixed_case {
                given_name
            } else {
                Some(namecase(&given_name.unwrap(), false))
            };

        let middle_names =
            if middle_names.is_empty() {
                None
            } else if mixed_case {
                Some(middle_names.join(" "))
            } else {
                Some(middle_names.iter().map( |w| namecase(w, false) ).join(" "))
            };

        let middle_initials =
            if middle_initials.is_empty() {
                None
            } else {
                Some(middle_initials)
            };

        let surname =
            if mixed_case {
                words[surname_index..].iter().join(" ")
            } else {
                let last_surname_word_ix = words.len() - surname_index - 1;
                words[surname_index..]
                    .iter()
                    .enumerate()
                    .map( |(i, w)| namecase(w, i < last_surname_word_ix) )
                    .join(" ")
            };

        Some(Name {
            first_initial: first_initial,
            given_name: given_name,
            surname: surname,
            middle_names: middle_names,
            middle_initials: middle_initials,
        })
    }

    pub fn display(&self) -> String {
        match self.given_name {
            Some(ref name) => {
                format!("{} {}", name, self.surname)
            }
            None => {
                format!("{}. {}", self.first_initial, self.surname)
            }
        }
    }
}
<|endoftext|>


<commit_before>// Inspired by http://python-gitlab.readthedocs.io/en/stable/

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;

#[macro_use]
extern crate error_chain;

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

#[macro_use]
extern crate log;
extern crate hyper;

pub mod gitlab;
pub mod groups;
pub mod projects;
pub mod issues;
pub mod merge_requests;

// Re-export those structs
pub use gitlab::Pagination;
pub use gitlab::GitLab;
// pub use projects::Project;

trait BuildQuery {
    fn build_query(&self) -> String;
}

#[cfg(test)]
mod tests {
    // use gitlab::GitLab;
    // use hyper;

    // #[test]
    // fn unauthorized() {
    //     let gl = GitLab::new("http", "gitlab.com", 80, "XXXXXXXXXXXXX");
    //     println!("gl: {:?}", gl);
    //     assert_eq!(gl.attempt_connection().unwrap().status,
    //                hyper::status::StatusCode::Unauthorized);
    // }
}
<commit_msg>Define a pub mod `errors` and import all of it.<commit_after>// Inspired by http://python-gitlab.readthedocs.io/en/stable/

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;

#[macro_use]
extern crate error_chain;

// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
pub mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain! { }
}

use errors::*;

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

#[macro_use]
extern crate log;
extern crate hyper;

pub mod gitlab;
pub mod groups;
pub mod projects;
pub mod issues;
pub mod merge_requests;

// Re-export those structs
pub use gitlab::Pagination;
pub use gitlab::GitLab;
// pub use projects::Project;

trait BuildQuery {
    fn build_query(&self) -> String;
}

#[cfg(test)]
mod tests {
    // use gitlab::GitLab;
    // use hyper;

    // #[test]
    // fn unauthorized() {
    //     let gl = GitLab::new("http", "gitlab.com", 80, "XXXXXXXXXXXXX");
    //     println!("gl: {:?}", gl);
    //     assert_eq!(gl.attempt_connection().unwrap().status,
    //                hyper::status::StatusCode::Unauthorized);
    // }
}
<|endoftext|>


<commit_before>#![cfg_attr(not(stage0), deny(warnings))]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
#![crate_name = "compiler_builtins"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       test(attr(deny(warnings))))]
#![feature(asm)]
#![feature(compiler_builtins)]
#![feature(core_intrinsics)]
#![feature(naked_functions)]
#![feature(repr_simd)]
#![feature(abi_unadjusted)]
#![feature(linkage)]
#![feature(lang_items)]
#![allow(unused_features)]
#![allow(stable_features)] // FIXME(mark-i-m): remove after i128 stabilizes
#![feature(i128_type)]
#![no_builtins]
#![cfg_attr(feature = "compiler-builtins", feature(staged_api))]
#![cfg_attr(feature = "compiler-builtins",
            unstable(feature = "compiler_builtins_lib",
                     reason = "Compiler builtins. Will never become stable.",
                     issue = "0"))]

// We disable #[no_mangle] for tests so that we can verify the test results
// against the native compiler-rt implementations of the builtins.

// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
// implementation of that intrinsic and we'll prefer to use that

// NOTE(aapcs, aeabi, arm) ARM targets use intrinsics named __aeabi_* instead of the intrinsics
// that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the
// AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them.

#[cfg(test)]
extern crate core;

fn abort() -> ! {
    unsafe { core::intrinsics::abort() }
}

#[macro_use]
mod macros;

pub mod int;
pub mod float;

pub mod mem;

#[cfg(target_arch = "arm")]
pub mod arm;

#[cfg(all(kernel_user_helpers, target_os = "linux", target_arch = "arm"))]
pub mod arm_linux;

#[cfg(target_arch = "x86")]
pub mod x86;

#[cfg(target_arch = "x86_64")]
pub mod x86_64;

pub mod probestack;
<commit_msg>Remove #![feature(i128_type)] as i128 is stable<commit_after>#![cfg_attr(not(stage0), deny(warnings))]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
#![crate_name = "compiler_builtins"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       test(attr(deny(warnings))))]
#![feature(asm)]
#![feature(compiler_builtins)]
#![feature(core_intrinsics)]
#![feature(naked_functions)]
#![feature(repr_simd)]
#![feature(abi_unadjusted)]
#![feature(linkage)]
#![feature(lang_items)]
#![allow(unused_features)]
#![no_builtins]
#![cfg_attr(feature = "compiler-builtins", feature(staged_api))]
#![cfg_attr(feature = "compiler-builtins",
            unstable(feature = "compiler_builtins_lib",
                     reason = "Compiler builtins. Will never become stable.",
                     issue = "0"))]

// We disable #[no_mangle] for tests so that we can verify the test results
// against the native compiler-rt implementations of the builtins.

// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
// implementation of that intrinsic and we'll prefer to use that

// NOTE(aapcs, aeabi, arm) ARM targets use intrinsics named __aeabi_* instead of the intrinsics
// that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the
// AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them.

#[cfg(test)]
extern crate core;

fn abort() -> ! {
    unsafe { core::intrinsics::abort() }
}

#[macro_use]
mod macros;

pub mod int;
pub mod float;

pub mod mem;

#[cfg(target_arch = "arm")]
pub mod arm;

#[cfg(all(kernel_user_helpers, target_os = "linux", target_arch = "arm"))]
pub mod arm_linux;

#[cfg(target_arch = "x86")]
pub mod x86;

#[cfg(target_arch = "x86_64")]
pub mod x86_64;

pub mod probestack;
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotCommandCenter::new();

    for line in input.lines() {
        br.exec_command(line);
    }
    0
}

#[derive(Debug)]
pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

#[derive(Debug)]
pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
            self.process_bots();
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        self.bots_to_check.remove(0)
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            println!("COMMAND CTR process_bots, {} bots to process", self.bots_to_check.len());
            let check_bot_key = self.get_next_bot_to_check();
            println!("COMMAND CTR processing bot {}", check_bot_key);
            if self.bot_has_two_chips(check_bot_key) {
                println!("COMMAND CTR found bot {} has two chips", check_bot_key);

                if let Some(command) = self.saved_commands.remove(&check_bot_key) {
                    println!("COMMAND CTR found command: {:?}", command);
                    let (low_value, high_value) = self.bot_low_high(check_bot_key);
                    println!("COMMAND CTR found low = {}, high = {}", low_value, high_value);
                    match command.low_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.low_value_key,
                            low_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.low_value_key,
                            low_value
                        ),
                    }

                    match command.high_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.high_value_key,
                            high_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.high_value_key,
                            high_value
                        ),
                    }
                } else {
                    println!("COMMAND CTR found no saved command for bot {} that has two chips", check_bot_key);
                }

            }
        }
        println!("COMMAND CTR bots_to_check is empty");
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    println!("Bot {} found {} < {}", self.key, c1, c2);
                    if c1 == 17 && c2 == 61 {
                        panic!("The bot you are looking for is {}", self.key);
                    }
                    (c1, c2)
                } else {
                    println!("Bot {} found {} < {}", self.key, c2, c1);
                    if c2 == 17 && c1 == 61 {
                        panic!("The bot you are looking for is {}", self.key);
                    }
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<commit_msg>Remove panic for part 1, check that outputs 0-2 have 1 val<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotCommandCenter::new();

    for line in input.lines() {
        br.exec_command(line);
    }
    println!("output 0: {:?}", br.outputs.get(&0));
    println!("output 1: {:?}", br.outputs.get(&1));
    println!("output 2: {:?}", br.outputs.get(&2));

    0
}

#[derive(Debug)]
pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

#[derive(Debug)]
pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
            self.process_bots();
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        self.bots_to_check.remove(0)
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            println!("COMMAND CTR process_bots, {} bots to process", self.bots_to_check.len());
            let check_bot_key = self.get_next_bot_to_check();
            println!("COMMAND CTR processing bot {}", check_bot_key);
            if self.bot_has_two_chips(check_bot_key) {
                println!("COMMAND CTR found bot {} has two chips", check_bot_key);

                if let Some(command) = self.saved_commands.remove(&check_bot_key) {
                    println!("COMMAND CTR found command: {:?}", command);
                    let (low_value, high_value) = self.bot_low_high(check_bot_key);
                    println!("COMMAND CTR found low = {}, high = {}", low_value, high_value);
                    match command.low_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.low_value_key,
                            low_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.low_value_key,
                            low_value
                        ),
                    }

                    match command.high_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.high_value_key,
                            high_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.high_value_key,
                            high_value
                        ),
                    }
                } else {
                    println!("COMMAND CTR found no saved command for bot {} that has two chips", check_bot_key);
                }

            }
        }
        println!("COMMAND CTR bots_to_check is empty");
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    println!("Bot {} found {} < {}", self.key, c1, c2);
                    (c1, c2)
                } else {
                    println!("Bot {} found {} < {}", self.key, c2, c1);
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) edef <edef@edef.eu>
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#![feature(asm, naked_functions, cfg_target_vendor, untagged_unions)]
#![cfg_attr(feature = "alloc", feature(alloc, allocator_api))]
#![cfg_attr(test, feature(test))]
#![no_std]

//! libfringe is a library implementing safe, lightweight context switches,
//! without relying on kernel services. It can be used in hosted environments
//! (using `std`) as well as on bare metal (using `core`).
//!
//! It provides the following safe abstractions:
//!
//!   * an implementation of generators,
//!     [Generator](generator/struct.Generator.html).
//!
//! It also provides the necessary low-level building blocks:
//!
//!   * a trait that can be implemented by stack allocators,
//!     [Stack](struct.Stack.html);
//!   * a wrapper for using slice references as stacks,
//!     [SliceStack](struct.SliceStack.html);
//!   * a stack allocator based on `Box<[u8]>`,
//!     [OwnedStack](struct.OwnedStack.html);
//!   * a stack allocator based on anonymous memory mappings with guard pages,
//!     [OsStack](struct.OsStack.html).

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(feature = "alloc")]
extern crate alloc;

pub use stack::*;
pub use generator::Generator;

mod arch;

/// Minimum alignment of a stack base address on the target platform.
pub const STACK_ALIGNMENT: usize = arch::STACK_ALIGNMENT;

mod debug;

pub mod generator;

mod stack;
<commit_msg>Remove cfg_target_vendor attribute.<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) edef <edef@edef.eu>
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#![feature(asm, naked_functions, untagged_unions)]
#![cfg_attr(feature = "alloc", feature(alloc, allocator_api))]
#![cfg_attr(test, feature(test))]
#![no_std]

//! libfringe is a library implementing safe, lightweight context switches,
//! without relying on kernel services. It can be used in hosted environments
//! (using `std`) as well as on bare metal (using `core`).
//!
//! It provides the following safe abstractions:
//!
//!   * an implementation of generators,
//!     [Generator](generator/struct.Generator.html).
//!
//! It also provides the necessary low-level building blocks:
//!
//!   * a trait that can be implemented by stack allocators,
//!     [Stack](struct.Stack.html);
//!   * a wrapper for using slice references as stacks,
//!     [SliceStack](struct.SliceStack.html);
//!   * a stack allocator based on `Box<[u8]>`,
//!     [OwnedStack](struct.OwnedStack.html);
//!   * a stack allocator based on anonymous memory mappings with guard pages,
//!     [OsStack](struct.OsStack.html).

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(feature = "alloc")]
extern crate alloc;

pub use stack::*;
pub use generator::Generator;

mod arch;

/// Minimum alignment of a stack base address on the target platform.
pub const STACK_ALIGNMENT: usize = arch::STACK_ALIGNMENT;

mod debug;

pub mod generator;

mod stack;
<|endoftext|>


<commit_before><commit_msg>Ugly first-sketch inspection of gre pkts<commit_after><|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate rand;
extern crate time;

#[derive(Debug)]
pub struct CohortResult<T: Clone> {
    duration: f64,
    result: T
}

impl<T: Clone> CohortResult<T> {
    pub fn new(duration: f64, result: &T) -> Self {
        CohortResult {
            duration: duration,
            result: result.clone()
        }
    }
}

#[derive(Debug)]
pub struct ExperimentResult<CurrentT: Clone, NewT: Clone> {
    current: CohortResult<CurrentT>,
    new: CohortResult<NewT>,
    name: &'static str
}

impl<CurrentT: Clone, NewT: Clone> ExperimentResult<CurrentT, NewT> {
    pub fn new(current: CohortResult<CurrentT>, new: CohortResult<NewT>, name: &'static str) -> Self {
        ExperimentResult {
            current: current,
            new: new,
            name: name
        }
    }
}

#[macro_export]
macro_rules! experiment {
    ($dexter_type:ident, $name:expr, current:$current:block new:$new:block) => {
        {
            use $crate::internal::rand::{thread_rng, Rng};
            use $crate::internal::time::{precise_time_ns};

            let mut rng = thread_rng();
            let mut did_one = false;
            let current_goes_first: bool = rng.gen();
            let mut current_val = None;
            let mut new_val = None;
            let mut current_duration = 0;
            let mut new_duration = 0;
            loop {
                if (current_goes_first || did_one) && !(current_goes_first && did_one) {
                    let start = precise_time_ns();
                    current_val = Some($current);
                    current_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
                if (!current_goes_first || did_one) && !(!current_goes_first && did_one) {
                    let start = precise_time_ns();
                    new_val = Some($new);
                    new_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
            }
            $dexter_type::publish(ExperimentResult::new(
                CohortResult::new(current_duration as f64 * 1e-9, &current_val.as_ref().unwrap()),
                CohortResult::new(new_duration as f64 * 1e-9, &new_val.as_ref().unwrap()),
                $name
            ));
            current_val.unwrap()
        }
    }
}

pub trait Dexter<CurrentT: Clone, NewT: Clone> {
    fn publish(_: ExperimentResult<CurrentT, NewT>) {}
}

#[cfg(test)]
mod test {
    use super::*;
    struct TestExperiment;

    impl Dexter<String, String> for TestExperiment {
        fn publish(result: ExperimentResult<String, String>) {
            println!("{:?}", result);
        }
    }

    #[test]
    fn it_works() {
        let a = experiment!{
            TestExperiment,
            "experiment!",
            current: {
                println!("current went!");
                "current result".to_string()
            }
            new: {
                println!("new went!");
                "new result".to_string()
            }
        };
        println!("{}", a);
    }
}

#[doc(hidden)]
mod internal {
    pub use rand;
    pub use time;
}
<commit_msg>Made internal mod public<commit_after>#![allow(dead_code)]
extern crate rand;
extern crate time;

#[derive(Debug)]
pub struct CohortResult<T: Clone> {
    duration: f64,
    result: T
}

impl<T: Clone> CohortResult<T> {
    pub fn new(duration: f64, result: &T) -> Self {
        CohortResult {
            duration: duration,
            result: result.clone()
        }
    }
}

#[derive(Debug)]
pub struct ExperimentResult<CurrentT: Clone, NewT: Clone> {
    current: CohortResult<CurrentT>,
    new: CohortResult<NewT>,
    name: &'static str
}

impl<CurrentT: Clone, NewT: Clone> ExperimentResult<CurrentT, NewT> {
    pub fn new(current: CohortResult<CurrentT>, new: CohortResult<NewT>, name: &'static str) -> Self {
        ExperimentResult {
            current: current,
            new: new,
            name: name
        }
    }
}

#[macro_export]
macro_rules! experiment {
    ($dexter_type:ident, $name:expr, current:$current:block new:$new:block) => {
        {
            use $crate::internal::rand::{thread_rng, Rng};
            use $crate::internal::time::{precise_time_ns};

            let mut rng = thread_rng();
            let mut did_one = false;
            let current_goes_first: bool = rng.gen();
            let mut current_val = None;
            let mut new_val = None;
            let mut current_duration = 0;
            let mut new_duration = 0;
            loop {
                if (current_goes_first || did_one) && !(current_goes_first && did_one) {
                    let start = precise_time_ns();
                    current_val = Some($current);
                    current_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
                if (!current_goes_first || did_one) && !(!current_goes_first && did_one) {
                    let start = precise_time_ns();
                    new_val = Some($new);
                    new_duration = precise_time_ns() - start;
                    if did_one {
                        break;
                    } else {
                        did_one = true;
                    }
                }
            }
            $dexter_type::publish(ExperimentResult::new(
                CohortResult::new(current_duration as f64 * 1e-9, &current_val.as_ref().unwrap()),
                CohortResult::new(new_duration as f64 * 1e-9, &new_val.as_ref().unwrap()),
                $name
            ));
            current_val.unwrap()
        }
    }
}

pub trait Dexter<CurrentT: Clone, NewT: Clone> {
    fn publish(_: ExperimentResult<CurrentT, NewT>) {}
}

#[cfg(test)]
mod test {
    use super::*;
    struct TestExperiment;

    impl Dexter<String, String> for TestExperiment {
        fn publish(result: ExperimentResult<String, String>) {
            println!("{:?}", result);
        }
    }

    #[test]
    fn it_works() {
        let a = experiment!{
            TestExperiment,
            "experiment!",
            current: {
                println!("current went!");
                "current result".to_string()
            }
            new: {
                println!("new went!");
                "new result".to_string()
            }
        };
        println!("{}", a);
    }
}

#[doc(hidden)]
pub mod internal {
    pub use rand;
    pub use time;
}
<|endoftext|>


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

use std::ascii::AsciiExt;

use tokenizer::{PeekableTokens, Token, Tokens};
use types::FromTokens;
use types::linestring::LineString;
use types::point::Point;
use types::polygon::Polygon;

mod tokenizer;
mod types;

pub enum WktItem {
    Point(Point),
    LineString(LineString),
    Polygon(Polygon),
}

impl WktItem {
    fn from_word_and_tokens(word: &str, tokens: &mut PeekableTokens)-> Result<Self, &'static str> {
        match word {
            "POINT" => {
                let x: Result<Point, _> = FromTokens::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "LINESTRING" => {
                let x: Result<LineString, _> = FromTokens::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "POLYGON" => {
                let x: Result<Polygon, _> = FromTokens::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            _ => Err("Invalid type encountered"),
        }
    }
}

pub struct Wkt {
    items: Vec<WktItem>
}

impl Wkt {
    fn new() -> Self {
        Wkt {items: vec![]}
    }

    fn add_item(&mut self, item: WktItem) {
        self.items.push(item);
    }

    fn from_str(wkt_str: &str) -> Result<Self, &'static str> {
        let tokens = Tokens::from_str(wkt_str);
        Wkt::from_tokens(tokens)
    }

    fn from_tokens(tokens: Tokens) -> Result<Self, &'static str> {
        let mut wkt = Wkt::new();
        let mut tokens = tokens.peekable();
        let word = match tokens.next() {
            Some(Token::Word(word)) => {
                if !word.is_ascii() {
                    return Err("Encountered non-ascii word");
                }
                word.to_ascii_uppercase()
            },
            None => return Ok(wkt),
            _ => return Err("Invalid WKT format"),
        };
        match WktItem::from_word_and_tokens(word.as_slice(), &mut tokens) {
            Ok(item) => wkt.add_item(item),
            Err(s) => return Err(s),
        }
        Ok(wkt)
    }
}

#[cfg(test)]
mod tests {
    use super::{Wkt, WktItem};

    #[test]
    fn empty_string() {
        let wkt = Wkt::from_str("").ok().unwrap();
        assert_eq!(0, wkt.items.len());
    }

    #[test]
    fn basic_point() {
        let mut wkt = Wkt::from_str("POINT (10 -20)").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        let point = match wkt.items.pop().unwrap() {
            WktItem::Point(point) => point,
            _ => unreachable!(),
        };
        assert_eq!(10.0, point.coord.x);
        assert_eq!(-20.0, point.coord.y);
        assert_eq!(None, point.coord.z);
        assert_eq!(None, point.coord.m);
    }

    #[test]
    fn basic_linestring() {
        let mut wkt = Wkt::from_str("LINESTRING (10 -20, -0 -0.5)").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        let linestring = match wkt.items.pop().unwrap() {
            WktItem::LineString(linestring) => linestring,
            _ => unreachable!(),
        };
        assert_eq!(2, linestring.coords.len());

        assert_eq!(10.0, linestring.coords[0].x);
        assert_eq!(-20.0, linestring.coords[0].y);
        assert_eq!(None, linestring.coords[0].z);
        assert_eq!(None, linestring.coords[0].m);

        assert_eq!(0.0, linestring.coords[1].x);
        assert_eq!(-0.5, linestring.coords[1].y);
        assert_eq!(None, linestring.coords[1].z);
        assert_eq!(None, linestring.coords[1].m);
    }

    #[test]
    fn basic_polygon() {
        let mut wkt = Wkt::from_str("POLYGON ((8 4, 4 0, 0 4, 8 4), (7 3, 4 1, 1 4, 7 3))").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        let linestring = match wkt.items.pop().unwrap() {
            WktItem::Polygon(linestring) => linestring,
            _ => unreachable!(),
        };
        assert_eq!(2, linestring.lines.len());
    }

    #[test]
    fn invalid_points() {
        Wkt::from_str("POINT ()").err().unwrap();
        Wkt::from_str("POINT (10)").err().unwrap();
        Wkt::from_str("POINT 10").err().unwrap();
        Wkt::from_str("POINT (10 -20 40)").err().unwrap();
    }
}
<commit_msg>Allow unstable warnings for now<commit_after>// Copyright 2014-2015 The GeoRust Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(unstable)]

use std::ascii::AsciiExt;

use tokenizer::{PeekableTokens, Token, Tokens};
use types::FromTokens;
use types::linestring::LineString;
use types::point::Point;
use types::polygon::Polygon;

mod tokenizer;
mod types;

pub enum WktItem {
    Point(Point),
    LineString(LineString),
    Polygon(Polygon),
}

impl WktItem {
    fn from_word_and_tokens(word: &str, tokens: &mut PeekableTokens)-> Result<Self, &'static str> {
        match word {
            "POINT" => {
                let x: Result<Point, _> = FromTokens::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "LINESTRING" => {
                let x: Result<LineString, _> = FromTokens::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "POLYGON" => {
                let x: Result<Polygon, _> = FromTokens::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            _ => Err("Invalid type encountered"),
        }
    }
}

pub struct Wkt {
    items: Vec<WktItem>
}

impl Wkt {
    fn new() -> Self {
        Wkt {items: vec![]}
    }

    fn add_item(&mut self, item: WktItem) {
        self.items.push(item);
    }

    fn from_str(wkt_str: &str) -> Result<Self, &'static str> {
        let tokens = Tokens::from_str(wkt_str);
        Wkt::from_tokens(tokens)
    }

    fn from_tokens(tokens: Tokens) -> Result<Self, &'static str> {
        let mut wkt = Wkt::new();
        let mut tokens = tokens.peekable();
        let word = match tokens.next() {
            Some(Token::Word(word)) => {
                if !word.is_ascii() {
                    return Err("Encountered non-ascii word");
                }
                word.to_ascii_uppercase()
            },
            None => return Ok(wkt),
            _ => return Err("Invalid WKT format"),
        };
        match WktItem::from_word_and_tokens(word.as_slice(), &mut tokens) {
            Ok(item) => wkt.add_item(item),
            Err(s) => return Err(s),
        }
        Ok(wkt)
    }
}

#[cfg(test)]
mod tests {
    use super::{Wkt, WktItem};

    #[test]
    fn empty_string() {
        let wkt = Wkt::from_str("").ok().unwrap();
        assert_eq!(0, wkt.items.len());
    }

    #[test]
    fn basic_point() {
        let mut wkt = Wkt::from_str("POINT (10 -20)").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        let point = match wkt.items.pop().unwrap() {
            WktItem::Point(point) => point,
            _ => unreachable!(),
        };
        assert_eq!(10.0, point.coord.x);
        assert_eq!(-20.0, point.coord.y);
        assert_eq!(None, point.coord.z);
        assert_eq!(None, point.coord.m);
    }

    #[test]
    fn basic_linestring() {
        let mut wkt = Wkt::from_str("LINESTRING (10 -20, -0 -0.5)").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        let linestring = match wkt.items.pop().unwrap() {
            WktItem::LineString(linestring) => linestring,
            _ => unreachable!(),
        };
        assert_eq!(2, linestring.coords.len());

        assert_eq!(10.0, linestring.coords[0].x);
        assert_eq!(-20.0, linestring.coords[0].y);
        assert_eq!(None, linestring.coords[0].z);
        assert_eq!(None, linestring.coords[0].m);

        assert_eq!(0.0, linestring.coords[1].x);
        assert_eq!(-0.5, linestring.coords[1].y);
        assert_eq!(None, linestring.coords[1].z);
        assert_eq!(None, linestring.coords[1].m);
    }

    #[test]
    fn basic_polygon() {
        let mut wkt = Wkt::from_str("POLYGON ((8 4, 4 0, 0 4, 8 4), (7 3, 4 1, 1 4, 7 3))").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        let linestring = match wkt.items.pop().unwrap() {
            WktItem::Polygon(linestring) => linestring,
            _ => unreachable!(),
        };
        assert_eq!(2, linestring.lines.len());
    }

    #[test]
    fn invalid_points() {
        Wkt::from_str("POINT ()").err().unwrap();
        Wkt::from_str("POINT (10)").err().unwrap();
        Wkt::from_str("POINT 10").err().unwrap();
        Wkt::from_str("POINT (10 -20 40)").err().unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>Add `no_colors` method<commit_after><|endoftext|>