<commit_before>use std::prelude::v1::*;

use std::cell::{RefCell};
use std::rc::{Rc, Weak};

use futures_core::{Future, Poll, Async, Stream};
use futures_core::task::{Context, Waker, LocalMap};
use futures_core::executor::{Executor, SpawnError};
use futures_core::never::Never;
use futures_util::stream::FuturesUnordered;

use thread::ThreadNotify;
use enter;

struct Task {
    fut: Box<Future<Item = (), Error = Never>>,
    map: LocalMap,
}

/// A single-threaded task pool.
///
/// This executor allows you to multiplex any number of tasks onto a single
/// thread. It's appropriate for strictly I/O-bound tasks that do very little
/// work in between I/O actions.
///
/// To get a handle to the pool that implements
/// [`Executor`](::futures_core::executor::Executor), use the
/// [`executor()`](LocalPool::executor) method. Because the executor is
/// single-threaded, it supports a special form of task spawning for non-`Send`
/// futures, via [`spvawn_local`](LocalExecutor::spawn_local).
pub struct LocalPool {
    pool: FuturesUnordered<Task>,
    incoming: Rc<Incoming>,
}

/// A handle to a [`LocalPool`](LocalPool) that implements
/// [`Executor`](::futures_core::executor::Executor).
pub struct LocalExecutor {
    incoming: Weak<Incoming>,
}

type Incoming = RefCell<Vec<Task>>;

// Set up and run a basic single-threaded executor loop, invocing `f` on each
// turn.
fn run_executor<T, F: FnMut(&Waker) -> Async<T>>(mut f: F) -> T {
    let _enter = enter()
        .expect("cannot execute `LocalPool` executor from within \
                 another executor");

    ThreadNotify::with_current(|thread| {
        let waker = &Waker::from(thread.clone());
        loop {
            if let Async::Ready(t) = f(waker) {
                return t;
            }
            thread.park();
        }
    })
}

impl LocalPool {
    /// Create a new, empty pool of tasks.
    pub fn new() -> LocalPool {
        LocalPool {
            pool: FuturesUnordered::new(),
            incoming: Default::default(),
        }
    }

    /// Get a clonable handle to the pool as an executor.
    pub fn executor(&self) -> LocalExecutor {
        LocalExecutor {
            incoming: Rc::downgrade(&self.incoming)
        }
    }

    /// Run all tasks in the pool to completion.
    ///
    /// The given executor, `exec`, is used as the default executor for any
    /// *newly*-spawned tasks. You can route these additional tasks back into
    /// the `LocalPool` by using its executor handle:
    ///
    /// ```
    /// # extern crate futures;
    /// # use futures::executor::LocalPool;
    ///
    /// # fn main() {
    /// let mut pool = LocalPool::new();
    /// let mut exec = pool.executor();
    ///
    /// // ... spawn some initial tasks using `exec.spawn()` or `exec.spawn_local()`
    ///
    /// // run *all* tasks in the pool to completion, including any newly-spawned ones.
    /// pool.run(&mut exec);
    /// # }
    /// ```
    ///
    /// The function will block the calling thread until *all* tasks in the pool
    /// are complete, including any spawned while running existing tasks.
    pub fn run(&mut self, exec: &mut Executor) {
        run_executor(|waker| self.poll_pool(waker, exec))
    }

    /// Runs all the tasks in the pull until the given future completes.
    ///
    /// The given executor, `exec`, is used as the default executor for any
    /// *newly*-spawned tasks. You can route these additional tasks back into
    /// the `LocalPool` by using its executor handle:
    ///
    /// ```
    /// # extern crate futures;
    /// # use futures::executor::LocalPool;
    /// # use futures::future::{Future, ok};
    ///
    /// # fn main() {
    /// let mut pool = LocalPool::new();
    /// let mut exec = pool.executor();
    /// # let my_app: Box<Future<Item = (), Error = ()>> = Box::new(ok(()));
    ///
    /// // run tasks in the pool until `my_app` completes, by default spawning
    /// // further tasks back onto the pool
    /// pool.run_until(my_app, &mut exec);
    /// # }
    /// ```
    ///
    /// The function will block the calling thread *only* until the future `f`
    /// completes; there may still be incomplete tasks in the pool, which will
    /// be inert after the call completes, but can continue with further use of
    /// `run` or `run_until`. While the function is running, however, all tasks
    /// in the pool will try to make progress.
    pub fn run_until<F>(&mut self, mut f: F, exec: &mut Executor) -> Result<F::Item, F::Error>
        where F: Future
    {
        // persistent state for the "main task"
        let mut main_map = LocalMap::new();

        run_executor(|waker| {
            {
                let mut main_cx = Context::new(&mut main_map, waker, exec);

                // if our main task is done, so are we
                match f.poll(&mut main_cx) {
                    Ok(Async::Ready(v)) => return Async::Ready(Ok(v)),
                    Err(err) => return Async::Ready(Err(err)),
                    _ => {}
                }
            }

            self.poll_pool(waker, exec);
            Async::Pending
        })
    }

    // Make maximal progress on the entire pool of spawned task, returning `Ready`
    // if the pool is empty and `Pending` if no further progress can be made.
    fn poll_pool(&mut self, waker: &Waker, exec: &mut Executor) -> Async<()> {
        // state for the FuturesUnordered, which will never be used
        let mut pool_map = LocalMap::new();
        let mut pool_cx = Context::new(&mut pool_map, waker, exec);

        loop {
            // empty the incoming queue of newly-spawned tasks
            {
                let mut incoming = self.incoming.borrow_mut();
                for task in incoming.drain(..) {
                    self.pool.push(task)
                }
            }

            if let Ok(ret) = self.pool.poll_next(&mut pool_cx) {
                // we queued up some new tasks; add them and poll again
                if !self.incoming.borrow().is_empty() {
                    continue;
                }

                // no queued tasks; we may be done
                match ret {
                    Async::Pending => return Async::Pending,
                    Async::Ready(None) => return Async::Ready(()),
                    _ => {}
                }
            }
        }
    }
}

/// Run a future to completion on the current thread.
///
/// This function will block the caller until the given future has completed.
/// Any tasks spawned onto the default executor will *also* be run on the
/// current thread, **but they may not complete before the function
/// returns**. Instead, once the starting future has completed, these other
/// tasks are simply dropped.
///
/// Use a [`LocalPool`](LocalPool) if you need finer-grained control over
/// spawned tasks.
pub fn block_on<F: Future>(f: F) -> Result<F::Item, F::Error> {
    let mut pool = LocalPool::new();
    let mut exec = pool.executor();

    // run our main future to completion
    let res = pool.run_until(f, &mut exec);
    // run any remainingspawned tasks to completion
    pool.run(&mut exec);

    res
}

impl Executor for LocalExecutor {
    fn spawn(&mut self, f: Box<Future<Item = (), Error = Never> + Send>) -> Result<(), SpawnError> {
        self.spawn_task(Task {
            fut: f,
            map: LocalMap::new(),
        })
    }

    fn status(&self) -> Result<(), SpawnError> {
        if self.incoming.upgrade().is_some() {
            Ok(())
        } else {
            Err(SpawnError::shutdown())
        }
    }
}

impl LocalExecutor {
    fn spawn_task(&self, task: Task) -> Result<(), SpawnError> {
        let incoming = self.incoming.upgrade().ok_or(SpawnError::shutdown())?;
        incoming.borrow_mut().push(task);
        Ok(())
    }

    /// Spawn a non-`Send` future onto the associated [`LocalPool`](LocalPool).
    pub fn spawn_local<F>(&mut self, f: F) -> Result<(), SpawnError>
        where F: Future<Item = (), Error = Never> + 'static
    {
        self.spawn_task(Task {
            fut: Box::new(f),
            map: LocalMap::new(),
        })
    }
}

impl Future for Task {
    type Item = ();
    type Error = Never;

    fn poll(&mut self, cx: &mut Context) -> Poll<(), Never> {
        self.fut.poll(&mut cx.with_locals(&mut self.map))
    }
}
<commit_msg>Typo fix<commit_after>use std::prelude::v1::*;

use std::cell::{RefCell};
use std::rc::{Rc, Weak};

use futures_core::{Future, Poll, Async, Stream};
use futures_core::task::{Context, Waker, LocalMap};
use futures_core::executor::{Executor, SpawnError};
use futures_core::never::Never;
use futures_util::stream::FuturesUnordered;

use thread::ThreadNotify;
use enter;

struct Task {
    fut: Box<Future<Item = (), Error = Never>>,
    map: LocalMap,
}

/// A single-threaded task pool.
///
/// This executor allows you to multiplex any number of tasks onto a single
/// thread. It's appropriate for strictly I/O-bound tasks that do very little
/// work in between I/O actions.
///
/// To get a handle to the pool that implements
/// [`Executor`](::futures_core::executor::Executor), use the
/// [`executor()`](LocalPool::executor) method. Because the executor is
/// single-threaded, it supports a special form of task spawning for non-`Send`
/// futures, via [`spawn_local`](LocalExecutor::spawn_local).
pub struct LocalPool {
    pool: FuturesUnordered<Task>,
    incoming: Rc<Incoming>,
}

/// A handle to a [`LocalPool`](LocalPool) that implements
/// [`Executor`](::futures_core::executor::Executor).
pub struct LocalExecutor {
    incoming: Weak<Incoming>,
}

type Incoming = RefCell<Vec<Task>>;

// Set up and run a basic single-threaded executor loop, invocing `f` on each
// turn.
fn run_executor<T, F: FnMut(&Waker) -> Async<T>>(mut f: F) -> T {
    let _enter = enter()
        .expect("cannot execute `LocalPool` executor from within \
                 another executor");

    ThreadNotify::with_current(|thread| {
        let waker = &Waker::from(thread.clone());
        loop {
            if let Async::Ready(t) = f(waker) {
                return t;
            }
            thread.park();
        }
    })
}

impl LocalPool {
    /// Create a new, empty pool of tasks.
    pub fn new() -> LocalPool {
        LocalPool {
            pool: FuturesUnordered::new(),
            incoming: Default::default(),
        }
    }

    /// Get a clonable handle to the pool as an executor.
    pub fn executor(&self) -> LocalExecutor {
        LocalExecutor {
            incoming: Rc::downgrade(&self.incoming)
        }
    }

