<commit_before>//! gpx handles parsing of GPX elements.

use std::io::Read;

use chrono::{DateTime, Utc};
use error_chain::{bail, ensure};
use geo_types::Rect;
use xml::reader::XmlEvent;

use crate::errors::*;
use crate::parser::{
    bounds, metadata, route, string, time, track, verify_starting_tag, waypoint, Context,
};
use crate::{Gpx, GpxVersion, Link, Metadata, Person};

/// Convert the version string to the version enum
fn version_string_to_version(version_str: &str) -> Result<GpxVersion> {
    match version_str {
        "1.0" => Ok(GpxVersion::Gpx10),
        "1.1" => Ok(GpxVersion::Gpx11),
        version => Err(Error::from(format!("Unknown version {}", version))),
    }
}

/// consume consumes an entire GPX element.
pub fn consume<R: Read>(context: &mut Context<R>) -> Result<Gpx> {
    let mut gpx: Gpx = Default::default();

    let mut author: Option<String> = None;
    let mut url: Option<String> = None;
    let mut urlname: Option<String> = None;
    let mut email: Option<String> = None;
    let mut time: Option<DateTime<Utc>> = None;
    let mut bounds: Option<Rect<f64>> = None;
    let mut gpx_name: Option<String> = None;
    let mut description: Option<String> = None;
    let mut keywords: Option<String> = None;

    // First we consume the gpx tag and its attributes
    let attributes = verify_starting_tag(context, "gpx")?;
    let version = attributes
        .iter()
        .find(|attr| attr.name.local_name == "version")
        .ok_or(ErrorKind::InvalidElementLacksAttribute("version", "gpx"))?;
    gpx.version = version_string_to_version(&version.value)?;
    context.version = gpx.version;

    loop {
        let next_event = {
            if let Some(next) = context.reader.peek() {
                match next {
                    Ok(n) => n,
                    Err(_) => bail!("error while parsing gpx event"),
                }
            } else {
                break;
            }
        };

        match next_event {
            XmlEvent::StartElement { ref name, .. } => match name.local_name.as_ref() {
                "metadata" if context.version != GpxVersion::Gpx10 => {
                    gpx.metadata = Some(metadata::consume(context)?);
                }
                "trk" => {
                    gpx.tracks.push(track::consume(context)?);
                }
                "rte" => {
                    gpx.route = route::consume(context)?;
                }
                "wpt" => {
                    gpx.waypoints.push(waypoint::consume(context, "wpt")?);
                }
                "time" if context.version == GpxVersion::Gpx10 => {
                    time = Some(time::consume(context)?);
                }
                "bounds" if context.version == GpxVersion::Gpx10 => {
                    bounds = Some(bounds::consume(context)?);
                }
                "author" if context.version == GpxVersion::Gpx10 => {
                    author = Some(string::consume(context, "author", false)?);
                }
                "email" if context.version == GpxVersion::Gpx10 => {
                    email = Some(string::consume(context, "email", false)?);
                }
                "url" if context.version == GpxVersion::Gpx10 => {
                    url = Some(string::consume(context, "url", false)?);
                }
                "urlname" if context.version == GpxVersion::Gpx10 => {
                    urlname = Some(string::consume(context, "urlname", false)?);
                }
                "name" if context.version == GpxVersion::Gpx10 => {
                    gpx_name = Some(string::consume(context, "name", false)?);
                }
                "description" if context.version == GpxVersion::Gpx10 => {
                    description = Some(string::consume(context, "description", true)?);
                }
                "keywords" if context.version == GpxVersion::Gpx10 => {
                    keywords = Some(string::consume(context, "keywords", true)?);
                }
                child => {
                    bail!(ErrorKind::InvalidChildElement(String::from(child), "gpx"));
                }
            },
            XmlEvent::EndElement { name } => {
                ensure!(
                    name.local_name == "gpx",
                    ErrorKind::InvalidClosingTag(name.local_name.clone(), "gpx")
                );
                if gpx.version == GpxVersion::Gpx10 {
                    let mut metadata: Metadata = Default::default();
                    metadata.name = gpx_name;
                    metadata.time = time;
                    metadata.bounds = bounds;
                    let mut person: Person = Default::default();
                    person.name = author;
                    if let Some(url) = url {
                        let mut link: Link = Default::default();
                        link.href = url;
                        link.text = urlname;
                        person.link = Some(link);
                    }
                    person.email = email;
                    metadata.author = Some(person);
                    metadata.keywords = keywords;
                    metadata.description = description;
                    gpx.metadata = Some(metadata);
                }
                context.reader.next();

                return Ok(gpx);
            }
            _ => {
                context.reader.next(); //consume and ignore this event
            }
        }
    }

    bail!(ErrorKind::MissingClosingTag("gpx"));
}

#[cfg(test)]
mod tests {
    use geo_types::Point;

    use super::consume;
    use crate::GpxVersion;

    #[test]
    fn consume_gpx() {
        let gpx = consume!("<gpx version=\"1.1\"></gpx>", GpxVersion::Unknown);

        assert!(gpx.is_ok());
    }

    #[test]
    fn consume_gpx_no_version() {
        let gpx = consume!("<gpx></gpx>", GpxVersion::Unknown);

        assert!(gpx.is_err());
    }

    #[test]
    fn consume_gpx_version_error() {
        let gpx = consume!("<gpx version=\"1.2\"></gpx>", GpxVersion::Unknown);

        assert!(gpx.is_err());
    }

    #[test]
    fn consume_gpx_full() {
        let gpx = consume!(
            "
            <gpx version=\"1.0\">
                <time>2016-03-27T18:57:55Z</time>
                <bounds minlat=\"45.487064362\" minlon=\"-74.031837463\" maxlat=\"45.701225281\" maxlon=\"-73.586273193\"></bounds>
                <trk></trk>
                <wpt lat=\"1.23\" lon=\"2.34\"></wpt>
                <wpt lon=\"10.256\" lat=\"-81.324\">
                    <time>2001-10-26T19:32:52+00:00</time>
                </wpt>
                <rte></rte>
            </gpx>
            ",
            GpxVersion::Unknown
        );

        assert!(gpx.is_ok());
        let gpx = gpx.unwrap();

        assert_eq!(gpx.version, GpxVersion::Gpx10);
        assert_eq!(gpx.tracks.len(), 1);

        assert_eq!(gpx.waypoints.len(), 2);

        let wpt = &gpx.waypoints[1];
        assert_eq!(wpt.point(), Point::new(10.256, -81.324));
    }
}
<commit_msg>Only add Person or Metadata if it's changed from default<commit_after>//! gpx handles parsing of GPX elements.

use std::io::Read;

use chrono::{DateTime, Utc};
use error_chain::{bail, ensure};
use geo_types::Rect;
use xml::reader::XmlEvent;

use crate::errors::*;
use crate::parser::{
    bounds, metadata, route, string, time, track, verify_starting_tag, waypoint, Context,
};
use crate::{Gpx, GpxVersion, Link, Metadata, Person};

/// Convert the version string to the version enum
fn version_string_to_version(version_str: &str) -> Result<GpxVersion> {
    match version_str {
        "1.0" => Ok(GpxVersion::Gpx10),
        "1.1" => Ok(GpxVersion::Gpx11),
        version => Err(Error::from(format!("Unknown version {}", version))),
    }
}

/// consume consumes an entire GPX element.
pub fn consume<R: Read>(context: &mut Context<R>) -> Result<Gpx> {
    let mut gpx: Gpx = Default::default();

    let mut author: Option<String> = None;
    let mut url: Option<String> = None;
    let mut urlname: Option<String> = None;
    let mut email: Option<String> = None;
    let mut time: Option<DateTime<Utc>> = None;
    let mut bounds: Option<Rect<f64>> = None;
    let mut gpx_name: Option<String> = None;
    let mut description: Option<String> = None;
    let mut keywords: Option<String> = None;

    // First we consume the gpx tag and its attributes
    let attributes = verify_starting_tag(context, "gpx")?;
    let version = attributes
        .iter()
        .find(|attr| attr.name.local_name == "version")
        .ok_or(ErrorKind::InvalidElementLacksAttribute("version", "gpx"))?;
    gpx.version = version_string_to_version(&version.value)?;
    context.version = gpx.version;

    loop {
        let next_event = {
            if let Some(next) = context.reader.peek() {
                match next {
                    Ok(n) => n,
                    Err(_) => bail!("error while parsing gpx event"),
                }
            } else {
                break;
            }
        };

        match next_event {
            XmlEvent::StartElement { ref name, .. } => match name.local_name.as_ref() {
                "metadata" if context.version != GpxVersion::Gpx10 => {
                    gpx.metadata = Some(metadata::consume(context)?);
                }
                "trk" => {
                    gpx.tracks.push(track::consume(context)?);
                }
                "rte" => {
                    gpx.route = route::consume(context)?;
                }
                "wpt" => {
                    gpx.waypoints.push(waypoint::consume(context, "wpt")?);
                }
                "time" if context.version == GpxVersion::Gpx10 => {
                    time = Some(time::consume(context)?);
                }
                "bounds" if context.version == GpxVersion::Gpx10 => {
                    bounds = Some(bounds::consume(context)?);
                }
                "author" if context.version == GpxVersion::Gpx10 => {
                    author = Some(string::consume(context, "author", false)?);
                }
                "email" if context.version == GpxVersion::Gpx10 => {
                    email = Some(string::consume(context, "email", false)?);
                }
                "url" if context.version == GpxVersion::Gpx10 => {
                    url = Some(string::consume(context, "url", false)?);
                }
                "urlname" if context.version == GpxVersion::Gpx10 => {
                    urlname = Some(string::consume(context, "urlname", false)?);
                }
                "name" if context.version == GpxVersion::Gpx10 => {
                    gpx_name = Some(string::consume(context, "name", false)?);
                }
                "description" if context.version == GpxVersion::Gpx10 => {
                    description = Some(string::consume(context, "description", true)?);
                }
                "keywords" if context.version == GpxVersion::Gpx10 => {
                    keywords = Some(string::consume(context, "keywords", true)?);
                }
                child => {
                    bail!(ErrorKind::InvalidChildElement(String::from(child), "gpx"));
                }
            },
            XmlEvent::EndElement { name } => {
                ensure!(
                    name.local_name == "gpx",
                    ErrorKind::InvalidClosingTag(name.local_name.clone(), "gpx")
                );
                if gpx.version == GpxVersion::Gpx10 {
                    let mut metadata: Metadata = Default::default();
                    metadata.name = gpx_name;
                    metadata.time = time;
                    metadata.bounds = bounds;
                    let mut person: Person = Default::default();
                    person.name = author;
                    if let Some(url) = url {
                        let mut link: Link = Default::default();
                        link.href = url;
                        link.text = urlname;
                        person.link = Some(link);
                    }
                    person.email = email;
                    if person != Default::default() {
                        metadata.author = Some(person);
                    }
                    metadata.keywords = keywords;
                    metadata.description = description;
                    if metadata != Default::default() {
                        gpx.metadata = Some(metadata);
                    }
                }
                context.reader.next();

                return Ok(gpx);
            }
            _ => {
                context.reader.next(); //consume and ignore this event
            }
        }
    }

    bail!(ErrorKind::MissingClosingTag("gpx"));
}

#[cfg(test)]
mod tests {
    use geo_types::Point;

    use super::consume;
    use crate::GpxVersion;

    #[test]
    fn consume_gpx() {
        let gpx = consume!("<gpx version=\"1.1\"></gpx>", GpxVersion::Unknown);

        assert!(gpx.is_ok());
    }

    #[test]
    fn consume_gpx_no_version() {
        let gpx = consume!("<gpx></gpx>", GpxVersion::Unknown);

        assert!(gpx.is_err());
    }

    #[test]
    fn consume_gpx_version_error() {
        let gpx = consume!("<gpx version=\"1.2\"></gpx>", GpxVersion::Unknown);

        assert!(gpx.is_err());
    }

    #[test]
    fn consume_gpx_full() {
        let gpx = consume!(
            "
            <gpx version=\"1.0\">
                <time>2016-03-27T18:57:55Z</time>
                <bounds minlat=\"45.487064362\" minlon=\"-74.031837463\" maxlat=\"45.701225281\" maxlon=\"-73.586273193\"></bounds>
                <trk></trk>
                <wpt lat=\"1.23\" lon=\"2.34\"></wpt>
                <wpt lon=\"10.256\" lat=\"-81.324\">
                    <time>2001-10-26T19:32:52+00:00</time>
                </wpt>
                <rte></rte>
            </gpx>
            ",
            GpxVersion::Unknown
        );

        assert!(gpx.is_ok());
        let gpx = gpx.unwrap();

        assert_eq!(gpx.version, GpxVersion::Gpx10);
        assert_eq!(gpx.tracks.len(), 1);

        assert_eq!(gpx.waypoints.len(), 2);

        let wpt = &gpx.waypoints[1];
        assert_eq!(wpt.point(), Point::new(10.256, -81.324));
    }
}
<|endoftext|>


<commit_before>use domination::Domination;
use multi_objective::MultiObjective;
use crowding_distance::CrowdingDistanceAssignment; // XXX: Change name
use selection::SelectSolutions;
use rayon::par_iter::*;
use selection::tournament_selection_fast;
use rand::Rng;
use std::u32;

pub struct Individual<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    genome: G,

    // The individuals fitness.
    fitness: Option<F>,

    // which pareto front this rated individual belongs to (only valid if fitness.is_some() and
    // pareto fronts have been determined)
    pareto_rank: u32,

    // The crowding distance to neighboring individuals (individuals with similar fitness)
    crowding_distance: f64,

    // the number of individuals in each crowd (points of equal fitness)
    crowd_size: u32,

    selected: bool,
}

impl<G, F> CrowdingDistanceAssignment<F> for Individual<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    fn fitness(&self) -> &F {
        self.fitness.as_ref().unwrap()
    }
    fn rank_mut(&mut self) -> &mut u32 {
        &mut self.pareto_rank
    }
    fn dist_mut(&mut self) -> &mut f64 {
        &mut self.crowding_distance
    }
    fn rank(&self) -> u32 {
        self.pareto_rank
    }
    fn dist(&self) -> f64 {
        self.crowding_distance
    }

    fn select(&mut self) {
        assert!(self.selected == false);
        self.selected = true;
    }
    fn unselect(&mut self) {
        self.selected = false;
    }
    fn is_selected(&self) -> bool {
        self.selected
    }

    fn crowd(&self) -> usize {
        self.crowd_size as usize
    }

    fn set_crowd(&mut self, crowd: usize) {
        self.crowd_size = crowd as u32;
    }
}

impl<G, F> Individual<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    fn from_genome(genome: G) -> Self {
        Individual {
            genome: genome,
            fitness: None,
            pareto_rank: u32::MAX,
            crowding_distance: 0.0,
            crowd_size: 1,
            selected: false,
        }
    }

    pub fn genome(&self) -> &G {
        &self.genome
    }

    pub fn fitness(&self) -> &F {
        self.fitness.as_ref().unwrap()
    }
    pub fn fitness_mut(&mut self) -> &mut F {
        self.fitness.as_mut().unwrap()
    }
}

/// An unrated Population of individuals.

pub struct UnratedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    individuals: Vec<Individual<G, F>>,
}

/// A rated Population of individuals, i.e. each individual has a fitness assigned.

pub struct RatedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    individuals: Vec<Individual<G, F>>,
}

/// A ranked (selected) Population (pareto_rank and crowding_distance).

pub struct RankedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    individuals: Vec<Individual<G, F>>,
}

impl<G, F> UnratedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    pub fn individuals(&self) -> &[Individual<G, F>] {
        &self.individuals
    }

    pub fn new() -> Self {
        UnratedPopulation { individuals: Vec::new() }
    }

    pub fn push(&mut self, genome: G) {
        self.individuals.push(Individual::from_genome(genome));
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }

    /// Rate the individuals in parallel.

    pub fn rate_in_parallel<E>(self, eval: &E, weight: f64) -> RatedPopulation<G, F>
        where E: Fn(&G) -> F + Sync
    {
        let UnratedPopulation { mut individuals } = self;

        individuals.par_iter_mut().weight(weight).for_each(|ind| {
            assert!(ind.fitness.is_none());
            let fitness = eval(&ind.genome);
            ind.fitness = Some(fitness);
        });

        RatedPopulation { individuals: individuals }
    }
}

impl<G, F> RatedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    pub fn select<S, R>(self, population_size: usize, num_objectives: usize, selection: &S, rng: &mut R) -> RankedPopulation<G, F>
        where S: SelectSolutions<Individual<G, F>, F>,
              R: Rng
    {
        let RatedPopulation { mut individuals } = self;

        // evaluate rank and crowding distance: XXX: replace by Select trait
        selection.select_solutions(&mut individuals, population_size, num_objectives, rng);

        // only keep individuals which are selected
        individuals.retain(|i| i.is_selected());

        // sort by rank and crowding-distance
        individuals.sort_by(|a, b| a.rank_and_crowding_order(b));

        assert!(individuals.len() == population_size);

        RankedPopulation { individuals: individuals }
    }

    pub fn individuals_mut(&mut self) -> &mut [Individual<G, F>] {
        &mut self.individuals
    }

    pub fn new() -> Self {
        RatedPopulation { individuals: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }

    pub fn fitness(&self, index: usize) -> &F {
        self.individuals[index].fitness.as_ref().unwrap()
    }

    pub fn fitness_mut(&mut self, index: usize) -> &mut F {
        self.individuals[index].fitness.as_mut().unwrap()
    }
}

impl<G, F> RankedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    pub fn into_unrated(self) -> UnratedPopulation<G, F> {
        let RankedPopulation { individuals } = self;
        let mut pop = UnratedPopulation::new();
        for ind in individuals {
            pop.push(ind.genome);
        }
        pop
    }

    /// Generate an unrated offspring population.
    pub fn reproduce<R, M>(&self,
                           rng: &mut R,
                           offspring_size: usize,
                           tournament_k: usize,
                           mate: &M)
                           -> UnratedPopulation<G, F>
        where R: Rng,
              M: Fn(&mut R, &G, &G) -> G
    {
        assert!(tournament_k > 0);
        assert!(self.len() > 0);

        // create `offspring_size` new offspring using k-tournament (
        // select the best individual out of k randomly choosen individuals)
        let offspring: Vec<_> =
            (0..offspring_size)
                .map(|_| {

                    // first parent. k candidates
                    let p1 = tournament_selection_fast(rng,
                                                       |i1, i2| self.individuals[i1].has_better_rank_and_crowding(&self.individuals[i2]),
                                                       self.len(),
                                                       tournament_k);

                    // second parent. k candidates
                    let p2 = tournament_selection_fast(rng,
                                                       |i1, i2| self.individuals[i1].has_better_rank_and_crowding(&self.individuals[i2]),
                                                       self.len(),
                                                       tournament_k);

                    // cross-over the two parents and produce one child (throw away
                    // second child XXX)

                    // The potentially dominating individual is gives as first
                    // parameter.
                    //let (p1, p2) = if self.individuals[p1].has_better_rank_and_crowding(&self.individuals[p2]) {
                    //    (p1, p2)
                    //} else if self.individuals[p2].has_better_rank_and_crowding(&self.individuals[p1]) {
                    //    (p2, p1)
                    //} else {
                    //    (p1, p2)
                    //};

                    Individual::from_genome(mate(rng, &self.individuals[p1].genome, &self.individuals[p2].genome))
                })
                .collect();

        assert!(offspring.len() == offspring_size);

        UnratedPopulation { individuals: offspring }
    }

    pub fn new() -> Self {
        RankedPopulation { individuals: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }

    /// Merging a ranked population with a rated population results in a rated population as the selection
    /// criteria is no longer met.
    pub fn merge(self, offspring: RatedPopulation<G, F>) -> RatedPopulation<G, F> {
        let RankedPopulation{mut individuals} = self;

        // XXX: Reset rank and crowding distance.

        individuals.extend(offspring.individuals);

        RatedPopulation { individuals: individuals }
    }

    pub fn all<C>(&self, f: &mut C)
        where C: FnMut(&G, &F)
    {
        for ind in &self.individuals {
            f(&ind.genome, ind.fitness.as_ref().unwrap());
        }
    }

    pub fn max_rank(&self) -> Option<usize> {
        self.individuals.iter().map(|ind| ind.pareto_rank).max().map(|r| r as usize)
    }

    pub fn all_of_rank<C>(&self, rank: usize, f: &mut C)
        where C: FnMut(&G, &F)
    {
        for ind in &self.individuals {
            if ind.pareto_rank as usize == rank {
                f(&ind.genome, ind.fitness.as_ref().unwrap());
            }
        }
    }

    pub fn individuals(&self) -> &[Individual<G, F>] {
        &self.individuals
    }
}
<commit_msg>Add RatedPopulation#individuals()<commit_after>use domination::Domination;
use multi_objective::MultiObjective;
use crowding_distance::CrowdingDistanceAssignment; // XXX: Change name
use selection::SelectSolutions;
use rayon::par_iter::*;
use selection::tournament_selection_fast;
use rand::Rng;
use std::u32;