    /// Run all tasks in the pool to completion.
    ///
    /// The given executor, `exec`, is used as the default executor for any
    /// *newly*-spawned tasks. You can route these additional tasks back into
    /// the `LocalPool` by using its executor handle:
    ///
    /// ```
    /// # extern crate futures;
    /// # use futures::executor::LocalPool;
    ///
    /// # fn main() {
    /// let mut pool = LocalPool::new();
    /// let mut exec = pool.executor();
    ///
    /// // ... spawn some initial tasks using `exec.spawn()` or `exec.spawn_local()`
    ///
    /// // run *all* tasks in the pool to completion, including any newly-spawned ones.
    /// pool.run(&mut exec);
    /// # }
    /// ```
    ///
    /// The function will block the calling thread until *all* tasks in the pool
    /// are complete, including any spawned while running existing tasks.
    pub fn run(&mut self, exec: &mut Executor) {
        run_executor(|waker| self.poll_pool(waker, exec))
    }

    /// Runs all the tasks in the pull until the given future completes.
    ///
    /// The given executor, `exec`, is used as the default executor for any
    /// *newly*-spawned tasks. You can route these additional tasks back into
    /// the `LocalPool` by using its executor handle:
    ///
    /// ```
    /// # extern crate futures;
    /// # use futures::executor::LocalPool;
    /// # use futures::future::{Future, ok};
    ///
    /// # fn main() {
    /// let mut pool = LocalPool::new();
    /// let mut exec = pool.executor();
    /// # let my_app: Box<Future<Item = (), Error = ()>> = Box::new(ok(()));
    ///
    /// // run tasks in the pool until `my_app` completes, by default spawning
    /// // further tasks back onto the pool
    /// pool.run_until(my_app, &mut exec);
    /// # }
    /// ```
    ///
    /// The function will block the calling thread *only* until the future `f`
    /// completes; there may still be incomplete tasks in the pool, which will
    /// be inert after the call completes, but can continue with further use of
    /// `run` or `run_until`. While the function is running, however, all tasks
    /// in the pool will try to make progress.
    pub fn run_until<F>(&mut self, mut f: F, exec: &mut Executor) -> Result<F::Item, F::Error>
        where F: Future
    {
        // persistent state for the "main task"
        let mut main_map = LocalMap::new();

        run_executor(|waker| {
            {
                let mut main_cx = Context::new(&mut main_map, waker, exec);

                // if our main task is done, so are we
                match f.poll(&mut main_cx) {
                    Ok(Async::Ready(v)) => return Async::Ready(Ok(v)),
                    Err(err) => return Async::Ready(Err(err)),
                    _ => {}
                }
            }

            self.poll_pool(waker, exec);
            Async::Pending
        })
    }

    // Make maximal progress on the entire pool of spawned task, returning `Ready`
    // if the pool is empty and `Pending` if no further progress can be made.
    fn poll_pool(&mut self, waker: &Waker, exec: &mut Executor) -> Async<()> {
        // state for the FuturesUnordered, which will never be used
        let mut pool_map = LocalMap::new();
        let mut pool_cx = Context::new(&mut pool_map, waker, exec);

        loop {
            // empty the incoming queue of newly-spawned tasks
            {
                let mut incoming = self.incoming.borrow_mut();
                for task in incoming.drain(..) {
                    self.pool.push(task)
                }
            }

            if let Ok(ret) = self.pool.poll_next(&mut pool_cx) {
                // we queued up some new tasks; add them and poll again
                if !self.incoming.borrow().is_empty() {
                    continue;
                }

                // no queued tasks; we may be done
                match ret {
                    Async::Pending => return Async::Pending,
                    Async::Ready(None) => return Async::Ready(()),
                    _ => {}
                }
            }
        }
    }
}

/// Run a future to completion on the current thread.
///
/// This function will block the caller until the given future has completed.
/// Any tasks spawned onto the default executor will *also* be run on the
/// current thread, **but they may not complete before the function
/// returns**. Instead, once the starting future has completed, these other
/// tasks are simply dropped.
///
/// Use a [`LocalPool`](LocalPool) if you need finer-grained control over
/// spawned tasks.
pub fn block_on<F: Future>(f: F) -> Result<F::Item, F::Error> {
    let mut pool = LocalPool::new();
    let mut exec = pool.executor();

    // run our main future to completion
    let res = pool.run_until(f, &mut exec);
    // run any remainingspawned tasks to completion
    pool.run(&mut exec);

    res
}

impl Executor for LocalExecutor {
    fn spawn(&mut self, f: Box<Future<Item = (), Error = Never> + Send>) -> Result<(), SpawnError> {
        self.spawn_task(Task {
            fut: f,
            map: LocalMap::new(),
        })
    }

    fn status(&self) -> Result<(), SpawnError> {
        if self.incoming.upgrade().is_some() {
            Ok(())
        } else {
            Err(SpawnError::shutdown())
        }
    }
}

impl LocalExecutor {
    fn spawn_task(&self, task: Task) -> Result<(), SpawnError> {
        let incoming = self.incoming.upgrade().ok_or(SpawnError::shutdown())?;
        incoming.borrow_mut().push(task);
        Ok(())
    }

    /// Spawn a non-`Send` future onto the associated [`LocalPool`](LocalPool).
    pub fn spawn_local<F>(&mut self, f: F) -> Result<(), SpawnError>
        where F: Future<Item = (), Error = Never> + 'static
    {
        self.spawn_task(Task {
            fut: Box::new(f),
            map: LocalMap::new(),
        })
    }
}

impl Future for Task {
    type Item = ();
    type Error = Never;

    fn poll(&mut self, cx: &mut Context) -> Poll<(), Never> {
        self.fut.poll(&mut cx.with_locals(&mut self.map))
    }
}
<|endoftext|>


<commit_before>use compact::CVec;
use descartes::{P2, V2, Segment, Area, Path, FiniteCurve, WithUniqueOrthogonal,
PointContainer, AreaError};
use land_use::buildings::BuildingStyle;
use itertools::Itertools;

use transport::transport_planning::RoadPrototype;

use planning::{Plan, PlanResult, Prototype, GestureIntent, Version};

pub mod interaction;

#[derive(Compact, Clone)]
pub enum ZoneIntent {
    LandUse(LandUse),
    MaxHeight(u8),
    SetBack(u8),
}

#[derive(Copy, Clone, PartialEq)]
pub enum LandUse {
    Residential,
    Commercial,
    Industrial,
    Agricultural,
    Recreational,
    Official,
}

#[derive(Compact, Clone)]
pub struct Lot {
    pub area: Area,
    pub land_uses: CVec<LandUse>,
    pub max_height: u8,
    pub set_back: u8,
    pub connection_points: CVec<(P2, V2)>,
}

impl Lot {
    pub fn center_point(&self) -> P2 {
        let outline = &self.area.primitives[0].boundary;
        P2::from_coordinates(
            (0..10u8)
                .into_iter()
                .fold(V2::new(0.0, 0.0), |sum_point, i| {
                    sum_point + outline.along(f32::from(i) * outline.length() / 10.0).coords
                }) / 10.0,
        )
    }
}

#[derive(Compact, Clone)]
pub struct BuildingIntent {
    pub lot: Lot,
    pub building_style: BuildingStyle,
}

#[derive(Compact, Clone)]
pub struct LotPrototype {
    pub lot: Lot,
    pub occupancy: LotOccupancy,
    pub based_on: Version,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum LotOccupancy {
    Vacant,
    Occupied(BuildingStyle),
}

pub fn calculate_prototypes(
    plan: &Plan,
    current_result: &PlanResult,
    based_on: Version,
) -> Result<Vec<Prototype>, AreaError> {
    let paved_area_areas = current_result
        .prototypes
        .values()
        .filter_map(|prototype| {
            if let Prototype::Road(RoadPrototype::PavedArea(ref shape)) = *prototype {
                Some(shape)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let building_prototypes = plan
        .gestures
        .values()
        .map(|gesture| {
            if let GestureIntent::Building(BuildingIntent {
                ref lot,
                building_style,
            }) = gesture.intent
            {
                let mut area = lot.area.clone();

                for paved_area_shape in &paved_area_areas {
                    let split = area.split(&paved_area_shape);

                    match split.a_minus_b() {
                        Ok(pieces) => if let Some(main_piece) = pieces
                            .disjoint()
                            .into_iter()
                            .find(|piece| piece.contains(lot.center_point()))
                        {
                            area = main_piece;
                        } else {
                            println!("No piece contains center");
                            return Ok(None);
                        },
                        Err(err) => return Err(err),
                    }
                }

                Ok(Some(Prototype::Lot(LotPrototype {
                    lot: Lot {
                        area,
                        ..lot.clone()
                    },
                    occupancy: LotOccupancy::Occupied(building_style),
                    based_on,
                })))
            } else {
                Ok(None)
            }
        })
        .collect::<Result<Vec<_>, _>>()?
        .into_iter()
        .filter_map(|maybe_proto| maybe_proto)
        .collect::<Vec<_>>();

    let vacant_lot_prototypes = {
        let building_areas = building_prototypes
            .iter()
            .filter_map(|prototype| {
                if let Prototype::Lot(LotPrototype {
                    occupancy: LotOccupancy::Occupied(_),
                    lot: Lot { ref area, .. },
                    ..
                }) = *prototype
                {
                    Some(area)
                } else {
                    None
                }
            })
            .collect::<Vec<_>>();

        let mut land_use_areas = plan
            .gestures
            .values()
            .filter_map(|gesture| {
                if let GestureIntent::Zone(ZoneIntent::LandUse(land_use)) = gesture.intent {
                    Some((land_use, &gesture.points))
                } else {
                    None
                }
            })
            .filter_map(|(land_use, points)| {
                Some((
                    land_use,
                    Area::new_simple(
                        Path::new(
                            points
                                .iter()
                                .chain(points.first())
                                .tuple_windows()
                                .filter_map(|(start, end)| Segment::line(*start, *end))
                                .collect(),
                        ).ok()?,
                    ).ok()?,
                ))
            })
            .collect::<Vec<_>>();

        let paved_or_built_area = paved_area_areas
            .iter()
            .chain(building_areas.iter())
            .try_fold(Area::new(CVec::new()), |union, piece| {
                union.split(piece).union()
            })?;

        land_use_areas = land_use_areas
            .into_iter()
            .map(|(land_use, shape)| {
                shape
                    .split(&paved_or_built_area)
                    .a_minus_b()
                    .map(|cut_shapes| {
                        cut_shapes
                            .disjoint()
                            .into_iter()
                            .map(|cut_shape| (land_use, cut_shape))
                            .collect::<Vec<_>>()
                    })
            })
            .collect::<Result<Vec<_>, _>>()?
            .into_iter()
            .flat_map(|areas| areas)
            .collect();

        land_use_areas
            .into_iter()
            .filter_map(|(land_use, area)| {
                let connection_points = area.primitives[0]
                    .boundary
                    .segments
                    .iter()
                    .flat_map(|segment| {
                        let length = segment.length();
                        (&[0.25, 0.5, 0.75])
                            .iter()
                            .map(|ratio| {
                                (
                                    segment.along(length * ratio),
                                    -segment.direction_along(length * ratio).orthogonal(),
                                )
                            })
                            .collect::<Vec<_>>()
                    })
                    .filter(|&(point, _dir)| {
                        // TODO: this is a horribly slow way to find connection points
                        paved_area_areas
                            .iter()
                            .any(|paved_area| paved_area.contains(point))
                    })
                    .collect::<CVec<_>>();

                if connection_points.is_empty() {
                    println!("No connection point found");
                    None
                } else {
                    Some(Prototype::Lot(LotPrototype {
                        lot: Lot {
                            land_uses: vec![land_use].into(),
                            max_height: 0,
                            set_back: 0,
                            connection_points,
                            area,
                        },
                        occupancy: LotOccupancy::Vacant,
                        based_on,
                    }))
                }
            })
            .collect::<Vec<_>>()
    };

    Ok(vacant_lot_prototypes
        .into_iter()
        .chain(building_prototypes)
        .collect())
}
<commit_msg>Subtract building gestures instead of building prototypes<commit_after>use compact::CVec;
use descartes::{P2, V2, Segment, Area, Path, FiniteCurve, WithUniqueOrthogonal,
PointContainer, AreaError};
use land_use::buildings::BuildingStyle;
use itertools::Itertools;

use transport::transport_planning::RoadPrototype;

use planning::{Plan, PlanResult, Prototype, GestureIntent, Version};

pub mod interaction;

#[derive(Compact, Clone)]
pub enum ZoneIntent {
    LandUse(LandUse),
    MaxHeight(u8),
    SetBack(u8),
}

#[derive(Copy, Clone, PartialEq)]
pub enum LandUse {
    Residential,
    Commercial,
    Industrial,
    Agricultural,
    Recreational,
    Official,
}

#[derive(Compact, Clone)]
pub struct Lot {
    pub area: Area,
    pub land_uses: CVec<LandUse>,
    pub max_height: u8,
    pub set_back: u8,
    pub connection_points: CVec<(P2, V2)>,
}

impl Lot {
    pub fn center_point(&self) -> P2 {
        let outline = &self.area.primitives[0].boundary;
        P2::from_coordinates(
            (0..10u8)
                .into_iter()
                .fold(V2::new(0.0, 0.0), |sum_point, i| {
                    sum_point + outline.along(f32::from(i) * outline.length() / 10.0).coords
                }) / 10.0,
        )
    }
}

#[derive(Compact, Clone)]
pub struct BuildingIntent {
    pub lot: Lot,
    pub building_style: BuildingStyle,
}

#[derive(Compact, Clone)]
pub struct LotPrototype {
    pub lot: Lot,
    pub occupancy: LotOccupancy,
    pub based_on: Version,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum LotOccupancy {
    Vacant,
    Occupied(BuildingStyle),
}

pub fn calculate_prototypes(
    plan: &Plan,
    current_result: &PlanResult,
    based_on: Version,
) -> Result<Vec<Prototype>, AreaError> {
    let paved_area_areas = current_result
        .prototypes
        .values()
        .filter_map(|prototype| {
            if let Prototype::Road(RoadPrototype::PavedArea(ref shape)) = *prototype {
                Some(shape)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let building_prototypes = plan
        .gestures
        .values()
        .map(|gesture| {
            if let GestureIntent::Building(BuildingIntent {
                ref lot,
                building_style,
            }) = gesture.intent
            {
                let mut area = lot.area.clone();

                for paved_area_shape in &paved_area_areas {
                    let split = area.split(&paved_area_shape);

                    match split.a_minus_b() {
                        Ok(pieces) => if let Some(main_piece) = pieces
                            .disjoint()
                            .into_iter()
                            .find(|piece| piece.contains(lot.center_point()))
                        {
                            area = main_piece;
                        } else {
                            println!("No piece contains center");
                            return Ok(None);
                        },
                        Err(err) => return Err(err),
                    }
                }

                Ok(Some(Prototype::Lot(LotPrototype {
                    lot: Lot {
                        area,
                        ..lot.clone()
                    },
                    occupancy: LotOccupancy::Occupied(building_style),
                    based_on,
                })))
            } else {
                Ok(None)
            }
        })
        .collect::<Result<Vec<_>, _>>()?
        .into_iter()
        .filter_map(|maybe_proto| maybe_proto)
        .collect::<Vec<_>>();

    let vacant_lot_prototypes = {
        let building_areas = plan
        .gestures
        .values()
        .filter_map(|gesture| {
            if let GestureIntent::Building(BuildingIntent {
                lot: Lot { ref area, .. },..
            }) = gesture.intent
            {
                Some(area)
            } else {
                None
            }
        }).collect::<Vec<_>>();

        let mut land_use_areas = plan
            .gestures
            .values()
            .filter_map(|gesture| {
                if let GestureIntent::Zone(ZoneIntent::LandUse(land_use)) = gesture.intent {
                    Some((land_use, &gesture.points))
                } else {
                    None
                }
            })
            .filter_map(|(land_use, points)| {
                Some((
                    land_use,
                    Area::new_simple(
                        Path::new(
                            points
                                .iter()
                                .chain(points.first())
                                .tuple_windows()
                                .filter_map(|(start, end)| Segment::line(*start, *end))
                                .collect(),
                        ).ok()?,
                    ).ok()?,
                ))
            })
            .collect::<Vec<_>>();

        let paved_or_built_area = paved_area_areas
            .clone()
            .into_iter()
            .chain(building_areas)
            .try_fold(Area::new(CVec::new()), |union, piece| {
                union.split(piece).union()
            })?;

        land_use_areas = land_use_areas
            .into_iter()
            .map(|(land_use, shape)| {
                shape
                    .split(&paved_or_built_area)
                    .a_minus_b()
                    .map(|cut_shapes| {
                        cut_shapes
                            .disjoint()
                            .into_iter()
                            .map(|cut_shape| (land_use, cut_shape))
                            .collect::<Vec<_>>()
                    })
            })
            .collect::<Result<Vec<_>, _>>()?
            .into_iter()
            .flat_map(|areas| areas)
            .collect();

        land_use_areas
            .into_iter()
            .filter_map(|(land_use, area)| {
                let connection_points = area.primitives[0]
                    .boundary
                    .segments
                    .iter()
                    .flat_map(|segment| {
                        let length = segment.length();
                        (&[0.25, 0.5, 0.75])
                            .iter()
                            .map(|ratio| {
                                (
                                    segment.along(length * ratio),
                                    -segment.direction_along(length * ratio).orthogonal(),
                                )
                            })
                            .collect::<Vec<_>>()
                    })
                    .filter(|&(point, _dir)| {
                        // TODO: this is a horribly slow way to find connection points
                        paved_area_areas
                            .iter()
                            .any(|paved_area| paved_area.contains(point))
                    })
                    .collect::<CVec<_>>();

                if connection_points.is_empty() {
                    println!("No connection point found");
                    None
                } else {
                    Some(Prototype::Lot(LotPrototype {
                        lot: Lot {
                            land_uses: vec![land_use].into(),
                            max_height: 0,
                            set_back: 0,
                            connection_points,
                            area,
                        },
                        occupancy: LotOccupancy::Vacant,
                        based_on,
                    }))
                }
            })
            .collect::<Vec<_>>()
    };

    Ok(vacant_lot_prototypes
        .into_iter()
        .chain(building_prototypes)
        .collect())
}
<|endoftext|>


<commit_before><commit_msg>fix musl build panic<commit_after><|endoftext|>


<commit_before>/*
Module: task

Task management.

An executing Rust program consists of a tree of tasks, each with their own
stack, and sole ownership of their allocated heap data. Tasks communicate
with each other using ports and channels.

When a task fails, that failure will propagate to its parent (the task
that spawned it) and the parent will fail as well. The reverse is not
true: when a parent task fails its children will continue executing. When
the root (main) task fails, all tasks fail, and then so does the entire
process.

A task may remove itself from this failure propagation mechanism by
calling the <unsupervise> function, after which failure will only
result in the termination of that task.

Tasks may execute in parallel and are scheduled automatically by the runtime.

Example:

> spawn("Hello, World", fn (&&msg: str) {
>   log msg;
> });

*/
import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task;
export spawn;
export spawn_notify;
export spawn_joinable;

native "rust-intrinsic" mod rustrt {
    // these must run on the Rust stack so that they can swap stacks etc:
    fn task_sleep(time_in_us: uint);
}

native "c-stack-cdecl" mod rustrt2 = "rustrt" {
    // these can run on the C stack:
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;

    fn set_min_stack(stack_size: uint);

    fn new_task() -> task_id;
    fn drop_task(task_id: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);

    fn start_task(id: task, closure: *u8);

}

/* Section: Types */

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt2::drop_task(task); }

type task_id = int;

/*
Type: task

A handle to a task
*/
type task = task_id;

/*
Type: joinable_task

A task that sends notification upon termination
*/
type joinable_task = (task, comm::port<task_notification>);

/*
Tag: task_result

Indicates the manner in which a task exited
*/
tag task_result {
    /* Variant: tr_success */
    tr_success;
    /* Variant: tr_failure */
    tr_failure;
}

/*
Tag: task_notification

Message sent upon task exit to indicate normal or abnormal termination
*/
tag task_notification {
    /* Variant: exit */
    exit(task, task_result);
}

/* Section: Operations */

/*
Type: get_task

Retreives a handle to the currently executing task
*/
fn get_task() -> task { rustrt2::get_task_id() }

/*
Function: sleep

Hints the scheduler to yield this task for a specified ammount of time.

Parameters:

time_in_us - maximum number of microseconds to yield control for
*/
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

/*
Function: yield

Yield control to the task scheduler

The scheduler may schedule another task to execute.
*/
fn yield() { sleep(1u) }

/*
Function: join

Wait for a child task to exit

The child task must have been spawned with <spawn_joinable>, which
produces a notification port that the child uses to communicate its
exit status.

Returns:

A task_result indicating whether the task terminated normally or failed
*/
fn join(task_port: joinable_task) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

/*
Function: unsupervise

Detaches this task from its parent in the task tree

An unsupervised task will not propagate its failure up the task tree
*/
fn unsupervise() { ret sys::unsupervise(); }

/*
Function: pin

Pins the current task and future child tasks to a single scheduler thread
*/
fn pin() { rustrt2::pin_task(); }

/*
Function: unpin

Unpin the current task and future child tasks
*/
fn unpin() { rustrt2::unpin_task(); }

/*
Function: set_min_stack

Set the minimum stack size (in bytes) for tasks spawned in the future.

This function has global effect and should probably not be used.
*/
fn set_min_stack(stack_size: uint) { rustrt2::set_min_stack(stack_size); }

/*
Function: spawn

Creates and executes a new child task

Sets up a new task with its own call stack and schedules it to be executed.
Upon execution the new task will call function `f` with the provided
argument `data`.

Function `f` is a bare function, meaning it may not close over any data, as do
shared functions (fn@) and lambda blocks. `data` must be a uniquely owned
type; it is moved into the new task and thus can no longer be accessed
locally.

Parameters:

data - A unique-type value to pass to the new task
f - A function to execute in the new task

Returns:

A handle to the new task
*/
fn spawn<uniq T>(-data: T, f: fn(T)) -> task {
    spawn_inner(data, f, none)
}

/*
Function: spawn_notify

Create and execute a new child task, requesting notification upon its
termination

Immediately before termination, either on success or failure, the spawned
task will send a <task_notification> message on the provided channel.
*/
fn spawn_notify<uniq T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner(data, f, some(notify))
}

/*
Function: spawn_joinable

Create and execute a task which can later be joined with the <join> function

This is a convenience wrapper around spawn_notify which, when paired
with <join> can be easily used to spawn a task then wait for it to
complete.
*/
fn spawn_joinable<uniq T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner<uniq T>(-data: T, f: fn(T),
                          notify: option<comm::chan<task_notification>>)
    -> task unsafe {

    fn wrapper<uniq T>(-data: *u8, f: fn(T)) unsafe {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task unsafe {
    let id = rustrt2::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt2::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt2::migrate_alloc(cast(raw_thunk.env), id);
    rustrt2::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Clean up std::task<commit_after>/*
Module: task

Task management.

An executing Rust program consists of a tree of tasks, each with their own
stack, and sole ownership of their allocated heap data. Tasks communicate
with each other using ports and channels.

When a task fails, that failure will propagate to its parent (the task
that spawned it) and the parent will fail as well. The reverse is not
true: when a parent task fails its children will continue executing. When
the root (main) task fails, all tasks fail, and then so does the entire
process.

A task may remove itself from this failure propagation mechanism by
calling the <unsupervise> function, after which failure will only
result in the termination of that task.

Tasks may execute in parallel and are scheduled automatically by the runtime.

Example:

> spawn("Hello, World", fn (&&msg: str) {
>   log msg;
> });

*/
import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task;
export spawn;
export spawn_notify;
export spawn_joinable;

native "rust-intrinsic" mod rusti {
    // these must run on the Rust stack so that they can swap stacks etc:
    fn task_sleep(time_in_us: uint);
}

native "c-stack-cdecl" mod rustrt = "rustrt" {
    // these can run on the C stack:
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;

    fn set_min_stack(stack_size: uint);

    fn new_task() -> task_id;
    fn drop_task(task_id: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);

    fn start_task(id: task, closure: *u8);

}

/* Section: Types */

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }

type task_id = int;

/*
Type: task

A handle to a task
*/
type task = task_id;

/*
Type: joinable_task

A task that sends notification upon termination
*/
type joinable_task = (task, comm::port<task_notification>);

/*
Tag: task_result

Indicates the manner in which a task exited
*/
tag task_result {
    /* Variant: tr_success */
    tr_success;
    /* Variant: tr_failure */
    tr_failure;
}

/*
Tag: task_notification

Message sent upon task exit to indicate normal or abnormal termination
*/
tag task_notification {
    /* Variant: exit */
    exit(task, task_result);
}

/* Section: Operations */

/*
Type: get_task

Retreives a handle to the currently executing task
*/
fn get_task() -> task { rustrt::get_task_id() }

/*
Function: sleep

Hints the scheduler to yield this task for a specified ammount of time.

Parameters:

time_in_us - maximum number of microseconds to yield control for
*/
fn sleep(time_in_us: uint) { ret rusti::task_sleep(time_in_us); }

/*
Function: yield

Yield control to the task scheduler

The scheduler may schedule another task to execute.
*/
fn yield() { sleep(1u) }

/*
Function: join

Wait for a child task to exit

The child task must have been spawned with <spawn_joinable>, which
produces a notification port that the child uses to communicate its
exit status.

Returns:

A task_result indicating whether the task terminated normally or failed
*/
fn join(task_port: joinable_task) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

/*
Function: unsupervise

Detaches this task from its parent in the task tree

An unsupervised task will not propagate its failure up the task tree
*/
fn unsupervise() { ret sys::unsupervise(); }

/*
Function: pin

Pins the current task and future child tasks to a single scheduler thread
*/
fn pin() { rustrt::pin_task(); }

/*
Function: unpin

Unpin the current task and future child tasks
*/
fn unpin() { rustrt::unpin_task(); }

/*
Function: set_min_stack

Set the minimum stack size (in bytes) for tasks spawned in the future.

This function has global effect and should probably not be used.
*/
fn set_min_stack(stack_size: uint) { rustrt::set_min_stack(stack_size); }

/*
Function: spawn

Creates and executes a new child task

Sets up a new task with its own call stack and schedules it to be executed.
Upon execution the new task will call function `f` with the provided
argument `data`.

Function `f` is a bare function, meaning it may not close over any data, as do
shared functions (fn@) and lambda blocks. `data` must be a uniquely owned
type; it is moved into the new task and thus can no longer be accessed
locally.

Parameters:

data - A unique-type value to pass to the new task
f - A function to execute in the new task

Returns:

A handle to the new task
*/
fn spawn<uniq T>(-data: T, f: fn(T)) -> task {
    spawn_inner(data, f, none)
}

/*
Function: spawn_notify

Create and execute a new child task, requesting notification upon its
termination

Immediately before termination, either on success or failure, the spawned
task will send a <task_notification> message on the provided channel.
*/
fn spawn_notify<uniq T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner(data, f, some(notify))
}

/*
Function: spawn_joinable

Create and execute a task which can later be joined with the <join> function

This is a convenience wrapper around spawn_notify which, when paired
with <join> can be easily used to spawn a task then wait for it to
complete.
*/
fn spawn_joinable<uniq T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner<uniq T>(-data: T, f: fn(T),
                          notify: option<comm::chan<task_notification>>)
    -> task unsafe {

    fn wrapper<uniq T>(-data: *u8, f: fn(T)) unsafe {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task unsafe {
    let id = rustrt::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>/*
Module: uint
*/

/*
Function: min_value

Return the minimal value for an uint.

This is always 0
*/
pure fn min_value() -> uint { ret 0u; }

/*
Function: max_value

Return the maximal value for an uint.

This is 2^wordsize - 1
*/
pure fn max_value() -> uint {
     ret 0u - 1u;
}

/* Function: add */
pure fn add(x: uint, y: uint) -> uint { ret x + y; }

/* Function: sub */
pure fn sub(x: uint, y: uint) -> uint { ret x - y; }

/* Function: mul */
pure fn mul(x: uint, y: uint) -> uint { ret x * y; }

/* Function: div */
pure fn div(x: uint, y: uint) -> uint { ret x / y; }

/**
 * Divide two numbers, return the result, rounded up.
 */
pure fn div_ceil(x: uint, y: uint) -> uint {
    let div = div(x, y);
    if x % y == 0u { ret div;}
    else { ret div + 1u; }
}

/**
 * Divide two numbers, return the result, rounded to the closest integer.
 */
pure fn div_round(x: uint, y: uint) -> uint {
    let div = div(x, y);
    if x % y * 2u  < y { ret div;}
    else { ret div + 1u; }
}

/**
 * Divide two numbers, return the result, rounded down.
 */
pure fn div_floor(x: uint, y: uint) -> uint { ret x / y; }

/* Function: rem */
pure fn rem(x: uint, y: uint) -> uint { ret x % y; }

/* Predicate: lt */
pure fn lt(x: uint, y: uint) -> bool { ret x < y; }

/* Predicate: le */
pure fn le(x: uint, y: uint) -> bool { ret x <= y; }

/* Predicate: eq */
pure fn eq(x: uint, y: uint) -> bool { ret x == y; }

/* Predicate: ne */
pure fn ne(x: uint, y: uint) -> bool { ret x != y; }

/* Predicate: ge */
pure fn ge(x: uint, y: uint) -> bool { ret x >= y; }

/* Predicate: gt */
pure fn gt(x: uint, y: uint) -> bool { ret x > y; }

/*
Function: range

Iterate over the range [`lo`..`hi`)
*/
fn range(lo: uint, hi: uint, it: block(uint)) {
    let i = lo;
    while i < hi { it(i); i += 1u; }
}

/*
Function: next_power_of_two

Returns the smallest power of 2 greater than or equal to `n`
*/
fn next_power_of_two(n: uint) -> uint {
    let halfbits: uint = sys::size_of::<uint>() * 4u;
    let tmp: uint = n - 1u;
    let shift: uint = 1u;
    while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; }
    ret tmp + 1u;
}

/*
Function: parse_buf

Parse a buffer of bytes

Parameters:

buf - A byte buffer
radix - The base of the number

Failure:

buf must not be empty
*/
fn parse_buf(buf: [u8], radix: uint) -> uint {
    if vec::len::<u8>(buf) == 0u {
        log_err "parse_buf(): buf is empty";
        fail;
    }
    let i = vec::len::<u8>(buf) - 1u;
    let power = 1u;
    let n = 0u;
    while true {
        let digit = char::to_digit(buf[i] as char);
        if (digit as uint) >= radix {
            fail;
        }
        n += (digit as uint) * power;
        power *= radix;
        if i == 0u { ret n; }
        i -= 1u;
    }
    fail;
}

/*
Function: from_str

Parse a string to an int

Failure:

s must not be empty
*/
fn from_str(s: str) -> uint { parse_buf(str::bytes(s), 10u) }

/*
Function: to_str

Convert to a string in a given base
*/
fn to_str(num: uint, radix: uint) -> str {
    let n = num;
    assert (0u < radix && radix <= 16u);
    fn digit(n: uint) -> char {
        ret alt n {
              0u { '0' }
              1u { '1' }
              2u { '2' }
              3u { '3' }
              4u { '4' }
              5u { '5' }
              6u { '6' }
              7u { '7' }
              8u { '8' }
              9u { '9' }
              10u { 'a' }
              11u { 'b' }
              12u { 'c' }
              13u { 'd' }
              14u { 'e' }
              15u { 'f' }
              _ { fail }
            };
    }
    if n == 0u { ret "0"; }
    let s: str = "";
    while n != 0u {
        s += str::unsafe_from_byte(digit(n % radix) as u8);
        n /= radix;
    }
    let s1: str = "";
    let len: uint = str::byte_len(s);
    while len != 0u { len -= 1u; s1 += str::unsafe_from_byte(s[len]); }
    ret s1;
}

/*
Function: str

Convert to a string
*/
fn str(i: uint) -> str { ret to_str(i, 10u); }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>[Docfixes + feature] lib/uint.rs: Applied review suggesions, took the opportunity to add function loop<commit_after>/*
Module: uint
*/

/*
Function: min_value

Return the minimal value for an uint.

This is always 0
*/
pure fn min_value() -> uint { ret 0u; }

/*
Function: max_value

Return the maximal value for an uint.

This is 2^wordsize - 1
*/
pure fn max_value() -> uint {
     ret 0u - 1u;
}

/* Function: add */
pure fn add(x: uint, y: uint) -> uint { ret x + y; }

/* Function: sub */
pure fn sub(x: uint, y: uint) -> uint { ret x - y; }

/* Function: mul */
pure fn mul(x: uint, y: uint) -> uint { ret x * y; }

/* Function: div */
pure fn div(x: uint, y: uint) -> uint { ret x / y; }

/* Function: div_ceil

   Divide two numbers, return the result, rounded up.

   Parameters:
   x - an integer
   y - an integer distinct from 0u

   Return:
    The smallest integer `q` such that `x/y <= q`.
*/
pure fn div_ceil(x: uint, y: uint) -> uint {
    let div = div(x, y);
    if x % y == 0u { ret div;}
    else { ret div + 1u; }
}

/* Function: div_ceil

   Divide two numbers, return the result, rounded to the closest integer.

   Parameters:
   x - an integer
   y - an integer distinct from 0u

   Return:
    The integer `q` closest to `x/y`.
*/
pure fn div_round(x: uint, y: uint) -> uint {
    let div = div(x, y);
    if x % y * 2u  < y { ret div;}
    else { ret div + 1u; }
}

/* Function: div_ceil

   Divide two numbers, return the result, rounded down.

   Parameters:
   x - an integer
   y - an integer distinct from 0u

   Note: This is the same function as `div`.

   Return:
    The smallest integer `q` such that `x/y <= q`. This
   is either `x/y` or `x/y + 1`.
*/
pure fn div_floor(x: uint, y: uint) -> uint { ret x / y; }

/* Function: rem */
pure fn rem(x: uint, y: uint) -> uint { ret x % y; }

/* Predicate: lt */
pure fn lt(x: uint, y: uint) -> bool { ret x < y; }

/* Predicate: le */
pure fn le(x: uint, y: uint) -> bool { ret x <= y; }

/* Predicate: eq */
pure fn eq(x: uint, y: uint) -> bool { ret x == y; }

/* Predicate: ne */
pure fn ne(x: uint, y: uint) -> bool { ret x != y; }

/* Predicate: ge */
pure fn ge(x: uint, y: uint) -> bool { ret x >= y; }

/* Predicate: gt */
pure fn gt(x: uint, y: uint) -> bool { ret x > y; }

/*
Function: range

Iterate over the range [`lo`..`hi`)
*/
fn range(lo: uint, hi: uint, it: block(uint)) {
    let i = lo;
    while i < hi { it(i); i += 1u; }
}

/*
Function: loop

Iterate over the range [`lo`..`hi`), or stop when requested

Parameters:
lo - The integer at which to start the loop (included)
hi - The integer at which to stop the loop (excluded)
it - A block to execute with each consecutive integer of the range.
Return `true` to continue, `false` to stop.

Returns:

`true` If execution proceeded correctly, `false` if it was interrupted,
that is if `it` returned `false` at any point.
*/
fn loop(lo: uint, hi: uint, it: block(uint) -> bool) -> bool {
    let i = lo;
    while i < hi {
        if (!it(i)) { ret false; }
        i += 1u;
    }
    ret true;
}

/*
Function: next_power_of_two

Returns the smallest power of 2 greater than or equal to `n`
*/
fn next_power_of_two(n: uint) -> uint {
    let halfbits: uint = sys::size_of::<uint>() * 4u;
    let tmp: uint = n - 1u;
    let shift: uint = 1u;
    while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; }
    ret tmp + 1u;
}

/*
Function: parse_buf

Parse a buffer of bytes

Parameters:

buf - A byte buffer
radix - The base of the number

Failure:

buf must not be empty
*/
fn parse_buf(buf: [u8], radix: uint) -> uint {
    if vec::len::<u8>(buf) == 0u {
        log_err "parse_buf(): buf is empty";
        fail;
    }
    let i = vec::len::<u8>(buf) - 1u;
    let power = 1u;
    let n = 0u;
    while true {
        let digit = char::to_digit(buf[i] as char);
        if (digit as uint) >= radix {
            fail;
        }
        n += (digit as uint) * power;
        power *= radix;
        if i == 0u { ret n; }
        i -= 1u;
    }
    fail;
}

/*
Function: from_str

Parse a string to an int

Failure:

s must not be empty
*/
fn from_str(s: str) -> uint { parse_buf(str::bytes(s), 10u) }

/*
Function: to_str

Convert to a string in a given base
*/
fn to_str(num: uint, radix: uint) -> str {
    let n = num;
    assert (0u < radix && radix <= 16u);
    fn digit(n: uint) -> char {
        ret alt n {
              0u { '0' }
              1u { '1' }
              2u { '2' }
              3u { '3' }
              4u { '4' }
              5u { '5' }
              6u { '6' }
              7u { '7' }
              8u { '8' }
              9u { '9' }
              10u { 'a' }
              11u { 'b' }
              12u { 'c' }
              13u { 'd' }
              14u { 'e' }
              15u { 'f' }
              _ { fail }
            };
    }
    if n == 0u { ret "0"; }
    let s: str = "";
    while n != 0u {
        s += str::unsafe_from_byte(digit(n % radix) as u8);
        n /= radix;
    }
    let s1: str = "";
    let len: uint = str::byte_len(s);
    while len != 0u { len -= 1u; s1 += str::unsafe_from_byte(s[len]); }
    ret s1;
}

/*
Function: str

Convert to a string
*/
fn str(i: uint) -> str { ret to_str(i, 10u); }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(stainless)]

extern crate stainless;
extern crate athena;

mod test {
    use athena::score;
    use athena::score::Match;

    pub fn do_new_score<'a>(choice: &'a String, query: &str) -> Option<Match<'a>> {
       let query_stirng = query.to_string();
       score::score(&choice,  &query_stirng)
    }

    pub fn match_quality(choice: &str, query: &str) -> f32 {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Quality(quality) = m.unwrap().quality;
        quality
    }

    pub fn match_substring(choice: &str, query: &str) -> (usize, usize) {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Substring(start,end) = m.unwrap().range;
        (start,end)
    }

    pub use athena::score::Substring;
    pub use athena::score::Quality;

    describe! score_and_match {
        it "scores_greater_than_zero_and_shows_match" {
            let range =  match_substring("a", "a");
            assert_eq!(range, (0,1));
        }

        it "match_range_ends_in_non_inclusive" {
            //                           0123456789
            let range = match_substring("ana.gemspec", "asp");
            assert_eq!(range, (2,9));
        }
    }

    describe! score_test {
        describe! mismatch {
            it "no_match_when_the_choice_is_emtpy" {
                let input = "".to_string();
                assert_eq!(do_new_score(&input, "a"), None);
            }

            it "no_match_if_query_is_longer_than_the_choice" {
                let input = "a".to_string();
                assert_eq!(do_new_score(&input, "aaaaa"), None);
            }

            it "no_match_if_query_does_not_match_at_all" {
                let input = "a".to_string();
                assert_eq!(do_new_score(&input, "b"), None);
            }

            it "repeated_character_does_not_match" {
                let input = "a".to_string();
                assert_eq!(do_new_score(&input,  "aa"), None);
            }
        }

        describe! empty_query {
            it "scores_one_when_the_query_is_empty" {
                assert_eq!(match_quality("a", ""), 1.0);
            }
        }

        describe! match_quality {
            it "scores_greater_than_zero_if_query_matches_choice" {
                assert!(match_quality("a", "a") > 0.0);
                assert!(match_quality("ab", "a") > 0.0);
                assert!(match_quality("ba", "a") > 0.0);
                assert!(match_quality("bab", "a") > 0.0);
                assert!(match_quality("babababab", "aaaa") > 0.0);
            }

            it "matches_punctuation" {
                assert!(match_quality("/! symbols $^", "/!$^") > 0.0);
            }

            it "normalizes_score_based_on_length" {
                assert_eq!(match_quality("a", "a"), 1.0);
                assert_eq!(match_quality("ab", "ab"), 0.5);
                assert_eq!(match_quality("a long string", "a long string"), 1.0 / "a long string".len() as f32);
                assert_eq!(match_quality("spec/search_spec.rb", "sear"), 1.0 / "spec/search_spec.rb".len() as f32)
            }

            it "scores_higher_for_better_matches" {
                assert!(match_quality("ahtena.gemspec", "asp") > match_quality("algorithm4_spec.rb", "asp"));
                assert!(match_quality("readme.md", "em") > match_quality("benchmark.rb", "em"));
                assert!(match_quality("search.rb", "sear") > match_quality("spec/search_spec.rb", "sear"));
            }

            it "scores_shorter_matches_higher" {
                assert!(match_quality("fbb", "fbb") > match_quality("foo bar baz", "fbb"));
                assert!(match_quality("foo", "foo") > match_quality("longer foo", "foo"));
                assert!(match_quality("foo", "foo") > match_quality("foo longer", "foo"));
                assert!(match_quality("1/2/3/4", "1/2/3") > match_quality("1/9/2/3/4", "1/2/3"));
            }

            it "scores_the_tighter_of_two_matches_regardless_of_order" {
                let beginning = "121padding2";
                let end = "1padding212";
                assert_eq!(match_quality(beginning, "12"), match_quality(end, "12"));
            }

            it "tighter_matches_score_higher" {
                assert!(match_quality("long 12 long", "12") > match_quality("1 long 2", "12"));
            }
        }
    }
}
<commit_msg>Renames helper function in tests.<commit_after>#![feature(plugin)]
#![plugin(stainless)]

extern crate stainless;
extern crate athena;

mod test {
    use athena::score;
    use athena::score::Match;

    pub fn do_score<'a>(choice: &'a String, query: &str) -> Option<Match<'a>> {
       let query_stirng = query.to_string();
       score::score(&choice,  &query_stirng)
    }

    pub fn match_quality(choice: &str, query: &str) -> f32 {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Quality(quality) = m.unwrap().quality;
        quality
    }

    pub fn match_substring(choice: &str, query: &str) -> (usize, usize) {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Substring(start,end) = m.unwrap().range;
        (start,end)
    }

    pub use athena::score::Substring;
    pub use athena::score::Quality;

    describe! score_and_match {
        it "scores_greater_than_zero_and_shows_match" {
            let range =  match_substring("a", "a");
            assert_eq!(range, (0,1));
        }

        it "match_range_ends_in_non_inclusive" {
            //                           0123456789
            let range = match_substring("ana.gemspec", "asp");
            assert_eq!(range, (2,9));
        }
    }

    describe! score_test {
        describe! mismatch {
            it "no_match_when_the_choice_is_emtpy" {
                let input = "".to_string();
                assert_eq!(do_score(&input, "a"), None);
            }

            it "no_match_if_query_is_longer_than_the_choice" {
                let input = "a".to_string();
                assert_eq!(do_score(&input, "aaaaa"), None);
            }

            it "no_match_if_query_does_not_match_at_all" {
                let input = "a".to_string();
                assert_eq!(do_score(&input, "b"), None);
            }

            it "repeated_character_does_not_match" {
                let input = "a".to_string();
                assert_eq!(do_score(&input,  "aa"), None);
            }
        }

        describe! empty_query {
            it "scores_one_when_the_query_is_empty" {
                assert_eq!(match_quality("a", ""), 1.0);
            }
        }

        describe! match_quality {
            it "scores_greater_than_zero_if_query_matches_choice" {
                assert!(match_quality("a", "a") > 0.0);
                assert!(match_quality("ab", "a") > 0.0);
                assert!(match_quality("ba", "a") > 0.0);
                assert!(match_quality("bab", "a") > 0.0);
                assert!(match_quality("babababab", "aaaa") > 0.0);
            }

            it "matches_punctuation" {
                assert!(match_quality("/! symbols $^", "/!$^") > 0.0);
            }

            it "normalizes_score_based_on_length" {
                assert_eq!(match_quality("a", "a"), 1.0);
                assert_eq!(match_quality("ab", "ab"), 0.5);
                assert_eq!(match_quality("a long string", "a long string"), 1.0 / "a long string".len() as f32);
                assert_eq!(match_quality("spec/search_spec.rb", "sear"), 1.0 / "spec/search_spec.rb".len() as f32)
            }

            it "scores_higher_for_better_matches" {
                assert!(match_quality("ahtena.gemspec", "asp") > match_quality("algorithm4_spec.rb", "asp"));
                assert!(match_quality("readme.md", "em") > match_quality("benchmark.rb", "em"));
                assert!(match_quality("search.rb", "sear") > match_quality("spec/search_spec.rb", "sear"));
            }

            it "scores_shorter_matches_higher" {
                assert!(match_quality("fbb", "fbb") > match_quality("foo bar baz", "fbb"));
                assert!(match_quality("foo", "foo") > match_quality("longer foo", "foo"));
                assert!(match_quality("foo", "foo") > match_quality("foo longer", "foo"));
                assert!(match_quality("1/2/3/4", "1/2/3") > match_quality("1/9/2/3/4", "1/2/3"));
            }

            it "scores_the_tighter_of_two_matches_regardless_of_order" {
                let beginning = "121padding2";
                let end = "1padding212";
                assert_eq!(match_quality(beginning, "12"), match_quality(end, "12"));
            }

            it "tighter_matches_score_higher" {
                assert!(match_quality("long 12 long", "12") > match_quality("1 long 2", "12"));
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::namecase;
use super::segment::{Segment, Segments};
use super::surname;
use super::utils::*;
use phf;
use std::borrow::Cow;
use std::iter::Peekable;

#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum Location {
    Start,
    Middle,
    End,
}

#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Category<'a> {
    Name(Cow<'a, str>),
    Initials,
    Abbreviation,
    Other,
}

#[derive(Debug, Clone)]
pub struct NamePart<'a> {
    pub word: &'a str,
    pub counts: CharacterCounts,
    pub category: Category<'a>,
}

pub struct NameParts<'a> {
    segments: Peekable<Segments<'a>>,
    location: Location,
    trust_capitalization: bool,
}

impl<'a> Iterator for NameParts<'a> {
    type Item = NamePart<'a>;

    fn next(&mut self) -> Option<NamePart<'a>> {
        self.segments.next().map(|Segment { word, counts }| {
            let location = if self.location == Location::Start {
                self.location = Location::Middle;
                Location::Start
            } else if self.segments.peek().is_none() {
                Location::End
            } else {
                Location::Middle
            };

            NamePart::from_word_and_counts(word, counts, self.trust_capitalization, location)
        })
    }
}

impl<'a> NamePart<'a> {
    pub fn all_from_text(
        text: &'a str,
        trust_capitalization: bool,
        location: Location,
    ) -> NameParts<'a> {
        NameParts {
            segments: Segments::from_text(text).peekable(),
            location,
            trust_capitalization,
        }
    }

    pub fn from_word(word: &str, trust_capitalization: bool, location: Location) -> NamePart {
        NamePart::from_word_and_counts(word, categorize_chars(word), trust_capitalization, location)
    }

    #[allow(clippy::if_same_then_else)]
    pub fn from_word_and_counts(
        word: &str,
        counts: CharacterCounts,
        trust_capitalization: bool,
        location: Location,
    ) -> NamePart {
        let CharacterCounts {
            chars,
            alpha,
            upper,
            ascii_alpha,
            ascii_vowels,
        } = counts;

        debug_assert!(alpha > 0 || word == "&");

        let all_upper = alpha == upper;

        let namecased = || {
            if upper == 1 && (all_upper || (trust_capitalization && starts_with_uppercase(word))) {
                Cow::Borrowed(word)
            } else {
                let might_be_particle = location == Location::Middle;
                Cow::Owned(namecase::namecase(
                    word,
                    chars == ascii_alpha,
                    might_be_particle,
                ))
            }
        };

        let category = if chars == 1 {
            if ascii_alpha == chars {
                Category::Initials
            } else if alpha > 0 {
                Category::Name(namecased())
            } else {
                Category::Other
            }
        } else if word.ends_with('.') {
            if alpha >= 2 && has_sequential_alphas(word) {
                Category::Abbreviation
            } else {
                Category::Initials
            }
        } else if chars - alpha > 2 && chars - alpha - combining_chars(word) as u8 > 2 {
            Category::Other
        } else if ascii_alpha > 0 && ascii_vowels == 0 {
            if trust_capitalization && all_upper {
                Category::Initials
            } else if location == Location::End
                && surname::is_vowelless_surname(word, trust_capitalization)
            {
                Category::Name(namecased())
            } else if chars <= 5 {
                Category::Initials
            } else {
                Category::Other
            }
        } else if chars <= 5 && trust_capitalization && all_upper {
            Category::Initials
        } else if chars == 2 && !trust_capitalization && !TWO_LETTER_GIVEN_NAMES.contains(word) {
            Category::Initials
        } else {
            Category::Name(namecased())
        };

        NamePart {
            word,
            counts,
            category,
        }
    }

    #[inline]
    pub fn is_initials(&self) -> bool {
        self.category == Category::Initials
    }

    #[inline]
    pub fn is_namelike(&self) -> bool {
        match self.category {
            Category::Name(_) => true,
            _ => false,
        }
    }

    // Called on Initials and also on given or middle Names
    pub fn with_initials<F>(&self, mut f: F)
    where
        F: FnMut(char),
    {
        match self.category {
            Category::Name(ref namecased) if !namecased.contains('-') && self.counts.upper > 0 => {
                f(namecased.chars().nth(0).unwrap())
            }
            Category::Name(ref namecased) => namecased
                .split('-')
                .filter_map(|w| w.chars().find(|c| c.is_alphabetic()))
                .flat_map(|c| c.to_uppercase())
                .for_each(f),
            Category::Initials if self.counts.upper == self.counts.chars => {
                self.word.chars().for_each(f)
            }
            Category::Initials => self.word.chars().filter_map(uppercase_if_alpha).for_each(f),
            _ => panic!("Called extract_initials on {:?}", self),
        }
    }

    // Normally called on a Name, but may be called on Initials if part was mis-categorized
    pub fn with_namecased<F>(&self, mut f: F)
    where
        F: FnMut(&str),
    {
        match self.category {
            Category::Name(ref namecased) => f(namecased),
            Category::Initials
                if self.counts.upper == 1
                    && (self.counts.alpha == 1 || starts_with_uppercase(self.word)) =>
            {
                f(self.word)
            }
            Category::Initials => {
                let namecased = namecase::namecase(
                    self.word,
                    self.counts.chars == self.counts.ascii_alpha,
                    true,
                );
                f(&namecased)
            }
            _ => panic!("Called extract_initials on {:?}", self),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::{black_box, Bencher};

    #[test]
    fn one_word() {
        assert_eq!(
            1,
            NamePart::all_from_text("John", true, Location::Start).count()
        );
    }

    #[test]
    fn two_words() {
        assert_eq!(
            2,
            NamePart::all_from_text("&* John Doe! ☃", true, Location::Start).count()
        );
    }

    #[test]
    fn only_junk() {
        assert_eq!(
            0,
            NamePart::all_from_text(" ... 23 ", true, Location::Start).count()
        );
    }

    #[bench]
    fn all_from_text_simple(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("John Doe", true, Location::Start).count()))
    }

    #[bench]
    fn all_from_text_initials(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("J. Doe", true, Location::Start).count()))
    }