pub struct Individual<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    genome: G,

    // The individuals fitness.
    fitness: Option<F>,

    // which pareto front this rated individual belongs to (only valid if fitness.is_some() and
    // pareto fronts have been determined)
    pareto_rank: u32,

    // The crowding distance to neighboring individuals (individuals with similar fitness)
    crowding_distance: f64,

    // the number of individuals in each crowd (points of equal fitness)
    crowd_size: u32,

    selected: bool,
}

impl<G, F> CrowdingDistanceAssignment<F> for Individual<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    fn fitness(&self) -> &F {
        self.fitness.as_ref().unwrap()
    }
    fn rank_mut(&mut self) -> &mut u32 {
        &mut self.pareto_rank
    }
    fn dist_mut(&mut self) -> &mut f64 {
        &mut self.crowding_distance
    }
    fn rank(&self) -> u32 {
        self.pareto_rank
    }
    fn dist(&self) -> f64 {
        self.crowding_distance
    }

    fn select(&mut self) {
        assert!(self.selected == false);
        self.selected = true;
    }
    fn unselect(&mut self) {
        self.selected = false;
    }
    fn is_selected(&self) -> bool {
        self.selected
    }

    fn crowd(&self) -> usize {
        self.crowd_size as usize
    }

    fn set_crowd(&mut self, crowd: usize) {
        self.crowd_size = crowd as u32;
    }
}

impl<G, F> Individual<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    fn from_genome(genome: G) -> Self {
        Individual {
            genome: genome,
            fitness: None,
            pareto_rank: u32::MAX,
            crowding_distance: 0.0,
            crowd_size: 1,
            selected: false,
        }
    }

    pub fn genome(&self) -> &G {
        &self.genome
    }

    pub fn fitness(&self) -> &F {
        self.fitness.as_ref().unwrap()
    }
    pub fn fitness_mut(&mut self) -> &mut F {
        self.fitness.as_mut().unwrap()
    }
}

/// An unrated Population of individuals.

pub struct UnratedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    individuals: Vec<Individual<G, F>>,
}

/// A rated Population of individuals, i.e. each individual has a fitness assigned.

pub struct RatedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    individuals: Vec<Individual<G, F>>,
}

/// A ranked (selected) Population (pareto_rank and crowding_distance).

pub struct RankedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    individuals: Vec<Individual<G, F>>,
}

impl<G, F> UnratedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    pub fn individuals(&self) -> &[Individual<G, F>] {
        &self.individuals
    }

    pub fn new() -> Self {
        UnratedPopulation { individuals: Vec::new() }
    }

    pub fn push(&mut self, genome: G) {
        self.individuals.push(Individual::from_genome(genome));
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }

    /// Rate the individuals in parallel.

    pub fn rate_in_parallel<E>(self, eval: &E, weight: f64) -> RatedPopulation<G, F>
        where E: Fn(&G) -> F + Sync
    {
        let UnratedPopulation { mut individuals } = self;

        individuals.par_iter_mut().weight(weight).for_each(|ind| {
            assert!(ind.fitness.is_none());
            let fitness = eval(&ind.genome);
            ind.fitness = Some(fitness);
        });

        RatedPopulation { individuals: individuals }
    }
}

impl<G, F> RatedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    pub fn select<S, R>(self, population_size: usize, num_objectives: usize, selection: &S, rng: &mut R) -> RankedPopulation<G, F>
        where S: SelectSolutions<Individual<G, F>, F>,
              R: Rng
    {
        let RatedPopulation { mut individuals } = self;

        // evaluate rank and crowding distance: XXX: replace by Select trait
        selection.select_solutions(&mut individuals, population_size, num_objectives, rng);

        // only keep individuals which are selected
        individuals.retain(|i| i.is_selected());

        // sort by rank and crowding-distance
        individuals.sort_by(|a, b| a.rank_and_crowding_order(b));

        assert!(individuals.len() == population_size);

        RankedPopulation { individuals: individuals }
    }

    pub fn individuals(&self) -> &[Individual<G, F>] {
        &self.individuals
    }

    pub fn individuals_mut(&mut self) -> &mut [Individual<G, F>] {
        &mut self.individuals
    }

    pub fn new() -> Self {
        RatedPopulation { individuals: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }

    pub fn fitness(&self, index: usize) -> &F {
        self.individuals[index].fitness.as_ref().unwrap()
    }

    pub fn fitness_mut(&mut self, index: usize) -> &mut F {
        self.individuals[index].fitness.as_mut().unwrap()
    }
}

impl<G, F> RankedPopulation<G, F>
    where F: MultiObjective + Domination,
          G: Send
{
    pub fn into_unrated(self) -> UnratedPopulation<G, F> {
        let RankedPopulation { individuals } = self;
        let mut pop = UnratedPopulation::new();
        for ind in individuals {
            pop.push(ind.genome);
        }
        pop
    }

    /// Generate an unrated offspring population.
    pub fn reproduce<R, M>(&self,
                           rng: &mut R,
                           offspring_size: usize,
                           tournament_k: usize,
                           mate: &M)
                           -> UnratedPopulation<G, F>
        where R: Rng,
              M: Fn(&mut R, &G, &G) -> G
    {
        assert!(tournament_k > 0);
        assert!(self.len() > 0);

        // create `offspring_size` new offspring using k-tournament (
        // select the best individual out of k randomly choosen individuals)
        let offspring: Vec<_> =
            (0..offspring_size)
                .map(|_| {

                    // first parent. k candidates
                    let p1 = tournament_selection_fast(rng,
                                                       |i1, i2| self.individuals[i1].has_better_rank_and_crowding(&self.individuals[i2]),
                                                       self.len(),
                                                       tournament_k);

                    // second parent. k candidates
                    let p2 = tournament_selection_fast(rng,
                                                       |i1, i2| self.individuals[i1].has_better_rank_and_crowding(&self.individuals[i2]),
                                                       self.len(),
                                                       tournament_k);

                    // cross-over the two parents and produce one child (throw away
                    // second child XXX)

                    // The potentially dominating individual is gives as first
                    // parameter.
                    //let (p1, p2) = if self.individuals[p1].has_better_rank_and_crowding(&self.individuals[p2]) {
                    //    (p1, p2)
                    //} else if self.individuals[p2].has_better_rank_and_crowding(&self.individuals[p1]) {
                    //    (p2, p1)
                    //} else {
                    //    (p1, p2)
                    //};

                    Individual::from_genome(mate(rng, &self.individuals[p1].genome, &self.individuals[p2].genome))
                })
                .collect();

        assert!(offspring.len() == offspring_size);

        UnratedPopulation { individuals: offspring }
    }

    pub fn new() -> Self {
        RankedPopulation { individuals: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.individuals.len()
    }

    /// Merging a ranked population with a rated population results in a rated population as the selection
    /// criteria is no longer met.
    pub fn merge(self, offspring: RatedPopulation<G, F>) -> RatedPopulation<G, F> {
        let RankedPopulation{mut individuals} = self;

        // XXX: Reset rank and crowding distance.

        individuals.extend(offspring.individuals);

        RatedPopulation { individuals: individuals }
    }

    pub fn all<C>(&self, f: &mut C)
        where C: FnMut(&G, &F)
    {
        for ind in &self.individuals {
            f(&ind.genome, ind.fitness.as_ref().unwrap());
        }
    }

    pub fn max_rank(&self) -> Option<usize> {
        self.individuals.iter().map(|ind| ind.pareto_rank).max().map(|r| r as usize)
    }

    pub fn all_of_rank<C>(&self, rank: usize, f: &mut C)
        where C: FnMut(&G, &F)
    {
        for ind in &self.individuals {
            if ind.pareto_rank as usize == rank {
                f(&ind.genome, ind.fitness.as_ref().unwrap());
            }
        }
    }

    pub fn individuals(&self) -> &[Individual<G, F>] {
        &self.individuals
    }
}
<|endoftext|>


<commit_before>use super::mode;
use super::util;
use std::collections::Deque;
use std::collections::RingBuf;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;
type Cmd<'a> = (uint,mode::Mode,&'a Doc);

#[inline(always)]
fn fitting(mut cmds:RingBuf<Cmd>, mut rem:int) -> bool {
    let mut fits = true;

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match cmds.pop_front() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(box ref ldoc, box ref rdoc) => {
                    cmds.push_front((ind, mode, rdoc));
                    cmds.push_front((ind, mode, ldoc));
                },
                &Group(box ref doc) => {
                    cmds.push_front((ind, mode, doc));
                },
                &Nest(off, box ref doc) => {
                    cmds.push_front((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as int;
                },
            }
        }
    }

    fits
}

impl Doc {

    #[inline]
    pub fn nil() -> Doc {
        Nil
    }

    #[inline]
    pub fn append(self, that:Doc) -> Doc {
        match self {
            Nil => {
                that
            },
            ldoc => match that {
                Nil => {
                    ldoc
                },
                rdoc => {
                    Append(box ldoc, box rdoc)
                },
            }
        }
    }

    #[inline]
    pub fn as_string<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc {
        Group(box self)
    }

    #[inline]
    pub fn nest(self, off:uint) -> Doc {
        Nest(off, box self)
    }

    #[inline]
    pub fn newline() -> Doc {
        Newline
    }

    #[inline]
    pub fn render(&self, width:uint) -> String {
        let mut pos = 0u;
        let mut cmds = RingBuf::new();
        let mut result = String::new();

        cmds.push((0, mode::Break, self));

        loop {
            match cmds.pop_front() {
                None => {
                    break;
                },
                Some((ind, mode, doc)) => match doc {
                    &Nil => {
                    },
                    &Append(box ref ldoc, box ref rdoc) => {
                        cmds.push_front((ind, mode, rdoc));
                        cmds.push_front((ind, mode, ldoc));
                    },
                    &Group(box ref doc) => match mode {
                        mode::Flat => {
                            cmds.push_front((ind, mode::Flat, doc));
                        },
                        mode::Break => {
                            // FIXME: fitting() modifies cmds so we must either
                            // take a clone and pass it or rewrite fitting()
                            // to modify a separate cmd stack and only observe
                            // this one.
                            let mut cmds_dup = cmds.clone();
                            let next = (ind, mode::Flat, doc);
                            cmds_dup.push_front(next);
                            if fitting(cmds_dup, width as int - pos as int) {
                                cmds.push_front(next);
                            } else {
                                cmds.push_front((ind, mode::Break, doc));
                            }
                        }
                    },
                    &Nest(off, box ref doc) => {
                        cmds.push_front((ind + off, mode, doc));
                    },
                    &Newline => {
                        result.push_str(util::string::nl_spaces(ind).as_slice());
                        pos = ind;
                    },
                    &Text(ref str) => {
                        result.push_str(str.as_slice());
                        pos += str.len();
                    },
                }
            }
        }

        result
    }