    #[bench]
    fn all_from_text_nonascii(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("이용희", false, Location::Start).count()))
    }

    #[bench]
    fn all_from_text_all_caps(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("JOHN DOE", false, Location::Start).count()))
    }

    #[test]
    fn single_ascii() {
        assert!(NamePart::from_word("I", true, Location::Start).is_initials());
    }

    #[test]
    fn single_han() {
        assert!(NamePart::from_word("鄭", true, Location::Start).is_namelike());
    }

    #[test]
    fn abbreviated_ascii() {
        assert!(NamePart::from_word("I.", true, Location::Start).is_initials());
    }

    #[test]
    fn abbreviated_double_ascii() {
        assert_eq!(
            Category::Abbreviation,
            NamePart::from_word("MI.", true, Location::Start).category
        );
    }

    #[test]
    fn double_abbreviated_double_ascii() {
        assert!(NamePart::from_word("M.I.", true, Location::Start).is_initials());
    }

    #[test]
    fn junk() {
        assert_eq!(
            Category::Other,
            NamePart::from_word("503(a)", true, Location::Start).category
        );
    }

    #[test]
    fn no_vowels() {
        assert!(NamePart::from_word("JM", true, Location::Start).is_initials());
        assert!(NamePart::from_word("jm", true, Location::Start).is_initials());
        assert!(NamePart::from_word("JM", false, Location::Start).is_initials());
        assert!(NamePart::from_word("JMMMMM", true, Location::Start).is_initials());
        assert_eq!(
            Category::Other,
            NamePart::from_word("jmmmmm", true, Location::Start).category
        );
        assert_eq!(
            Category::Other,
            NamePart::from_word("JMMMMM", false, Location::Start).category
        );
    }

    #[test]
    fn vowelless_surname() {
        assert!(NamePart::from_word("NG", true, Location::Start).is_initials());
        assert!(NamePart::from_word("Ng", true, Location::Start).is_initials());
        assert!(NamePart::from_word("Ng", true, Location::End).is_namelike());
        assert!(NamePart::from_word("NG", false, Location::End).is_namelike());
        assert!(NamePart::from_word("NG", true, Location::End).is_initials());
    }

    #[test]
    fn word() {
        assert!(NamePart::from_word("JEM", true, Location::Start).is_initials());
        assert!(NamePart::from_word("Jem", true, Location::Start).is_namelike());
        assert!(NamePart::from_word("JEM", false, Location::Start).is_namelike());
    }

    #[test]
    fn two_letters() {
        assert!(NamePart::from_word("Al", true, Location::Start).is_namelike());
        assert!(NamePart::from_word("AL", true, Location::Start).is_initials());
        assert!(NamePart::from_word("AL", false, Location::Start).is_namelike());
        assert!(NamePart::from_word("At", true, Location::Start).is_namelike());
        assert!(NamePart::from_word("AT", true, Location::Start).is_initials());
        assert!(NamePart::from_word("AT", false, Location::Start).is_initials());
    }

    #[bench]
    fn from_word_simple(b: &mut Bencher) {
        let name = "Jonathan";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                true,
                Location::Start,
            ))
        })
    }

    #[bench]
    fn from_word_initials(b: &mut Bencher) {
        let name = "J.";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                true,
                Location::Start,
            ))
        })
    }

    #[bench]
    fn from_word_nonascii(b: &mut Bencher) {
        let name = "희";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                false,
                Location::Start,
            ))
        })
    }

    #[bench]
    fn from_word_all_caps(b: &mut Bencher) {
        let name = "JONATHAN";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                false,
                Location::Start,
            ))
        })
    }
}

// Everything with a vowel reasonably popular in the Social Security data:
// https://www.ssa.gov/oact/babynames/limits.html
static TWO_LETTER_GIVEN_NAMES: phf::Set<&'static str> = phf_set! {
    "Jo",
    "JO",
    "jo",
    "Ty",
    "TY",
    "ty",
    "Ed",
    "ED",
    "ed",
    "Al",
    "AL",
    "al",
    "Bo",
    "BO",
    "bo",
    "Lu",
    "LU",
    "lu",
    "Cy",
    "CY",
    "cy",
    "An",
    "AN",
    "an",
    "La",
    "LA",
    "la",
    "Aj",
    "AJ",
    "aj",
    "Le",
    "LE",
    "le",
    "Om",
    "OM",
    "om",
    "Pa",
    "PA",
    "pa",
    "De",
    "DE",
    "de",
    "Ky",
    "KY",
    "ky",
    "My",
    "MY",
    "my",
    "Vy",
    "VY",
    "vy",
    "Vi",
    "VI",
    "vi",
    "Ka",
    "KA",
    "ka",
    "Sy",
    "SY",
    "sy",
    "Vu",
    "VU",
    "vu",
    "Yu",
    "YU",
    "yu",
    "Mi",
    "MI",
    "mi",
    "Su",
    "SU",
    "su",
    "Ma",
    "MA",
    "ma",
    "Ha",
    "HA",
    "ha",
    "Ki",
    "KI",
    "ki",
    "Tu",
    "TU",
    "tu",
    "Ji",
    "JI",
    "ji",
    "Ja",
    "JA",
    "ja",
    "Ly",
    "LY",
    "ly",
    "Li",
    "LI",
    "li",
    "Ai",
    "AI",
    "ai",
    "Ry",
    "RY",
    "ry",
    "Ab",
    "AB",
    "ab",
    "Ho",
    "HO",
    "ho",
    "Da",
    "DA",
    "da",
    "Oz",
    "OZ",
    "oz",
    "El",
    "EL",
    "el",
    "Na",
    "NA",
    "na",
    "Yi",
    "YI",
    "yi",
    "Em",
    "EM",
    "em",
    "Di",
    "DI",
    "di",
    "Go",
    "GO",
    "go",
    "Ev",
    "EV",
    "ev",
    "Mo",
    "MO",
    "mo",
    "Lo",
    "LO",
    "lo",
    "Ra",
    "RA",
    "ra",
    "Do",
    "DO",
    "do",
    "Gi",
    "GI",
    "gi",
};
<commit_msg>Only want one uppercase mapping<commit_after>use super::namecase;
use super::segment::{Segment, Segments};
use super::surname;
use super::utils::*;
use phf;
use std::borrow::Cow;
use std::iter::Peekable;