    #[inline]
    pub fn text<T:Str>(str:T) -> Doc {
        Text(String::from_str(str.as_slice()))
    }

}
<commit_msg>Don't need push_front; replace RingBuf with Vec<commit_after>use super::mode;
use super::util;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;
type Cmd<'a> = (uint,mode::Mode,&'a Doc);

#[inline(always)]
fn fitting(mut cmds:Vec<Cmd>, mut rem:int) -> bool {
    let mut fits = true;

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match cmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(box ref ldoc, box ref rdoc) => {
                    cmds.push((ind, mode, rdoc));
                    cmds.push((ind, mode, ldoc));
                },
                &Group(box ref doc) => {
                    cmds.push((ind, mode, doc));
                },
                &Nest(off, box ref doc) => {
                    cmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as int;
                },
            }
        }
    }

    fits
}

impl Doc {

    #[inline]
    pub fn nil() -> Doc {
        Nil
    }

    #[inline]
    pub fn append(self, that:Doc) -> Doc {
        match self {
            Nil => {
                that
            },
            ldoc => match that {
                Nil => {
                    ldoc
                },
                rdoc => {
                    Append(box ldoc, box rdoc)
                },
            }
        }
    }

    #[inline]
    pub fn as_string<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc {
        Group(box self)
    }

    #[inline]
    pub fn nest(self, off:uint) -> Doc {
        Nest(off, box self)
    }

    #[inline]
    pub fn newline() -> Doc {
        Newline
    }

    #[inline]
    pub fn render(&self, width:uint) -> String {
        let mut pos = 0u;
        let mut cmds = vec![];
        let mut result = String::new();

        cmds.push((0, mode::Break, self));

        loop {
            match cmds.pop() {
                None => {
                    break;
                },
                Some((ind, mode, doc)) => match doc {
                    &Nil => {
                    },
                    &Append(box ref ldoc, box ref rdoc) => {
                        cmds.push((ind, mode, rdoc));
                        cmds.push((ind, mode, ldoc));
                    },
                    &Group(box ref doc) => match mode {
                        mode::Flat => {
                            cmds.push((ind, mode::Flat, doc));
                        },
                        mode::Break => {
                            // FIXME: fitting() modifies cmds so we must either
                            // take a clone and pass it or rewrite fitting()
                            // to modify a separate cmd stack and only observe
                            // this one.
                            let mut cmds_dup = cmds.clone();
                            let next = (ind, mode::Flat, doc);
                            cmds_dup.push(next);
                            if fitting(cmds_dup, width as int - pos as int) {
                                cmds.push(next);
                            } else {
                                cmds.push((ind, mode::Break, doc));
                            }
                        }
                    },
                    &Nest(off, box ref doc) => {
                        cmds.push((ind + off, mode, doc));
                    },
                    &Newline => {
                        result.push_str(util::string::nl_spaces(ind).as_slice());
                        pos = ind;
                    },
                    &Text(ref str) => {
                        result.push_str(str.as_slice());
                        pos += str.len();
                    },
                }
            }
        }

        result
    }

    #[inline]
    pub fn text<T:Str>(str:T) -> Doc {
        Text(String::from_str(str.as_slice()))
    }

}
<|endoftext|>


<commit_before>use std::fmt;
use std::borrow::{Cow, IntoCow};
use std::error::Error as StdError;

///Struct which containing the current position
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct SourcePosition {
    ///Current line of the input
    pub line: i32,
    ///Current column of the input
    pub column: i32
}
impl SourcePosition {
    fn start() -> SourcePosition {
        SourcePosition { line: 1, column: 1 }
    }

    fn update(&mut self, c: &char) {
        self.column += 1;
        if *c == '\n' {
            self.column = 1;
            self.line += 1;
        }
    }
}

///Enum used to store information about an error that has occured
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
    ///Error indicating an unexpected token has been encountered in the stream
    Unexpected(char),
    ///Error indicating that the parser expected something else
    Expected(Cow<'static, str>),
    ///Generic message
    Message(Cow<'static, str>)
}

///Enum used to indicate if a stream has had any elements consumed
#[derive(Clone, PartialEq, Debug, Copy)]
pub enum Consumed<T> {
    ///Constructor indicating that the parser has consumed elements
    Consumed(T),
    ///Constructor indicating that the parser did not consume any elements
    Empty(T)
}

impl <T> Consumed<T> {

    ///Returns true if the `self` is empty
    pub fn is_empty(&self) -> bool {
        match *self {
            Consumed::Empty(_) => true,
            Consumed::Consumed(_) => false
        }
    }

    ///Extracts the contained value
    pub fn into_inner(self) -> T {
        match self {
            Consumed::Empty(x) => x,
            Consumed::Consumed(x) => x
        }
    }

    ///Converts the consumed state into the Consumed state
    pub fn as_consumed(self) -> Consumed<T> {
        Consumed::Consumed(self.into_inner())
    }

    ///Converts the consumed state into the Empty state
    pub fn as_empty(self) -> Consumed<T> {
        Consumed::Empty(self.into_inner())
    }

    ///Maps over the contained value without changing the consumed state
    pub fn map<F, U>(self, f: F) -> Consumed<U>
        where F: FnOnce(T) -> U {
        match self {
            Consumed::Empty(x) => Consumed::Empty(f(x)),
            Consumed::Consumed(x) => Consumed::Consumed(f(x))
        }
    }

    ///Combines the Consumed flags from `self` and the result of `f`
    pub fn combine<F, U, I>(self, f: F) -> ParseResult<U, I>
        where F: FnOnce(T) -> ParseResult<U, I> {
        match self {
            Consumed::Consumed(x) => {
                match f(x) {
                    Ok((v, Consumed::Empty(rest))) => Ok((v, Consumed::Consumed(rest))),
                    Err(Consumed::Empty(err)) => Err(Consumed::Consumed(err)),
                    y => y
                }
            }
            Consumed::Empty(x) => f(x)
        }
    }
}
///Struct which hold information about an error that occured at a specific position.
///Can hold multiple instances of `Error` if more that one error occured at the position.
#[derive(Clone, Debug, PartialEq)]
pub struct ParseError {
    ///The position where the error occured
    pub position: SourcePosition,
    ///A vector containing specific information on what errors occured at `position`
    pub errors: Vec<Error>
}

impl ParseError {
    pub fn new(position: SourcePosition, error: Error) -> ParseError {
        ParseError { position: position, errors: vec![error] }
    }
    pub fn add_message<S>(&mut self, message: S)
        where S: IntoCow<'static, str> {
        self.add_error(Error::Message(message.into_cow()));
    }
    pub fn add_error(&mut self, message: Error) {
        //Don't add duplicate errors
        if self.errors.iter().find(|msg| **msg == message).is_none() {
            self.errors.push(message);
        }
    }
    pub fn set_expected(&mut self, message: Cow<'static, str>) {
        //Remove all other expected messages
        self.errors.retain(|e| match *e { Error::Expected(_) => false, _ => true });
        self.errors.push(Error::Expected(message));
    }
    pub fn merge(mut self, other: ParseError) -> ParseError {
        use std::cmp::Ordering;
        //Only keep the errors which occured after consuming the most amount of data
        match self.position.cmp(&other.position) {
            Ordering::Less => other,
            Ordering::Greater => self,
            Ordering::Equal => {
                for message in other.errors.into_iter() {
                    self.add_error(message);
                }
                self
            }
        }
    }
}

impl StdError for ParseError {
    fn description(&self) -> &str { "parse error" }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "Parse error at {}", self.position));

        //First print the token that we did not expect
        //There should really just be one unexpected message at this point though we print them
        //all to be safe
        let unexpected = self.errors.iter()
            .filter(|e| match **e { Error::Unexpected(_) => true, _ => false } );
        for error in unexpected {
            try!(writeln!(f, "{}", error));
        }

        //Then we print out all the things that were expected in a comma separated list
        //'Expected 'a', 'expression' or 'let'
        let expected_count = self.errors.iter()
            .filter(|e| match **e { Error::Expected(_) => true, _ => false } )
            .count();
        let mut i = 0;
        for error in self.errors.iter() {
            match *error {
                Error::Expected(ref message) => {
                    i += 1;
                    if i == 1 {
                        try!(write!(f, "Expected"));
                    }
                    else if i == expected_count {//Last expected message to be written
                        try!(write!(f, " or"));
                    }
                    else {
                        try!(write!(f, ","));
                    }
                    try!(write!(f, " '{}'", message));
                }
                _ => ()
            }
        }
        if expected_count != 0 {
            try!(writeln!(f, ""));
        }
        //If there are any generic messages we print them out last
        let messages = self.errors.iter()
            .filter(|e| match **e { Error::Message(_) => true, _ => false } );
        for error in messages {
            try!(writeln!(f, "{}", error));
        }
        Ok(())
    }
}
impl fmt::Display for SourcePosition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "line: {}, column: {}", self.line, self.column)
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Unexpected(c) => write!(f, "Unexpected character '{}'", c),
            Error::Expected(ref s) => write!(f, "Expected {}", s),
            Error::Message(ref msg) => write!(f, "{}", msg),
        }
    }
}

///The `State<I>` struct keeps track of the current position in the stream `I`
#[derive(Clone, PartialEq, Debug)]
pub struct State<I> {
    pub position: SourcePosition,
    pub input: I
}

impl <I: Stream> State<I> {
    pub fn new(input: I) -> State<I> {
        State { position: SourcePosition::start(), input: input }
    }

    pub fn as_empty(&self) -> State<I> {
        State { position: self.position, input: self.input.clone() }
    }