#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum Location {
    Start,
    Middle,
    End,
}

#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Category<'a> {
    Name(Cow<'a, str>),
    Initials,
    Abbreviation,
    Other,
}

#[derive(Debug, Clone)]
pub struct NamePart<'a> {
    pub word: &'a str,
    pub counts: CharacterCounts,
    pub category: Category<'a>,
}

pub struct NameParts<'a> {
    segments: Peekable<Segments<'a>>,
    location: Location,
    trust_capitalization: bool,
}

impl<'a> Iterator for NameParts<'a> {
    type Item = NamePart<'a>;

    fn next(&mut self) -> Option<NamePart<'a>> {
        self.segments.next().map(|Segment { word, counts }| {
            let location = if self.location == Location::Start {
                self.location = Location::Middle;
                Location::Start
            } else if self.segments.peek().is_none() {
                Location::End
            } else {
                Location::Middle
            };

            NamePart::from_word_and_counts(word, counts, self.trust_capitalization, location)
        })
    }
}

impl<'a> NamePart<'a> {
    pub fn all_from_text(
        text: &'a str,
        trust_capitalization: bool,
        location: Location,
    ) -> NameParts<'a> {
        NameParts {
            segments: Segments::from_text(text).peekable(),
            location,
            trust_capitalization,
        }
    }

    pub fn from_word(word: &str, trust_capitalization: bool, location: Location) -> NamePart {
        NamePart::from_word_and_counts(word, categorize_chars(word), trust_capitalization, location)
    }

    #[allow(clippy::if_same_then_else)]
    pub fn from_word_and_counts(
        word: &str,
        counts: CharacterCounts,
        trust_capitalization: bool,
        location: Location,
    ) -> NamePart {
        let CharacterCounts {
            chars,
            alpha,
            upper,
            ascii_alpha,
            ascii_vowels,
        } = counts;

        debug_assert!(alpha > 0 || word == "&");

        let all_upper = alpha == upper;

        let namecased = || {
            if upper == 1 && (all_upper || (trust_capitalization && starts_with_uppercase(word))) {
                Cow::Borrowed(word)
            } else {
                let might_be_particle = location == Location::Middle;
                Cow::Owned(namecase::namecase(
                    word,
                    chars == ascii_alpha,
                    might_be_particle,
                ))
            }
        };

        let category = if chars == 1 {
            if ascii_alpha == chars {
                Category::Initials
            } else if alpha > 0 {
                Category::Name(namecased())
            } else {
                Category::Other
            }
        } else if word.ends_with('.') {
            if alpha >= 2 && has_sequential_alphas(word) {
                Category::Abbreviation
            } else {
                Category::Initials
            }
        } else if chars - alpha > 2 && chars - alpha - combining_chars(word) as u8 > 2 {
            Category::Other
        } else if ascii_alpha > 0 && ascii_vowels == 0 {
            if trust_capitalization && all_upper {
                Category::Initials
            } else if location == Location::End
                && surname::is_vowelless_surname(word, trust_capitalization)
            {
                Category::Name(namecased())
            } else if chars <= 5 {
                Category::Initials
            } else {
                Category::Other
            }
        } else if chars <= 5 && trust_capitalization && all_upper {
            Category::Initials
        } else if chars == 2 && !trust_capitalization && !TWO_LETTER_GIVEN_NAMES.contains(word) {
            Category::Initials
        } else {
            Category::Name(namecased())
        };

        NamePart {
            word,
            counts,
            category,
        }
    }

    #[inline]
    pub fn is_initials(&self) -> bool {
        self.category == Category::Initials
    }

    #[inline]
    pub fn is_namelike(&self) -> bool {
        match self.category {
            Category::Name(_) => true,
            _ => false,
        }
    }

    // Called on Initials and also on given or middle Names
    pub fn with_initials<F>(&self, mut f: F)
    where
        F: FnMut(char),
    {
        match self.category {
            Category::Name(ref namecased) if !namecased.contains('-') && self.counts.upper > 0 => {
                f(namecased.chars().nth(0).unwrap())
            }
            Category::Name(ref namecased) => namecased
                .split('-')
                .filter_map(|w| w.chars().find(|c| c.is_alphabetic()))
                .filter_map(|c| c.to_uppercase().next())
                .for_each(f),
            Category::Initials if self.counts.upper == self.counts.chars => {
                self.word.chars().for_each(f)
            }
            Category::Initials => self.word.chars().filter_map(uppercase_if_alpha).for_each(f),
            _ => panic!("Called extract_initials on {:?}", self),
        }
    }

    // Normally called on a Name, but may be called on Initials if part was mis-categorized
    pub fn with_namecased<F>(&self, mut f: F)
    where
        F: FnMut(&str),
    {
        match self.category {
            Category::Name(ref namecased) => f(namecased),
            Category::Initials
                if self.counts.upper == 1
                    && (self.counts.alpha == 1 || starts_with_uppercase(self.word)) =>
            {
                f(self.word)
            }
            Category::Initials => {
                let namecased = namecase::namecase(
                    self.word,
                    self.counts.chars == self.counts.ascii_alpha,
                    true,
                );
                f(&namecased)
            }
            _ => panic!("Called extract_initials on {:?}", self),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::{black_box, Bencher};

    #[test]
    fn one_word() {
        assert_eq!(
            1,
            NamePart::all_from_text("John", true, Location::Start).count()
        );
    }

    #[test]
    fn two_words() {
        assert_eq!(
            2,
            NamePart::all_from_text("&* John Doe! ☃", true, Location::Start).count()
        );
    }

    #[test]
    fn only_junk() {
        assert_eq!(
            0,
            NamePart::all_from_text(" ... 23 ", true, Location::Start).count()
        );
    }

    #[bench]
    fn all_from_text_simple(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("John Doe", true, Location::Start).count()))
    }

    #[bench]
    fn all_from_text_initials(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("J. Doe", true, Location::Start).count()))
    }

    #[bench]
    fn all_from_text_nonascii(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("이용희", false, Location::Start).count()))
    }

    #[bench]
    fn all_from_text_all_caps(b: &mut Bencher) {
        b.iter(|| black_box(NamePart::all_from_text("JOHN DOE", false, Location::Start).count()))
    }

    #[test]
    fn single_ascii() {
        assert!(NamePart::from_word("I", true, Location::Start).is_initials());
    }

    #[test]
    fn single_han() {
        assert!(NamePart::from_word("鄭", true, Location::Start).is_namelike());
    }

    #[test]
    fn abbreviated_ascii() {
        assert!(NamePart::from_word("I.", true, Location::Start).is_initials());
    }

    #[test]
    fn abbreviated_double_ascii() {
        assert_eq!(
            Category::Abbreviation,
            NamePart::from_word("MI.", true, Location::Start).category
        );
    }

    #[test]
    fn double_abbreviated_double_ascii() {
        assert!(NamePart::from_word("M.I.", true, Location::Start).is_initials());
    }

    #[test]
    fn junk() {
        assert_eq!(
            Category::Other,
            NamePart::from_word("503(a)", true, Location::Start).category
        );
    }

    #[test]
    fn no_vowels() {
        assert!(NamePart::from_word("JM", true, Location::Start).is_initials());
        assert!(NamePart::from_word("jm", true, Location::Start).is_initials());
        assert!(NamePart::from_word("JM", false, Location::Start).is_initials());
        assert!(NamePart::from_word("JMMMMM", true, Location::Start).is_initials());
        assert_eq!(
            Category::Other,
            NamePart::from_word("jmmmmm", true, Location::Start).category
        );
        assert_eq!(
            Category::Other,
            NamePart::from_word("JMMMMM", false, Location::Start).category
        );
    }

    #[test]
    fn vowelless_surname() {
        assert!(NamePart::from_word("NG", true, Location::Start).is_initials());
        assert!(NamePart::from_word("Ng", true, Location::Start).is_initials());
        assert!(NamePart::from_word("Ng", true, Location::End).is_namelike());
        assert!(NamePart::from_word("NG", false, Location::End).is_namelike());
        assert!(NamePart::from_word("NG", true, Location::End).is_initials());
    }

    #[test]
    fn word() {
        assert!(NamePart::from_word("JEM", true, Location::Start).is_initials());
        assert!(NamePart::from_word("Jem", true, Location::Start).is_namelike());
        assert!(NamePart::from_word("JEM", false, Location::Start).is_namelike());
    }

    #[test]
    fn two_letters() {
        assert!(NamePart::from_word("Al", true, Location::Start).is_namelike());
        assert!(NamePart::from_word("AL", true, Location::Start).is_initials());
        assert!(NamePart::from_word("AL", false, Location::Start).is_namelike());
        assert!(NamePart::from_word("At", true, Location::Start).is_namelike());
        assert!(NamePart::from_word("AT", true, Location::Start).is_initials());
        assert!(NamePart::from_word("AT", false, Location::Start).is_initials());
    }

    #[bench]
    fn from_word_simple(b: &mut Bencher) {
        let name = "Jonathan";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                true,
                Location::Start,
            ))
        })
    }

    #[bench]
    fn from_word_initials(b: &mut Bencher) {
        let name = "J.";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                true,
                Location::Start,
            ))
        })
    }

    #[bench]
    fn from_word_nonascii(b: &mut Bencher) {
        let name = "희";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                false,
                Location::Start,
            ))
        })
    }

    #[bench]
    fn from_word_all_caps(b: &mut Bencher) {
        let name = "JONATHAN";
        let counts = categorize_chars(name);
        b.iter(|| {
            black_box(NamePart::from_word_and_counts(
                name,
                counts.clone(),
                false,
                Location::Start,
            ))
        })
    }
}

// Everything with a vowel reasonably popular in the Social Security data:
// https://www.ssa.gov/oact/babynames/limits.html
static TWO_LETTER_GIVEN_NAMES: phf::Set<&'static str> = phf_set! {
    "Jo",
    "JO",
    "jo",
    "Ty",
    "TY",
    "ty",
    "Ed",
    "ED",
    "ed",
    "Al",
    "AL",
    "al",
    "Bo",
    "BO",
    "bo",
    "Lu",
    "LU",
    "lu",
    "Cy",
    "CY",
    "cy",
    "An",
    "AN",
    "an",
    "La",
    "LA",
    "la",
    "Aj",
    "AJ",
    "aj",
    "Le",
    "LE",
    "le",
    "Om",
    "OM",
    "om",
    "Pa",
    "PA",
    "pa",
    "De",
    "DE",
    "de",
    "Ky",
    "KY",
    "ky",
    "My",
    "MY",
    "my",
    "Vy",
    "VY",
    "vy",
    "Vi",
    "VI",
    "vi",
    "Ka",
    "KA",
    "ka",
    "Sy",
    "SY",
    "sy",
    "Vu",
    "VU",
    "vu",
    "Yu",
    "YU",
    "yu",
    "Mi",
    "MI",
    "mi",
    "Su",
    "SU",
    "su",
    "Ma",
    "MA",
    "ma",
    "Ha",
    "HA",
    "ha",
    "Ki",
    "KI",
    "ki",
    "Tu",
    "TU",
    "tu",
    "Ji",
    "JI",
    "ji",
    "Ja",
    "JA",
    "ja",
    "Ly",
    "LY",
    "ly",
    "Li",
    "LI",
    "li",
    "Ai",
    "AI",
    "ai",
    "Ry",
    "RY",
    "ry",
    "Ab",
    "AB",
    "ab",
    "Ho",
    "HO",
    "ho",
    "Da",
    "DA",
    "da",
    "Oz",
    "OZ",
    "oz",
    "El",
    "EL",
    "el",
    "Na",
    "NA",
    "na",
    "Yi",
    "YI",
    "yi",
    "Em",
    "EM",
    "em",
    "Di",
    "DI",
    "di",
    "Go",
    "GO",
    "go",
    "Ev",
    "EV",
    "ev",
    "Mo",
    "MO",
    "mo",
    "Lo",
    "LO",
    "lo",
    "Ra",
    "RA",
    "ra",
    "Do",
    "DO",
    "do",
    "Gi",
    "GI",
    "gi",
};
<|endoftext|>