    ///`uncons` is the most general way of extracting and item from a stream
    ///It takes a function `f` as argument which should update the position
    ///according to the item that was extracted
    ///Usually you want to use `uncons_char` instead which works directly on character streams
    pub fn uncons<F>(self, f: F) -> ParseResult<<I as Stream>::Item, I>
        where F: FnOnce(&mut SourcePosition, &<I as Stream>::Item) {
        let State { mut position, input, .. } = self;
        match input.uncons() {
            Ok((c, input)) => {
                f(&mut position, &c);
                Ok((c, Consumed::Consumed(State { position: position, input: input })))
            }
            Err(()) => Err(Consumed::Empty(ParseError::new(position, Error::Message("End of input".into_cow()))))
        }
    }
}
impl <I: Stream<Item=char>> State<I> {
    ///Specialized uncons function for character streams which updates the position
    ///with no further action needed
    pub fn uncons_char(self) -> ParseResult<<I as Stream>::Item, I> {
        self.uncons(SourcePosition::update)
    }

}

///A type alias over the specific `Result` type used to indicated parser success/failure.
///`O` is the type that is output on success
///`I` is the specific stream type used in the parser
pub type ParseResult<O, I> = Result<(O, Consumed<State<I>>), Consumed<ParseError>>;

///A stream is a sequence of items that can be extracted one by one
pub trait Stream : Clone {
    type Item;
    ///Takes a stream and removes its first item, yielding the item and the rest of the elements
    ///Returns `Err` when no more elements could be retrieved
    fn uncons(self) -> Result<(Self::Item, Self), ()>;
}

impl <I: Iterator + Clone> Stream for I {
    type Item = <I as Iterator>::Item;
    fn uncons(mut self) -> Result<(I::Item, Self), ()> {
        match self.next() {
            Some(x) => Ok((x, self)),
            None => Err(())
        }
    }
}

impl <'a> Stream for &'a str {
    type Item = char;
    fn uncons(self) -> Result<(char, &'a str), ()> {
        match self.char_indices().next() {
            Some((offset, c)) => Ok((c, &self[offset + c.len_utf8()..])),
            None => Err(())
        }
    }
}

impl <'a, T> Stream for &'a [T] {
    type Item = &'a T;
    fn uncons(self) -> Result<(&'a T, &'a [T]), ()> {
        match self {
            [ref x, rest..] => Ok((x, rest)),
            [] => Err(())
        }
    }
}

///By implementing the `Parser` trait a type says that it can be used to parse an input stream into
///the type `Output`.
pub trait Parser {
    ///A type implementing the `Stream` trait which is the specific type
    ///that is parsed.
    type Input: Stream;
    ///The type which is returned when the parsing is successful.
    type Output;

    ///Entrypoint of the parser
    ///Takes some input and tries to parse it returning a `ParseResult`
    fn parse(&mut self, input: Self::Input) -> Result<(Self::Output, Self::Input), ParseError> {
        match self.parse_state(State::new(input)) {
            Ok((v, state)) => Ok((v, state.into_inner().input)),
            Err(error) => Err(error.into_inner())
        }
    }
    ///Parses using the state `input` by calling Stream::uncons one or more times
    ///On success returns `Ok((value, new_state))` on failure it returns `Err(error)`
    fn parse_state(&mut self, input: State<Self::Input>) -> ParseResult<Self::Output, Self::Input>;
}
impl <'a, I, O, P: ?Sized> Parser for &'a mut P
    where I: Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
        (*self).parse_state(input)
    }
}
impl <I, O, P: ?Sized> Parser for Box<P>
    where I: Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
        (**self).parse_state(input)
    }
}
<commit_msg>Replace unnecessary use of char_indices() by simply using chars()<commit_after>use std::fmt;
use std::borrow::{Cow, IntoCow};
use std::error::Error as StdError;

///Struct which containing the current position
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct SourcePosition {
    ///Current line of the input
    pub line: i32,
    ///Current column of the input
    pub column: i32
}
impl SourcePosition {
    fn start() -> SourcePosition {
        SourcePosition { line: 1, column: 1 }
    }

    fn update(&mut self, c: &char) {
        self.column += 1;
        if *c == '\n' {
            self.column = 1;
            self.line += 1;
        }
    }
}

///Enum used to store information about an error that has occured
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
    ///Error indicating an unexpected token has been encountered in the stream
    Unexpected(char),
    ///Error indicating that the parser expected something else
    Expected(Cow<'static, str>),
    ///Generic message
    Message(Cow<'static, str>)
}

///Enum used to indicate if a stream has had any elements consumed
#[derive(Clone, PartialEq, Debug, Copy)]
pub enum Consumed<T> {
    ///Constructor indicating that the parser has consumed elements
    Consumed(T),
    ///Constructor indicating that the parser did not consume any elements
    Empty(T)
}

impl <T> Consumed<T> {

    ///Returns true if the `self` is empty
    pub fn is_empty(&self) -> bool {
        match *self {
            Consumed::Empty(_) => true,
            Consumed::Consumed(_) => false
        }
    }

    ///Extracts the contained value
    pub fn into_inner(self) -> T {
        match self {
            Consumed::Empty(x) => x,
            Consumed::Consumed(x) => x
        }
    }

    ///Converts the consumed state into the Consumed state
    pub fn as_consumed(self) -> Consumed<T> {
        Consumed::Consumed(self.into_inner())
    }

    ///Converts the consumed state into the Empty state
    pub fn as_empty(self) -> Consumed<T> {
        Consumed::Empty(self.into_inner())
    }

    ///Maps over the contained value without changing the consumed state
    pub fn map<F, U>(self, f: F) -> Consumed<U>
        where F: FnOnce(T) -> U {
        match self {
            Consumed::Empty(x) => Consumed::Empty(f(x)),
            Consumed::Consumed(x) => Consumed::Consumed(f(x))
        }
    }

    ///Combines the Consumed flags from `self` and the result of `f`
    pub fn combine<F, U, I>(self, f: F) -> ParseResult<U, I>
        where F: FnOnce(T) -> ParseResult<U, I> {
        match self {
            Consumed::Consumed(x) => {
                match f(x) {
                    Ok((v, Consumed::Empty(rest))) => Ok((v, Consumed::Consumed(rest))),
                    Err(Consumed::Empty(err)) => Err(Consumed::Consumed(err)),
                    y => y
                }
            }
            Consumed::Empty(x) => f(x)
        }
    }
}
///Struct which hold information about an error that occured at a specific position.
///Can hold multiple instances of `Error` if more that one error occured at the position.
#[derive(Clone, Debug, PartialEq)]
pub struct ParseError {
    ///The position where the error occured
    pub position: SourcePosition,
    ///A vector containing specific information on what errors occured at `position`
    pub errors: Vec<Error>
}

impl ParseError {
    pub fn new(position: SourcePosition, error: Error) -> ParseError {
        ParseError { position: position, errors: vec![error] }
    }
    pub fn add_message<S>(&mut self, message: S)
        where S: IntoCow<'static, str> {
        self.add_error(Error::Message(message.into_cow()));
    }
    pub fn add_error(&mut self, message: Error) {
        //Don't add duplicate errors
        if self.errors.iter().find(|msg| **msg == message).is_none() {
            self.errors.push(message);
        }
    }
    pub fn set_expected(&mut self, message: Cow<'static, str>) {
        //Remove all other expected messages
        self.errors.retain(|e| match *e { Error::Expected(_) => false, _ => true });
        self.errors.push(Error::Expected(message));
    }
    pub fn merge(mut self, other: ParseError) -> ParseError {
        use std::cmp::Ordering;
        //Only keep the errors which occured after consuming the most amount of data
        match self.position.cmp(&other.position) {
            Ordering::Less => other,
            Ordering::Greater => self,
            Ordering::Equal => {
                for message in other.errors.into_iter() {
                    self.add_error(message);
                }
                self
            }
        }
    }
}

impl StdError for ParseError {
    fn description(&self) -> &str { "parse error" }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "Parse error at {}", self.position));

        //First print the token that we did not expect
        //There should really just be one unexpected message at this point though we print them
        //all to be safe
        let unexpected = self.errors.iter()
            .filter(|e| match **e { Error::Unexpected(_) => true, _ => false } );
        for error in unexpected {
            try!(writeln!(f, "{}", error));
        }

        //Then we print out all the things that were expected in a comma separated list
        //'Expected 'a', 'expression' or 'let'
        let expected_count = self.errors.iter()
            .filter(|e| match **e { Error::Expected(_) => true, _ => false } )
            .count();
        let mut i = 0;
        for error in self.errors.iter() {
            match *error {
                Error::Expected(ref message) => {
                    i += 1;
                    if i == 1 {
                        try!(write!(f, "Expected"));
                    }
                    else if i == expected_count {//Last expected message to be written
                        try!(write!(f, " or"));
                    }
                    else {
                        try!(write!(f, ","));
                    }
                    try!(write!(f, " '{}'", message));
                }
                _ => ()
            }
        }
        if expected_count != 0 {
            try!(writeln!(f, ""));
        }
        //If there are any generic messages we print them out last
        let messages = self.errors.iter()
            .filter(|e| match **e { Error::Message(_) => true, _ => false } );
        for error in messages {
            try!(writeln!(f, "{}", error));
        }
        Ok(())
    }
}
impl fmt::Display for SourcePosition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "line: {}, column: {}", self.line, self.column)
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Unexpected(c) => write!(f, "Unexpected character '{}'", c),
            Error::Expected(ref s) => write!(f, "Expected {}", s),
            Error::Message(ref msg) => write!(f, "{}", msg),
        }
    }
}

///The `State<I>` struct keeps track of the current position in the stream `I`
#[derive(Clone, PartialEq, Debug)]
pub struct State<I> {
    pub position: SourcePosition,
    pub input: I
}

impl <I: Stream> State<I> {
    pub fn new(input: I) -> State<I> {
        State { position: SourcePosition::start(), input: input }
    }

    pub fn as_empty(&self) -> State<I> {
        State { position: self.position, input: self.input.clone() }
    }

    ///`uncons` is the most general way of extracting and item from a stream
    ///It takes a function `f` as argument which should update the position
    ///according to the item that was extracted
    ///Usually you want to use `uncons_char` instead which works directly on character streams
    pub fn uncons<F>(self, f: F) -> ParseResult<<I as Stream>::Item, I>
        where F: FnOnce(&mut SourcePosition, &<I as Stream>::Item) {
        let State { mut position, input, .. } = self;
        match input.uncons() {
            Ok((c, input)) => {
                f(&mut position, &c);
                Ok((c, Consumed::Consumed(State { position: position, input: input })))
            }
            Err(()) => Err(Consumed::Empty(ParseError::new(position, Error::Message("End of input".into_cow()))))
        }
    }
}
impl <I: Stream<Item=char>> State<I> {
    ///Specialized uncons function for character streams which updates the position
    ///with no further action needed
    pub fn uncons_char(self) -> ParseResult<<I as Stream>::Item, I> {
        self.uncons(SourcePosition::update)
    }

}