<commit_before>use std::ffi::CStr;
use std::ptr;

use llvm::core::*;
use llvm::execution_engine::*;
use llvm::orc::*;
use llvm::target::*;
use llvm::target_machine::*;
use llvm::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault;
use llvm::target_machine::LLVMCodeModel::LLVMCodeModelJITDefault;
use llvm::target_machine::LLVMRelocMode::LLVMRelocDefault;

pub struct LlvmJit {
    tm: *mut LLVMOpaqueTargetMachine,
    orc: *mut LLVMOrcOpaqueJITStack,
}

impl LlvmJit {
    pub fn new() -> LlvmJit {
        unsafe {
            LLVM_InitializeNativeTarget();
            LLVM_InitializeNativeAsmPrinter();

            let default_triple = LLVMGetDefaultTargetTriple();
            let mut error = ptr::null_mut();
            let mut target_ref = ptr::null_mut();

            if LLVMGetTargetFromTriple(default_triple, &mut target_ref, &mut error) != 0 {
                panic!("couldn't get target from triple: {:?}.", CStr::from_ptr(error));
            }

            if LLVMTargetHasJIT(target_ref) == 0 {
                panic!("target doesn't support JIT.");
            }

            let tm = LLVMCreateTargetMachine(target_ref,
                        default_triple,
                        ptr::null(),
                        ptr::null(),
                        LLVMCodeGenLevelDefault,
                        LLVMRelocDefault,
                        LLVMCodeModelJITDefault);

            assert!(!tm.is_null());
            LLVMDisposeMessage(default_triple);

            let orc = LLVMOrcCreateInstance(tm);

            LlvmJit {
                tm: tm,
                orc: orc,
            }
        }
    }
}<commit_msg>opt: fix unused use<commit_after>use std::ffi::CStr;
use std::ptr;

use llvm::core::*;
use llvm::orc::*;
use llvm::target::*;
use llvm::target_machine::*;
use llvm::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault;
use llvm::target_machine::LLVMCodeModel::LLVMCodeModelJITDefault;
use llvm::target_machine::LLVMRelocMode::LLVMRelocDefault;

pub struct LlvmJit {
    tm: *mut LLVMOpaqueTargetMachine,
    orc: *mut LLVMOrcOpaqueJITStack,
}

impl LlvmJit {
    pub fn new() -> LlvmJit {
        unsafe {
            LLVM_InitializeNativeTarget();
            LLVM_InitializeNativeAsmPrinter();

            let default_triple = LLVMGetDefaultTargetTriple();
            let mut error = ptr::null_mut();
            let mut target_ref = ptr::null_mut();

            if LLVMGetTargetFromTriple(default_triple, &mut target_ref, &mut error) != 0 {
                panic!("couldn't get target from triple: {:?}.", CStr::from_ptr(error));
            }

            if LLVMTargetHasJIT(target_ref) == 0 {
                panic!("target doesn't support JIT.");
            }

            let tm = LLVMCreateTargetMachine(target_ref,
                        default_triple,
                        ptr::null(),
                        ptr::null(),
                        LLVMCodeGenLevelDefault,
                        LLVMRelocDefault,
                        LLVMCodeModelJITDefault);

            assert!(!tm.is_null());
            LLVMDisposeMessage(default_triple);

            let orc = LLVMOrcCreateInstance(tm);

            LlvmJit {
                tm: tm,
                orc: orc,
            }
        }
    }
}<|endoftext|>