///A type alias over the specific `Result` type used to indicated parser success/failure.
///`O` is the type that is output on success
///`I` is the specific stream type used in the parser
pub type ParseResult<O, I> = Result<(O, Consumed<State<I>>), Consumed<ParseError>>;

///A stream is a sequence of items that can be extracted one by one
pub trait Stream : Clone {
    type Item;
    ///Takes a stream and removes its first item, yielding the item and the rest of the elements
    ///Returns `Err` when no more elements could be retrieved
    fn uncons(self) -> Result<(Self::Item, Self), ()>;
}

impl <I: Iterator + Clone> Stream for I {
    type Item = <I as Iterator>::Item;
    fn uncons(mut self) -> Result<(I::Item, Self), ()> {
        match self.next() {
            Some(x) => Ok((x, self)),
            None => Err(())
        }
    }
}

impl <'a> Stream for &'a str {
    type Item = char;
    fn uncons(self) -> Result<(char, &'a str), ()> {
        match self.chars().next() {
            Some(c) => Ok((c, &self[c.len_utf8()..])),
            None => Err(())
        }
    }
}

impl <'a, T> Stream for &'a [T] {
    type Item = &'a T;
    fn uncons(self) -> Result<(&'a T, &'a [T]), ()> {
        match self {
            [ref x, rest..] => Ok((x, rest)),
            [] => Err(())
        }
    }
}

///By implementing the `Parser` trait a type says that it can be used to parse an input stream into
///the type `Output`.
pub trait Parser {
    ///A type implementing the `Stream` trait which is the specific type
    ///that is parsed.
    type Input: Stream;
    ///The type which is returned when the parsing is successful.
    type Output;

    ///Entrypoint of the parser
    ///Takes some input and tries to parse it returning a `ParseResult`
    fn parse(&mut self, input: Self::Input) -> Result<(Self::Output, Self::Input), ParseError> {
        match self.parse_state(State::new(input)) {
            Ok((v, state)) => Ok((v, state.into_inner().input)),
            Err(error) => Err(error.into_inner())
        }
    }
    ///Parses using the state `input` by calling Stream::uncons one or more times
    ///On success returns `Ok((value, new_state))` on failure it returns `Err(error)`
    fn parse_state(&mut self, input: State<Self::Input>) -> ParseResult<Self::Output, Self::Input>;
}
impl <'a, I, O, P: ?Sized> Parser for &'a mut P
    where I: Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
        (*self).parse_state(input)
    }
}
impl <I, O, P: ?Sized> Parser for Box<P>
    where I: Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
        (**self).parse_state(input)
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::collections::hashmap::HashMap;

pub struct Params {
    captures: HashMap<String, String>
}

impl Params {
    pub fn new<I: Iterator<String>>(uri: &str, matcher: Regex, params: I) -> Params {
        let captures = matcher.captures(uri).unwrap();
        Params {
            captures: params.map(|p| (p.clone(), captures.name(p.as_slice()).to_string())).collect()
        }
    }

    pub fn get<'a>(&'a self, param: String) -> Option<&'a String> {
        self.captures.find(&param)
    }
}

<commit_msg>(test) Added tests and benching of Params.<commit_after>use regex::Regex;
use std::collections::hashmap::HashMap;

pub struct Params {
    captures: HashMap<String, String>
}

impl Params {
    pub fn new<I: Iterator<String>>(uri: &str, matcher: Regex, params: I) -> Params {
        let captures = matcher.captures(uri).unwrap();
        Params {
            captures: params.map(|p| (p.clone(), captures.name(p.as_slice()).to_string())).collect()
        }
    }

    pub fn get<'a>(&'a self, param: &'static str) -> Option<String> {
        self.captures.find(&param.to_string()).and_then(|p| Some(p.clone()))
    }
}

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

    #[test]
    fn test_new() {
        let params = Params::new("/users/7324", deglob("/users/:userid".to_string()), vec!["userid".to_string()].move_iter());
        assert_eq!(params.get("userid").unwrap(), "7324".to_string());
    }

    #[bench]
    fn bench_get(b: &mut Bencher) {
        let params = Params::new("/users/7324", deglob("/users/:userid".to_string()), vec!["userid".to_string()].move_iter());
        b.iter(|| {
            black_box(params.get("userid").unwrap())
        })
    }
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io;
use std::net::SocketAddr;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::mpsc::sync_channel;
use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant};
use std::fmt;

use rpc::Rpc;
use rpc::connection::{Connection, ConnectionOptions};
use util::duration_to_ms;
use Result;
use Error;

use mio::{
    EventLoop,
    EventLoopConfig,
    EventSet,
    Handler,
    Sender,
    Token,
};
use slab::Slab;

pub type Loop = EventLoop<MessengerHandler>;

pub enum Command {
    Shutdown,
    Send(Rpc),
    Timer((Duration, Box<TimerCallback>)),
}

impl fmt::Debug for Command {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Command::Shutdown => write!(f, "Command::Shutdown"),
            Command::Send(ref rpc) => write!(f, "Command::Send({:?})", rpc),
            Command::Timer((ref duration, _)) => write!(f, "Command::Timer({:?})", duration),
        }
    }
}

/// Essentially FnBox...
pub trait TimerCallback: Send {
    fn callback(self: Box<Self>);
}

impl <F> TimerCallback for F where F: FnOnce() + Send {
    fn callback(self: Box<F>) {
        (*self)()
    }
}

pub enum TimeoutKind {

    /// Active while a connection is reset. After expiration, the connection creates a new socket
    /// and attempts negotiation.
    ConnectionReset(Token),

    /// An RPC timeout.
    ///
    /// This timeout tracks an RPC timeout deadline. When it expires, the RPC should be timed out.
    Rpc(Token, usize),

    /// A general timer timeout.
    Timer(Box<TimerCallback>),
}

struct Inner {
    channel: Sender<Command>,
    thread: JoinHandle<io::Result<()>>,
}

#[derive(Clone)]
pub struct Messenger {
    inner: Arc<Inner>,
}

impl Messenger {
    pub fn new() -> io::Result<Messenger> {
        let mut event_loop_config = EventLoopConfig::new();
        // Timer granularity of 10ms.
        event_loop_config.timer_tick_ms(10);
        let mut event_loop = try!(EventLoop::configured(event_loop_config));
        let channel = event_loop.channel();
        let thread = thread::spawn(move || {
            let mut connection_manager = MessengerHandler::new();
            event_loop.run(&mut connection_manager)
        });
        Ok(Messenger {
            inner: Arc::new(Inner {
                channel: channel,
                thread: thread,
            }),
        })
    }

    /// Sends a generic Kudu RPC, and executes the callback when the RPC is complete.
    pub fn send(&self, mut rpc: Rpc) {
        // TODO: is there a better way to handle queue failure?
        debug_assert!(rpc.callback.is_some());
        rpc.response.clear();
        self.inner.channel.send(Command::Send(rpc)).unwrap();
    }

    pub fn delayed_send(&self, delay: Duration, rpc: Rpc) {
        let deadline = rpc.deadline.clone();
        if Instant::now() + delay > deadline {
            rpc.fail(Error::TimedOut);
            return;
        }

        let messenger = self.clone();
        let rpc: Rpc = rpc;
        self.timer(delay, Box::new(move || { messenger.send(rpc) }));
    }

    pub fn send_sync(&self, mut rpc: Rpc) -> (Result<()>, Rpc) {
        let (send, recv) = sync_channel(0);
        assert!(rpc.callback.is_none());
        rpc.callback = Some(Box::new(move |result, rpc| send.send((result, rpc)).unwrap()));
        self.send(rpc);
        recv.recv().unwrap()
    }

    pub fn timer(&self, duration: Duration, callback: Box<TimerCallback>) {
        self.inner.channel.send(Command::Timer((duration, callback))).unwrap();
    }
}

pub struct MessengerHandler {
    connection_slab: Slab<Connection, Token>,
    index: HashMap<SocketAddr, Token>,
    cxn_options: Rc<ConnectionOptions>,
}

impl MessengerHandler {
    fn new() -> MessengerHandler {
        MessengerHandler {
            connection_slab: Slab::new(128),
            index: HashMap::new(),
            cxn_options: Rc::new(ConnectionOptions::default()),
        }
    }
}

impl fmt::Debug for MessengerHandler {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MessengerHandler {{ connections: {} }}", self.connection_slab.count())
    }
}

impl Handler for MessengerHandler {

    type Timeout = TimeoutKind;
    type Message = Command;

    fn ready(&mut self, event_loop: &mut Loop, token: Token, events: EventSet) {
        self.connection_slab[token].ready(event_loop, token, events)
    }

    fn notify(&mut self, event_loop: &mut Loop, command: Command) {
        match command {
            Command::Shutdown => event_loop.shutdown(),
            Command::Send(rpc) => {
                let token = self.index.get(&rpc.addr).cloned().unwrap_or_else(|| {
                    // No open connection for the socket address; create a new one.
                    if !self.connection_slab.has_remaining() {
                        let count = self.connection_slab.count();
                        self.connection_slab.grow(count / 2);
                    }
                    let cxn_options = self.cxn_options.clone();
                    let token = self.connection_slab
                                    .insert_with(|token| Connection::new(event_loop,
                                                                         token,
                                                                         rpc.addr,
                                                                         cxn_options))
                                    .unwrap();
                    self.index.insert(rpc.addr, token);
                    token
                });
                self.connection_slab[token].send_rpc(event_loop, token, rpc);
            },
            Command::Timer((duration, callback)) => {
                event_loop.timeout_ms(TimeoutKind::Timer(callback),
                                      duration_to_ms(&duration)).unwrap();
            }
        }
    }

    fn timeout(&mut self, event_loop: &mut Loop, timeout: TimeoutKind) {

        match timeout {
            TimeoutKind::ConnectionReset(token) => {
                let drop_cxn = self.connection_slab
                                   .get_mut(token)
                                   .unwrap()
                                   .reset_timeout(event_loop, token);
                if drop_cxn {
                    let cxn = self.connection_slab.remove(token).unwrap();
                    let removed_token = self.index.remove(cxn.addr()).unwrap();
                    assert!(removed_token == token);
                    debug!("{:?}: closing", cxn);
                }
            },
            TimeoutKind::Rpc(token, call_id) => {
                // Connection RPC timeout. A note on the unwrap calls below: the connection
                // carefully cancels all outstanding timers before asking to be torn down in
                // Connection#timeout, so if a connection timer fires, the connection must still
                // exist.
                self.connection_slab
                    .get_mut(token)
                    .unwrap()
                    .rpc_timeout(call_id);
            },
            TimeoutKind::Timer(callback) => callback.callback(),
        }
    }
}

#[cfg(test)]
mod tests {

    use std::sync::Arc;
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::mpsc::{sync_channel, SyncSender};
    use std::time::{Duration, Instant};

    use env_logger;
    use kudu_pb;

    use mini_cluster::{self, MiniCluster, MiniClusterConfig};
    use rpc::{channel_callback, retry_channel_callback, master, Callback, Rpc};
    use super::*;
    use Error;
    use Result;

    #[test]
    fn send() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .log_rpc_trace(true));

        let messenger = Messenger::new().unwrap();
        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        let mut rpc = master::ping(cluster.master_addrs()[0],
                                   Instant::now() + Duration::from_secs(5),
                                   kudu_pb::master::PingRequestPB::new());
        rpc.callback = Some(retry_channel_callback(messenger.clone(), send));

        messenger.send(rpc);
        let (result, _) = recv.recv().unwrap();
        assert_eq!(Ok(()), result);
    }

    #[test]
    fn send_concurrent() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .log_rpc_trace(true));
        let messenger = Messenger::new().unwrap();

        let (send, recv) = sync_channel::<Result<()>>(100);

        struct PingCB(u8, Messenger, SyncSender<Result<()>>);
        impl Callback for PingCB {
            fn callback(mut self: Box<Self>, result: Result<()>, mut rpc: Rpc) {
                if result.as_ref().err().map_or(false, |error| error.is_network_error()) {
                    trace!("retrying RPC {:?} after network error: {}", rpc, result.unwrap_err());
                    let messenger = self.1.clone();
                    rpc.response.clear();
                    rpc.callback = Some(self);
                    return messenger.send(rpc);
                }

                let is_ok = result.is_ok();
                self.2.send(result).unwrap();
                self.0 -= 1;
                if is_ok && self.0 > 0 {
                    let messenger = self.1.clone();
                    rpc.response.clear();
                    rpc.callback = Some(self);
                    messenger.send(rpc);
                }
            }
        }

        // Send 100 pings, with 10 outstanding at a time.
        for _ in 0..10 {
            let mut rpc = master::ping(cluster.master_addrs()[0],
                                       Instant::now() + Duration::from_secs(5),
                                       kudu_pb::master::PingRequestPB::new());

            rpc.callback = Some(Box::new(PingCB(10, messenger.clone(), send.clone())));
            messenger.send(rpc);
        }
        drop(send);

        let mut count = 0;
        for result in recv {
            result.unwrap();
            count += 1;
        }
        assert_eq!(100, count);
    }

    #[test]
    fn timeout() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_masters(1)
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .rpc_negotiation_delay(1000));
        let messenger = Messenger::new().unwrap();

        let now = Instant::now();
        let mut rpc = master::ping(cluster.master_addrs()[0], now + Duration::from_millis(100),
                                   kudu_pb::master::PingRequestPB::new());

        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        rpc.callback = Some(retry_channel_callback(messenger.clone(), send));
        messenger.send(rpc);

        let (result, _) = recv.recv().unwrap();

        match result {
            Ok(()) => panic!("expected failure"),
            Err(Error::TimedOut) => (),
            Err(other) => panic!("unexpected error: {}", other),
        }

        let elapsed = Instant::now().duration_since(now);

        // If this gets flaky, figure out how to get tighter times out of mio.
        assert!(elapsed > Duration::from_millis(100), "expected: 100ms, elapsed: {:?}", elapsed);
        assert!(elapsed < Duration::from_millis(150), "expected: 100ms, elapsed: {:?}", elapsed);
    }

    #[test]
    fn cancel() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_masters(1)
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .rpc_negotiation_delay(1000));
        let messenger = Messenger::new().unwrap();

        let now = Instant::now();
        let mut rpc = master::ping(cluster.master_addrs()[0], now + Duration::from_millis(500),
                                   kudu_pb::master::PingRequestPB::new());

        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        let cancel = Arc::new(AtomicBool::new(false));
        rpc.cancel = Some(cancel.clone());
        rpc.callback = Some(channel_callback(send));
        messenger.send(rpc);

        cancel.store(true, Ordering::Relaxed);
        let (result, _) = recv.recv().unwrap();

        match result {
            Ok(()) => panic!("expected failure"),
            Err(Error::Cancelled) => (),
            Err(other) => panic!("unexpected error: {}", other),
        }

        let elapsed = Instant::now().duration_since(now);
        assert!(elapsed < Duration::from_millis(25), "expected: 0ms, elapsed: {:?}", elapsed);
    }

    #[test]
    fn timer() {
        let _ = env_logger::init();
        let messenger = Messenger::new().unwrap();

        let now = Instant::now();
        let (send, recv) = sync_channel::<()>(0);

        messenger.timer(Duration::from_millis(100), Box::new(move || send.send(()).unwrap()));

        recv.recv().unwrap();

        let elapsed = Instant::now().duration_since(now);
        info!("elapsed: {:?}", elapsed);

        // If this gets flaky, figure out how to get tighter times out of mio.
        assert!(elapsed > Duration::from_millis(75), "expected: 100ms, elapsed: {:?}", elapsed);
        assert!(elapsed < Duration::from_millis(125), "expected: 100ms, elapsed: {:?}", elapsed);
    }

    /// Tests that a connection will fail an RPC after a failure to connect.
    #[test]
    fn test_connection_error() {
        let _ = env_logger::init();
        let messenger = Messenger::new().unwrap();

        let rpc = master::ping(mini_cluster::get_unbound_address(),
                               Instant::now() + Duration::from_millis(100),
                               kudu_pb::master::PingRequestPB::new());

        let (result, _) = messenger.send_sync(rpc);
        assert_eq!(Err(Error::ConnectionError), result);
    }

    /// Tests that a connection will fail an RPC after a failure to connect.
    #[test]
    fn connection_hangup() {
        let _ = env_logger::init();
        let mut cluster = MiniCluster::new(MiniClusterConfig::default()
                                                             .num_tservers(0)
                                                             .log_rpc_negotiation_trace(true)
                                                             .log_rpc_trace(true));
        let messenger = Messenger::new().unwrap();
        let mut rpc = master::ping(cluster.master_addrs()[0],
                                   Instant::now() + Duration::from_secs(5),
                                   kudu_pb::master::PingRequestPB::new());

        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        rpc.callback = Some(retry_channel_callback(messenger.clone(), send));
        messenger.send(rpc);

        let (result, _) = recv.recv().unwrap();

        assert_eq!(Ok(()), result);

        let master = cluster.master_addrs()[0];
        cluster.stop_node(master);

        let rpc = master::ping(cluster.master_addrs()[0],
                               Instant::now() + Duration::from_secs(5),
                               kudu_pb::master::PingRequestPB::new());

        let (result, _) = messenger.send_sync(rpc);
        assert_eq!(Err(Error::ConnectionError), result);
    }
}
<commit_msg>Timers can fire early<commit_after>use std::collections::HashMap;
use std::io;
use std::net::SocketAddr;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::mpsc::sync_channel;
use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant};
use std::fmt;

use rpc::Rpc;
use rpc::connection::{Connection, ConnectionOptions};
use util::duration_to_ms;
use Result;
use Error;

use mio::{
    EventLoop,
    EventLoopConfig,
    EventSet,
    Handler,
    Sender,
    Token,
};
use slab::Slab;

pub type Loop = EventLoop<MessengerHandler>;

pub enum Command {
    Shutdown,
    Send(Rpc),
    Timer((Duration, Box<TimerCallback>)),
}

impl fmt::Debug for Command {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Command::Shutdown => write!(f, "Command::Shutdown"),
            Command::Send(ref rpc) => write!(f, "Command::Send({:?})", rpc),
            Command::Timer((ref duration, _)) => write!(f, "Command::Timer({:?})", duration),
        }
    }
}

/// Essentially FnBox...
pub trait TimerCallback: Send {
    fn callback(self: Box<Self>);
}

impl <F> TimerCallback for F where F: FnOnce() + Send {
    fn callback(self: Box<F>) {
        (*self)()
    }
}

pub enum TimeoutKind {

    /// Active while a connection is reset. After expiration, the connection creates a new socket
    /// and attempts negotiation.
    ConnectionReset(Token),

    /// An RPC timeout.
    ///
    /// This timeout tracks an RPC timeout deadline. When it expires, the RPC should be timed out.
    Rpc(Token, usize),

    /// A general timer timeout.
    Timer(Box<TimerCallback>),
}

struct Inner {
    channel: Sender<Command>,
    thread: JoinHandle<io::Result<()>>,
}

#[derive(Clone)]
pub struct Messenger {
    inner: Arc<Inner>,
}

impl Messenger {
    pub fn new() -> io::Result<Messenger> {
        let mut event_loop_config = EventLoopConfig::new();
        // Timer granularity of 10ms.
        event_loop_config.timer_tick_ms(10);
        let mut event_loop = try!(EventLoop::configured(event_loop_config));
        let channel = event_loop.channel();
        let thread = thread::spawn(move || {
            let mut connection_manager = MessengerHandler::new();
            event_loop.run(&mut connection_manager)
        });
        Ok(Messenger {
            inner: Arc::new(Inner {
                channel: channel,
                thread: thread,
            }),
        })
    }

    /// Sends a generic Kudu RPC, and executes the callback when the RPC is complete.
    pub fn send(&self, mut rpc: Rpc) {
        // TODO: is there a better way to handle queue failure?
        debug_assert!(rpc.callback.is_some());
        rpc.response.clear();
        self.inner.channel.send(Command::Send(rpc)).unwrap();
    }

    pub fn delayed_send(&self, delay: Duration, rpc: Rpc) {
        let deadline = rpc.deadline.clone();
        if Instant::now() + delay > deadline {
            rpc.fail(Error::TimedOut);
            return;
        }

        let messenger = self.clone();
        let rpc: Rpc = rpc;
        self.timer(delay, Box::new(move || { messenger.send(rpc) }));
    }

    pub fn send_sync(&self, mut rpc: Rpc) -> (Result<()>, Rpc) {
        let (send, recv) = sync_channel(0);
        assert!(rpc.callback.is_none());
        rpc.callback = Some(Box::new(move |result, rpc| send.send((result, rpc)).unwrap()));
        self.send(rpc);
        recv.recv().unwrap()
    }

    pub fn timer(&self, duration: Duration, callback: Box<TimerCallback>) {
        self.inner.channel.send(Command::Timer((duration, callback))).unwrap();
    }
}

pub struct MessengerHandler {
    connection_slab: Slab<Connection, Token>,
    index: HashMap<SocketAddr, Token>,
    cxn_options: Rc<ConnectionOptions>,
}

impl MessengerHandler {
    fn new() -> MessengerHandler {
        MessengerHandler {
            connection_slab: Slab::new(128),
            index: HashMap::new(),
            cxn_options: Rc::new(ConnectionOptions::default()),
        }
    }
}

impl fmt::Debug for MessengerHandler {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MessengerHandler {{ connections: {} }}", self.connection_slab.count())
    }
}

impl Handler for MessengerHandler {

    type Timeout = TimeoutKind;
    type Message = Command;

    fn ready(&mut self, event_loop: &mut Loop, token: Token, events: EventSet) {
        self.connection_slab[token].ready(event_loop, token, events)
    }

    fn notify(&mut self, event_loop: &mut Loop, command: Command) {
        match command {
            Command::Shutdown => event_loop.shutdown(),
            Command::Send(rpc) => {
                let token = self.index.get(&rpc.addr).cloned().unwrap_or_else(|| {
                    // No open connection for the socket address; create a new one.
                    if !self.connection_slab.has_remaining() {
                        let count = self.connection_slab.count();
                        self.connection_slab.grow(count / 2);
                    }
                    let cxn_options = self.cxn_options.clone();
                    let token = self.connection_slab
                                    .insert_with(|token| Connection::new(event_loop,
                                                                         token,
                                                                         rpc.addr,
                                                                         cxn_options))
                                    .unwrap();
                    self.index.insert(rpc.addr, token);
                    token
                });
                self.connection_slab[token].send_rpc(event_loop, token, rpc);
            },
            Command::Timer((duration, callback)) => {
                event_loop.timeout_ms(TimeoutKind::Timer(callback),
                                      duration_to_ms(&duration)).unwrap();
            }
        }
    }

    fn timeout(&mut self, event_loop: &mut Loop, timeout: TimeoutKind) {

        match timeout {
            TimeoutKind::ConnectionReset(token) => {
                let drop_cxn = self.connection_slab
                                   .get_mut(token)
                                   .unwrap()
                                   .reset_timeout(event_loop, token);
                if drop_cxn {
                    let cxn = self.connection_slab.remove(token).unwrap();
                    let removed_token = self.index.remove(cxn.addr()).unwrap();
                    assert!(removed_token == token);
                    debug!("{:?}: closing", cxn);
                }
            },
            TimeoutKind::Rpc(token, call_id) => {
                // Connection RPC timeout. A note on the unwrap calls below: the connection
                // carefully cancels all outstanding timers before asking to be torn down in
                // Connection#timeout, so if a connection timer fires, the connection must still
                // exist.
                self.connection_slab
                    .get_mut(token)
                    .unwrap()
                    .rpc_timeout(call_id);
            },
            TimeoutKind::Timer(callback) => callback.callback(),
        }
    }
}

#[cfg(test)]
mod tests {

    use std::sync::Arc;
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::mpsc::{sync_channel, SyncSender};
    use std::time::{Duration, Instant};

    use env_logger;
    use kudu_pb;

    use mini_cluster::{self, MiniCluster, MiniClusterConfig};
    use rpc::{channel_callback, retry_channel_callback, master, Callback, Rpc};
    use super::*;
    use Error;
    use Result;

    #[test]
    fn send() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .log_rpc_trace(true));

        let messenger = Messenger::new().unwrap();
        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        let mut rpc = master::ping(cluster.master_addrs()[0],
                                   Instant::now() + Duration::from_secs(5),
                                   kudu_pb::master::PingRequestPB::new());
        rpc.callback = Some(retry_channel_callback(messenger.clone(), send));

        messenger.send(rpc);
        let (result, _) = recv.recv().unwrap();
        assert_eq!(Ok(()), result);
    }

    #[test]
    fn send_concurrent() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .log_rpc_trace(true));
        let messenger = Messenger::new().unwrap();

        let (send, recv) = sync_channel::<Result<()>>(100);

        struct PingCB(u8, Messenger, SyncSender<Result<()>>);
        impl Callback for PingCB {
            fn callback(mut self: Box<Self>, result: Result<()>, mut rpc: Rpc) {
                if result.as_ref().err().map_or(false, |error| error.is_network_error()) {
                    trace!("retrying RPC {:?} after network error: {}", rpc, result.unwrap_err());
                    let messenger = self.1.clone();
                    rpc.response.clear();
                    rpc.callback = Some(self);
                    return messenger.send(rpc);
                }

                let is_ok = result.is_ok();
                self.2.send(result).unwrap();
                self.0 -= 1;
                if is_ok && self.0 > 0 {
                    let messenger = self.1.clone();
                    rpc.response.clear();
                    rpc.callback = Some(self);
                    messenger.send(rpc);
                }
            }
        }

        // Send 100 pings, with 10 outstanding at a time.
        for _ in 0..10 {
            let mut rpc = master::ping(cluster.master_addrs()[0],
                                       Instant::now() + Duration::from_secs(5),
                                       kudu_pb::master::PingRequestPB::new());

            rpc.callback = Some(Box::new(PingCB(10, messenger.clone(), send.clone())));
            messenger.send(rpc);
        }
        drop(send);

        let mut count = 0;
        for result in recv {
            result.unwrap();
            count += 1;
        }
        assert_eq!(100, count);
    }

    #[test]
    fn timeout() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_masters(1)
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .rpc_negotiation_delay(1000));
        let messenger = Messenger::new().unwrap();

        let now = Instant::now();
        let mut rpc = master::ping(cluster.master_addrs()[0], now + Duration::from_millis(100),
                                   kudu_pb::master::PingRequestPB::new());

        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        rpc.callback = Some(retry_channel_callback(messenger.clone(), send));
        messenger.send(rpc);

        let (result, _) = recv.recv().unwrap();

        match result {
            Ok(()) => panic!("expected failure"),
            Err(Error::TimedOut) => (),
            Err(other) => panic!("unexpected error: {}", other),
        }

        let elapsed = Instant::now().duration_since(now);

        // If this gets flaky, figure out how to get tighter times out of mio.
        assert!(elapsed > Duration::from_millis(90), "expected: 100ms, elapsed: {:?}", elapsed);
        assert!(elapsed < Duration::from_millis(150), "expected: 100ms, elapsed: {:?}", elapsed);
    }

    #[test]
    fn cancel() {
        let _ = env_logger::init();
        let cluster = MiniCluster::new(MiniClusterConfig::default()
                                                         .num_masters(1)
                                                         .num_tservers(0)
                                                         .log_rpc_negotiation_trace(true)
                                                         .rpc_negotiation_delay(1000));
        let messenger = Messenger::new().unwrap();

        let now = Instant::now();
        let mut rpc = master::ping(cluster.master_addrs()[0], now + Duration::from_millis(500),
                                   kudu_pb::master::PingRequestPB::new());

        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        let cancel = Arc::new(AtomicBool::new(false));
        rpc.cancel = Some(cancel.clone());
        rpc.callback = Some(channel_callback(send));
        messenger.send(rpc);

        cancel.store(true, Ordering::Relaxed);
        let (result, _) = recv.recv().unwrap();

        match result {
            Ok(()) => panic!("expected failure"),
            Err(Error::Cancelled) => (),
            Err(other) => panic!("unexpected error: {}", other),
        }

        let elapsed = Instant::now().duration_since(now);
        assert!(elapsed < Duration::from_millis(25), "expected: 0ms, elapsed: {:?}", elapsed);
    }

    #[test]
    fn timer() {
        let _ = env_logger::init();
        let messenger = Messenger::new().unwrap();

        let now = Instant::now();
        let (send, recv) = sync_channel::<()>(0);

        messenger.timer(Duration::from_millis(100), Box::new(move || send.send(()).unwrap()));

        recv.recv().unwrap();

        let elapsed = Instant::now().duration_since(now);
        info!("elapsed: {:?}", elapsed);

        // If this gets flaky, figure out how to get tighter times out of mio.
        assert!(elapsed > Duration::from_millis(75), "expected: 100ms, elapsed: {:?}", elapsed);
        assert!(elapsed < Duration::from_millis(125), "expected: 100ms, elapsed: {:?}", elapsed);
    }

    /// Tests that a connection will fail an RPC after a failure to connect.
    #[test]
    fn test_connection_error() {
        let _ = env_logger::init();
        let messenger = Messenger::new().unwrap();

        let rpc = master::ping(mini_cluster::get_unbound_address(),
                               Instant::now() + Duration::from_millis(100),
                               kudu_pb::master::PingRequestPB::new());

        let (result, _) = messenger.send_sync(rpc);
        assert_eq!(Err(Error::ConnectionError), result);
    }

    /// Tests that a connection will fail an RPC after a failure to connect.
    #[test]
    fn connection_hangup() {
        let _ = env_logger::init();
        let mut cluster = MiniCluster::new(MiniClusterConfig::default()
                                                             .num_tservers(0)
                                                             .log_rpc_negotiation_trace(true)
                                                             .log_rpc_trace(true));
        let messenger = Messenger::new().unwrap();
        let mut rpc = master::ping(cluster.master_addrs()[0],
                                   Instant::now() + Duration::from_secs(5),
                                   kudu_pb::master::PingRequestPB::new());

        let (send, recv) = sync_channel::<(Result<()>, Rpc)>(0);
        rpc.callback = Some(retry_channel_callback(messenger.clone(), send));
        messenger.send(rpc);

        let (result, _) = recv.recv().unwrap();

        assert_eq!(Ok(()), result);

        let master = cluster.master_addrs()[0];
        cluster.stop_node(master);

        let rpc = master::ping(cluster.master_addrs()[0],
                               Instant::now() + Duration::from_secs(5),
                               kudu_pb::master::PingRequestPB::new());

        let (result, _) = messenger.send_sync(rpc);
        assert_eq!(Err(Error::ConnectionError), result);
    }
}
<|endoftext|>