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

//! Various re-occuring types that are used by the ElasticSearch API.
//!
//! E.g. `Duration`
//!
//! This isn't all types. Types that are specific to one API are defined in the
//! appropriate place, e.g. types only used by the Query DSL are in `query.rs`

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

use ::operations::common::OptionVal;

/// The units by which duration is measured.
///
/// TODO - this list is incomplete, see: https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units
#[derive(Debug)]
pub enum DurationUnit {
    Month,
    Week,
    Day,
    Hour,
    Minute,
    Second,
    Millisecond
}

impl ToString for DurationUnit {
    fn to_string(&self) -> String {
        match *self {
            DurationUnit::Month  => "M",
            DurationUnit::Week   => "w",
            DurationUnit::Day    => "d",
            DurationUnit::Hour   => "h",
            DurationUnit::Minute => "m",
            DurationUnit::Second => "s",
            DurationUnit::Millisecond => "ms"
        }.to_owned()
    }
}

/// A time-period unit, will be formatted into the ElasticSearch standard format
///
/// # Examples
///
/// ```
/// use rs_es::units::{Duration, DurationUnit};
///
/// assert_eq!("100d", Duration::new(100, DurationUnit::Day).to_string());
/// ```
#[derive(Debug)]
pub struct Duration {
    amt: i64,
    unit: DurationUnit
}

impl Duration {
    pub fn new(amt: i64, unit: DurationUnit) -> Duration {
        Duration {
            amt: amt,
            unit: unit
        }
    }

    pub fn months(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Month)
    }

    pub fn weeks(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Week)
    }

    pub fn days(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Day)
    }

    pub fn hours(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Hour)
    }

    pub fn minutes(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Minute)
    }

    pub fn seconds(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Second)
    }

    pub fn milliseconds(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Millisecond)
    }
}

impl ToString for Duration {
    fn to_string(&self) -> String {
        format!("{}{}", self.amt, self.unit.to_string())
    }
}

impl ToJson for Duration {
    fn to_json(&self) -> Json {
        Json::String(self.to_string())
    }
}

impl<'a> From<&'a Duration> for OptionVal {
    fn from(from: &'a Duration) -> OptionVal {
        OptionVal(from.to_string())
    }
}

from_exp!(Duration, OptionVal, from, OptionVal(from.to_string()));

/// Representing a geographic location
#[derive(Debug)]
pub enum Location {
    LatLon(f64, f64),
    GeoHash(String)
}

impl<'a> From<&'a Json> for Location {
    fn from(from: &'a Json) -> Location {
        Location::LatLon(
            get_json_f64!(from, "lat"),
            get_json_f64!(from, "lon"))
    }
}

from_exp!((f64, f64), Location, from, Location::LatLon(from.0, from.1));
from!(String, Location, GeoHash);

impl ToJson for Location {
    fn to_json(&self) -> Json {
        match self {
            &Location::LatLon(lat, lon) => {
                let mut d = BTreeMap::new();
                d.insert("lat".to_owned(), Json::F64(lat));
                d.insert("lon".to_owned(), Json::F64(lon));
                Json::Object(d)
            },
            &Location::GeoHash(ref geo_hash) => {
                Json::String(geo_hash.clone())
            }
        }
    }
}

/// Representing a geographic box
#[derive(Debug)]
pub enum GeoBox {
    Corners(Location, Location),
    Vertices(f64, f64, f64, f64)
}

impl<'a> From<&'a Json> for GeoBox {
    fn from(from: &'a Json) -> GeoBox {
        GeoBox::Corners(
            Location::from(from.find("top_left").expect("No 'top_left' field")),
            Location::from(from.find("bottom_right").expect("No 'bottom_right' field")))
    }
}

from_exp!((Location, Location), GeoBox, from, GeoBox::Corners(from.0, from.1));
from_exp!(((f64, f64), (f64, f64)),
          GeoBox,
          from,
          GeoBox::Corners(Location::LatLon({from.0}.0, {from.0}.1),
                          Location::LatLon({from.1}.0, {from.1}.1)));
from_exp!((f64, f64, f64, f64),
          GeoBox,
          from,
          GeoBox::Vertices(from.0, from.1, from.2, from.3));

impl ToJson for GeoBox {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &GeoBox::Corners(ref top_left, ref bottom_right) => {
                d.insert("top_left".to_owned(), top_left.to_json());
                d.insert("bottom_right".to_owned(), bottom_right.to_json());
            },
            &GeoBox::Vertices(ref top, ref left, ref bottom, ref right) => {
                d.insert("top".to_owned(), top.to_json());
                d.insert("left".to_owned(), left.to_json());
                d.insert("bottom".to_owned(), bottom.to_json());
                d.insert("right".to_owned(), right.to_json());
            }
        }
        Json::Object(d)
    }
}

/// A non-specific holder for an option which can either be a single thing, or
/// multiple instances of that thing.
#[derive(Debug)]
pub enum OneOrMany<T: ToJson> {
    One(T),
    Many(Vec<T>)
}

impl<T: Default + ToJson> Default for OneOrMany<T> {
    fn default() -> Self {
        OneOrMany::One(Default::default())
    }
}

impl<T: ToJson> From<T> for OneOrMany<T> {
    fn from(from: T) -> OneOrMany<T> {
        OneOrMany::One(from)
    }
}

impl<T: ToJson> From<Vec<T>> for OneOrMany<T> {
    fn from(from: Vec<T>) -> OneOrMany<T> {
        OneOrMany::Many(from)
    }
}

impl<T: ToJson> ToJson for OneOrMany<T> {
    fn to_json(&self) -> Json {
        match self {
            &OneOrMany::One(ref t)  => t.to_json(),
            &OneOrMany::Many(ref t) => t.to_json()
        }
    }
}

/// DistanceType
#[derive(Debug)]
pub enum DistanceType {
    SloppyArc,
    Arc,
    Plane
}

impl ToJson for DistanceType {
    fn to_json(&self) -> Json {
        Json::String(match self {
            &DistanceType::SloppyArc => "sloppy_arc",
            &DistanceType::Arc       => "arc",
            &DistanceType::Plane     => "plane"
        }.to_owned())
    }
}

/// DistanceUnit
#[derive(Debug)]
pub enum DistanceUnit {
    Mile,
    Yard,
    Feet,
    Inch,
    Kilometer,
    Meter,
    Centimeter,
    Millimeter,
    NauticalMile
}

impl ToString for DistanceUnit {
    fn to_string(&self) -> String {
        match *self {
            DistanceUnit::Mile => "mi",
            DistanceUnit::Yard => "yd",
            DistanceUnit::Feet => "ft",
            DistanceUnit::Inch => "in",
            DistanceUnit::Kilometer => "km",
            DistanceUnit::Meter => "m",
            DistanceUnit::Centimeter => "cm",
            DistanceUnit::Millimeter => "mm",
            DistanceUnit::NauticalMile => "NM"
        }.to_owned()
    }
}

impl ToJson for DistanceUnit {
    fn to_json(&self) -> Json {
        Json::String(self.to_string())
    }
}

/// Distance, both an amount and a unit
#[derive(Debug)]
pub struct Distance {
     amt: f64,
     unit: DistanceUnit
}

impl Distance {
    pub fn new(amt: f64, unit: DistanceUnit) -> Distance {
        Distance {
            amt:  amt,
            unit: unit
        }
    }
}

impl ToJson for Distance {
    fn to_json(&self) -> Json {
        Json::String(format!("{}{}", self.amt, self.unit.to_string()))
    }
}

/// A trait for types that can become JsonVals
pub trait JsonPotential {
    fn to_json_val(&self) -> JsonVal;
}

macro_rules! json_potential {
    ($t:ty) => (
        impl JsonPotential for $t {
            fn to_json_val(&self) -> JsonVal {
                (*self).into()
            }
        }
    )
}

impl<'a> JsonPotential for &'a str {
    fn to_json_val(&self) -> JsonVal {
        (*self).into()
    }
}

json_potential!(i64);
json_potential!(i32);
json_potential!(u64);
json_potential!(u32);
json_potential!(f64);
json_potential!(f32);
json_potential!(bool);

/// A Json value that's not a structural thing - i.e. just String, i64 and f64,
/// no array or object
#[derive(Debug)]
pub enum JsonVal {
    String(String),
    I64(i64),
    U64(u64),
    F64(f64),
    Boolean(bool)
}

impl Default for JsonVal {
    fn default() -> Self {
        JsonVal::String(Default::default())
    }
}

impl ToJson for JsonVal {
    fn to_json(&self) -> Json {
        match self {
            &JsonVal::String(ref str) => str.to_json(),
            &JsonVal::I64(i)          => Json::I64(i),
            &JsonVal::U64(u)          => Json::U64(u),
            &JsonVal::F64(f)          => Json::F64(f),
            &JsonVal::Boolean(b)      => Json::Boolean(b)
        }
    }
}

from!(String, JsonVal, String);

impl<'a> From<&'a str> for JsonVal {
    fn from(from: &'a str) -> JsonVal {
        JsonVal::String(from.to_owned())
    }
}

from_exp!(f32, JsonVal, from, JsonVal::F64(from as f64));
from!(f64, JsonVal, F64);
from_exp!(i32, JsonVal, from, JsonVal::I64(from as i64));
from!(i64, JsonVal, I64);
from_exp!(u32, JsonVal, from, JsonVal::U64(from as u64));
from!(u64, JsonVal, U64);
from!(bool, JsonVal, Boolean);

impl<'a> From<&'a Json> for JsonVal {
    fn from(from: &'a Json) -> JsonVal {
        match from {
            &Json::String(ref s) => JsonVal::String(s.clone()),
            &Json::F64(f)        => JsonVal::F64(f),
            &Json::I64(f)        => JsonVal::I64(f),
            &Json::U64(f)        => JsonVal::U64(f),
            &Json::Boolean(b)    => JsonVal::Boolean(b),
            _                    => panic!("Not a String, F64, I64, U64 or Boolean")
        }
    }
}
<commit_msg>Unnecessary trait bounds<commit_after>/*
 * Copyright 2015-2016 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Various re-occuring types that are used by the ElasticSearch API.
//!
//! E.g. `Duration`
//!
//! This isn't all types. Types that are specific to one API are defined in the
//! appropriate place, e.g. types only used by the Query DSL are in `query.rs`

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

use ::operations::common::OptionVal;

/// The units by which duration is measured.
///
/// TODO - this list is incomplete, see: https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units
#[derive(Debug)]
pub enum DurationUnit {
    Month,
    Week,
    Day,
    Hour,
    Minute,
    Second,
    Millisecond
}

impl ToString for DurationUnit {
    fn to_string(&self) -> String {
        match *self {
            DurationUnit::Month  => "M",
            DurationUnit::Week   => "w",
            DurationUnit::Day    => "d",
            DurationUnit::Hour   => "h",
            DurationUnit::Minute => "m",
            DurationUnit::Second => "s",
            DurationUnit::Millisecond => "ms"
        }.to_owned()
    }
}

/// A time-period unit, will be formatted into the ElasticSearch standard format
///
/// # Examples
///
/// ```
/// use rs_es::units::{Duration, DurationUnit};
///
/// assert_eq!("100d", Duration::new(100, DurationUnit::Day).to_string());
/// ```
#[derive(Debug)]
pub struct Duration {
    amt: i64,
    unit: DurationUnit
}

impl Duration {
    pub fn new(amt: i64, unit: DurationUnit) -> Duration {
        Duration {
            amt: amt,
            unit: unit
        }
    }

    pub fn months(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Month)
    }

    pub fn weeks(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Week)
    }

    pub fn days(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Day)
    }

    pub fn hours(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Hour)
    }

    pub fn minutes(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Minute)
    }

    pub fn seconds(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Second)
    }

    pub fn milliseconds(amt: i64) -> Duration {
        Duration::new(amt, DurationUnit::Millisecond)
    }
}

impl ToString for Duration {
    fn to_string(&self) -> String {
        format!("{}{}", self.amt, self.unit.to_string())
    }
}

impl ToJson for Duration {
    fn to_json(&self) -> Json {
        Json::String(self.to_string())
    }
}

impl<'a> From<&'a Duration> for OptionVal {
    fn from(from: &'a Duration) -> OptionVal {
        OptionVal(from.to_string())
    }
}

from_exp!(Duration, OptionVal, from, OptionVal(from.to_string()));

/// Representing a geographic location
#[derive(Debug)]
pub enum Location {
    LatLon(f64, f64),
    GeoHash(String)
}

impl<'a> From<&'a Json> for Location {
    fn from(from: &'a Json) -> Location {
        Location::LatLon(
            get_json_f64!(from, "lat"),
            get_json_f64!(from, "lon"))
    }
}

from_exp!((f64, f64), Location, from, Location::LatLon(from.0, from.1));
from!(String, Location, GeoHash);

impl ToJson for Location {
    fn to_json(&self) -> Json {
        match self {
            &Location::LatLon(lat, lon) => {
                let mut d = BTreeMap::new();
                d.insert("lat".to_owned(), Json::F64(lat));
                d.insert("lon".to_owned(), Json::F64(lon));
                Json::Object(d)
            },
            &Location::GeoHash(ref geo_hash) => {
                Json::String(geo_hash.clone())
            }
        }
    }
}

/// Representing a geographic box
#[derive(Debug)]
pub enum GeoBox {
    Corners(Location, Location),
    Vertices(f64, f64, f64, f64)
}

impl<'a> From<&'a Json> for GeoBox {
    fn from(from: &'a Json) -> GeoBox {
        GeoBox::Corners(
            Location::from(from.find("top_left").expect("No 'top_left' field")),
            Location::from(from.find("bottom_right").expect("No 'bottom_right' field")))
    }
}

from_exp!((Location, Location), GeoBox, from, GeoBox::Corners(from.0, from.1));
from_exp!(((f64, f64), (f64, f64)),
          GeoBox,
          from,
          GeoBox::Corners(Location::LatLon({from.0}.0, {from.0}.1),
                          Location::LatLon({from.1}.0, {from.1}.1)));
from_exp!((f64, f64, f64, f64),
          GeoBox,
          from,
          GeoBox::Vertices(from.0, from.1, from.2, from.3));

impl ToJson for GeoBox {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &GeoBox::Corners(ref top_left, ref bottom_right) => {
                d.insert("top_left".to_owned(), top_left.to_json());
                d.insert("bottom_right".to_owned(), bottom_right.to_json());
            },
            &GeoBox::Vertices(ref top, ref left, ref bottom, ref right) => {
                d.insert("top".to_owned(), top.to_json());
                d.insert("left".to_owned(), left.to_json());
                d.insert("bottom".to_owned(), bottom.to_json());
                d.insert("right".to_owned(), right.to_json());
            }
        }
        Json::Object(d)
    }
}

/// A non-specific holder for an option which can either be a single thing, or
/// multiple instances of that thing.
#[derive(Debug)]
pub enum OneOrMany<T> {
    One(T),
    Many(Vec<T>)
}

impl<T: Default> Default for OneOrMany<T> {
    fn default() -> Self {
        OneOrMany::One(Default::default())
    }
}

impl<T: ToJson> From<T> for OneOrMany<T> {
    fn from(from: T) -> OneOrMany<T> {
        OneOrMany::One(from)
    }
}

impl<T: ToJson> From<Vec<T>> for OneOrMany<T> {
    fn from(from: Vec<T>) -> OneOrMany<T> {
        OneOrMany::Many(from)
    }
}

impl<T: ToJson> ToJson for OneOrMany<T> {
    fn to_json(&self) -> Json {
        match self {
            &OneOrMany::One(ref t)  => t.to_json(),
            &OneOrMany::Many(ref t) => t.to_json()
        }
    }
}

/// DistanceType
#[derive(Debug)]
pub enum DistanceType {
    SloppyArc,
    Arc,
    Plane
}

impl ToJson for DistanceType {
    fn to_json(&self) -> Json {
        Json::String(match self {
            &DistanceType::SloppyArc => "sloppy_arc",
            &DistanceType::Arc       => "arc",
            &DistanceType::Plane     => "plane"
        }.to_owned())
    }
}

/// DistanceUnit
#[derive(Debug)]
pub enum DistanceUnit {
    Mile,
    Yard,
    Feet,
    Inch,
    Kilometer,
    Meter,
    Centimeter,
    Millimeter,
    NauticalMile
}

impl ToString for DistanceUnit {
    fn to_string(&self) -> String {
        match *self {
            DistanceUnit::Mile => "mi",
            DistanceUnit::Yard => "yd",
            DistanceUnit::Feet => "ft",
            DistanceUnit::Inch => "in",
            DistanceUnit::Kilometer => "km",
            DistanceUnit::Meter => "m",
            DistanceUnit::Centimeter => "cm",
            DistanceUnit::Millimeter => "mm",
            DistanceUnit::NauticalMile => "NM"
        }.to_owned()
    }
}

impl ToJson for DistanceUnit {
    fn to_json(&self) -> Json {
        Json::String(self.to_string())
    }
}

/// Distance, both an amount and a unit
#[derive(Debug)]
pub struct Distance {
     amt: f64,
     unit: DistanceUnit
}

impl Distance {
    pub fn new(amt: f64, unit: DistanceUnit) -> Distance {
        Distance {
            amt:  amt,
            unit: unit
        }
    }
}

impl ToJson for Distance {
    fn to_json(&self) -> Json {
        Json::String(format!("{}{}", self.amt, self.unit.to_string()))
    }
}

/// A trait for types that can become JsonVals
pub trait JsonPotential {
    fn to_json_val(&self) -> JsonVal;
}

macro_rules! json_potential {
    ($t:ty) => (
        impl JsonPotential for $t {
            fn to_json_val(&self) -> JsonVal {
                (*self).into()
            }
        }
    )
}

impl<'a> JsonPotential for &'a str {
    fn to_json_val(&self) -> JsonVal {
        (*self).into()
    }
}

json_potential!(i64);
json_potential!(i32);
json_potential!(u64);
json_potential!(u32);
json_potential!(f64);
json_potential!(f32);
json_potential!(bool);

/// A Json value that's not a structural thing - i.e. just String, i64 and f64,
/// no array or object
#[derive(Debug)]
pub enum JsonVal {
    String(String),
    I64(i64),
    U64(u64),
    F64(f64),
    Boolean(bool)
}

impl Default for JsonVal {
    fn default() -> Self {
        JsonVal::String(Default::default())
    }
}

impl ToJson for JsonVal {
    fn to_json(&self) -> Json {
        match self {
            &JsonVal::String(ref str) => str.to_json(),
            &JsonVal::I64(i)          => Json::I64(i),
            &JsonVal::U64(u)          => Json::U64(u),
            &JsonVal::F64(f)          => Json::F64(f),
            &JsonVal::Boolean(b)      => Json::Boolean(b)
        }
    }
}

from!(String, JsonVal, String);

impl<'a> From<&'a str> for JsonVal {
    fn from(from: &'a str) -> JsonVal {
        JsonVal::String(from.to_owned())
    }
}

from_exp!(f32, JsonVal, from, JsonVal::F64(from as f64));
from!(f64, JsonVal, F64);
from_exp!(i32, JsonVal, from, JsonVal::I64(from as i64));
from!(i64, JsonVal, I64);
from_exp!(u32, JsonVal, from, JsonVal::U64(from as u64));
from!(u64, JsonVal, U64);
from!(bool, JsonVal, Boolean);

impl<'a> From<&'a Json> for JsonVal {
    fn from(from: &'a Json) -> JsonVal {
        match from {
            &Json::String(ref s) => JsonVal::String(s.clone()),
            &Json::F64(f)        => JsonVal::F64(f),
            &Json::I64(f)        => JsonVal::I64(f),
            &Json::U64(f)        => JsonVal::U64(f),
            &Json::Boolean(b)    => JsonVal::Boolean(b),
            _                    => panic!("Not a String, F64, I64, U64 or Boolean")
        }
    }
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::fmt;
use rand::random;

type Point = (isize, isize);

#[derive(Debug, Clone)]
pub struct World {
    width: isize,
    height: isize,
    generation: HashSet<Point>,
    neighbours: HashMap<Point, usize>,
    age: usize,
}

impl World {
    pub fn new(width: isize, height: isize)  -> World {
        World { width: width, height: height, age: 0,
                generation: HashSet::new(), neighbours: HashMap::new(), }
    }

    pub fn seed(mut self) -> World {
        self.generation = (0..self.width).cartesian_product(0..self.height)
                                         .filter(|_| random())
                                         .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self
    }

    pub fn evolve(&mut self) -> &World {
        self.generation = self.neighbours.iter()
                              .filter(|&(n, c)| self.decide_fate(n, *c))
                              .map(|(n, _)| *n)
                              .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self.age += 1;
        self
    }

    fn calculate_neighbours(&mut self) {
        self.neighbours.clear();
        for &(x, y) in self.generation.iter() {
            (-1..2)
            .cartesian_product(-1..2)
            .filter(|&(dx, dy)| dx != 0 || dy != 0)
            .map(|(dx, dy)| (dx + x, dy + y))
            .fold(&mut self.neighbours, |acc, point| {
                *acc.entry(point).or_insert(0) += 1;
                acc
            });
        };
    }

    fn decide_fate(&self, p: &Point, c: usize) -> bool {
        if self.generation.contains(p) {
            c == 3 || c == 2
        } else {
            c == 3
        }
    }
}

impl fmt::Display for World {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = String::with_capacity(((self.width + 2) * (self.height + 2) + 50) as usize);
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '┌' } else if x == self.width + 1 { '┐' } else { '─' });
        }
        buf.push('\n');
        for y in 0..self.height {
            buf.push('│');
            for x in 0..self.width {
                buf.push(if self.generation.contains(&(x, y)) { '*' } else { ' ' });
            }
            buf.push('|');
            if y == 0 {
                buf.push_str(&format!(" cells: {}", self.generation.len()));
            }
            if y == 1 {
                buf.push_str(&format!(" age: {}", self.age));
            }
            buf.push('\n');
        }
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '└' } else if x == self.width + 1 { '┘' } else { '─' });
        }
        write!(f, "{}", buf)
    }
}
<commit_msg>Fold all the things<commit_after>use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::fmt;
use rand::random;

type Point = (isize, isize);

#[derive(Debug, Clone)]
pub struct World {
    width: isize,
    height: isize,
    generation: HashSet<Point>,
    neighbours: HashMap<Point, usize>,
    age: usize,
}

impl World {
    pub fn new(width: isize, height: isize)  -> World {
        World { width: width, height: height, age: 0,
                generation: HashSet::new(), neighbours: HashMap::new(), }
    }

    pub fn seed(mut self) -> World {
        (0..self.width).cartesian_product(0..self.height)
                       .filter(|_| random())
                       .fold(&mut self.generation, |acc, point| {
                            acc.insert(point);
                            acc
                       });
        self.calculate_neighbours();
        self
    }

    pub fn evolve(&mut self) -> &World {
        self.generation = self.neighbours.iter()
                              .filter(|&(n, c)| self.decide_fate(n, *c))
                              .map(|(n, _)| *n)
                              .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self.age += 1;
        self
    }

    fn calculate_neighbours(&mut self) {
        self.neighbours.clear();
        for &(x, y) in self.generation.iter() {
            (-1..2)
            .cartesian_product(-1..2)
            .filter(|&(dx, dy)| dx != 0 || dy != 0)
            .map(|(dx, dy)| (dx + x, dy + y))
            .fold(&mut self.neighbours, |acc, point| {
                *acc.entry(point).or_insert(0) += 1;
                acc
            });
        };
    }

    fn decide_fate(&self, p: &Point, c: usize) -> bool {
        if self.generation.contains(p) {
            c == 3 || c == 2
        } else {
            c == 3
        }
    }
}

impl fmt::Display for World {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = String::with_capacity(((self.width + 2) * (self.height + 2) + 50) as usize);
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '┌' } else if x == self.width + 1 { '┐' } else { '─' });
        }
        buf.push('\n');
        for y in 0..self.height {
            buf.push('│');
            for x in 0..self.width {
                buf.push(if self.generation.contains(&(x, y)) { '*' } else { ' ' });
            }
            buf.push('|');
            if y == 0 {
                buf.push_str(&format!(" cells: {}", self.generation.len()));
            }
            if y == 1 {
                buf.push_str(&format!(" age: {}", self.age));
            }
            buf.push('\n');
        }
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '└' } else if x == self.width + 1 { '┘' } else { '─' });
        }
        write!(f, "{}", buf)
    }
}
<|endoftext|>


<commit_before>//! Module: czmq-zcert

use {czmq_sys, Error, ErrorKind, RawInterface, Result, Sockish, zmq, ZList};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::{error, fmt, ptr, slice, str};

const KEY_SIZE: usize = 32;

pub struct ZCert {
    zcert: *mut czmq_sys::zcert_t,
    owned: bool,
}

unsafe impl Send for ZCert {}
unsafe impl Sync for ZCert {}

impl Drop for ZCert {
    fn drop(&mut self) {
        if self.owned {
            unsafe { czmq_sys::zcert_destroy(&mut self.zcert) };
        }
    }
}

impl ZCert {
    pub fn new() -> Result<ZCert> {
        let zcert = unsafe { czmq_sys::zcert_new() };

        if zcert == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZCertError::Instantiate));
        }

        Ok(ZCert {
            zcert: zcert,
            owned: true,
        })
    }

    pub fn from_keys(public_key: &[u8], secret_key: &[u8]) -> ZCert {
        ZCert {
            zcert: unsafe { czmq_sys::zcert_new_from(public_key.as_ptr(), secret_key.as_ptr()) },
            owned: true,
        }
    }

    pub fn from_txt(public_txt: &str, secret_txt: &str) -> ZCert {
        ZCert::from_keys(&zmq::z85_decode(public_txt), &zmq::z85_decode(secret_txt))
    }

    pub fn load(filename: &str) -> Result<ZCert> {
        let filename_c = try!(CString::new(filename));
        let zcert = unsafe { czmq_sys::zcert_load(filename_c.as_ptr()) };

        if zcert == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZCertError::InvalidCert(filename_c.into_string().unwrap())));
        }

        Ok(ZCert {
            zcert: zcert,
            owned: true,
        })
    }

    pub fn public_key<'a>(&'a self) -> &'a [u8] {
        unsafe {
            let ptr = czmq_sys::zcert_public_key(self.zcert);
            slice::from_raw_parts(ptr, KEY_SIZE)
        }
    }

    pub fn secret_key<'a>(&'a self) -> &'a [u8] {
        unsafe {
            let ptr = czmq_sys::zcert_secret_key(self.zcert);
            slice::from_raw_parts(ptr, KEY_SIZE)
        }
    }

    pub fn public_txt<'a>(&'a self) -> &'a str {
        unsafe {
            let ptr = czmq_sys::zcert_public_txt(self.zcert);
            CStr::from_ptr(ptr as *const c_char).to_str().unwrap_or("")
        }
    }

    pub fn secret_txt<'a>(&'a self) -> &'a str {
        unsafe {
            let ptr = czmq_sys::zcert_secret_txt(self.zcert);
            CStr::from_ptr(ptr as *const c_char).to_str().unwrap_or("")
        }
    }

    pub fn set_meta(&self, key: &str, value: &str) {
        let key_c = CString::new(key).unwrap_or(CString::new("").unwrap());
        let value_c = CString::new(value).unwrap_or(CString::new("").unwrap());

        unsafe { czmq_sys::zcert_set_meta(self.zcert, key_c.as_ptr(), "%s\0".as_ptr() as *const i8, value_c.as_ptr()) };
    }

    pub fn meta<'a>(&'a self, key: &str) -> Result<Option<&'a str>> {
        let key_c = try!(CString::new(key));

        let value = unsafe {
            let ptr = czmq_sys::zcert_meta(self.zcert, key_c.as_ptr());
            CStr::from_ptr(ptr as *const c_char)
        };

        match value.to_str() {
            Ok(s) => Ok(Some(s)),
            Err(_) => Ok(None),
        }
    }

    pub fn meta_keys(&self) -> ZList<&'static str> {
        let ptr = unsafe { czmq_sys::zcert_meta_keys(self.zcert) };
        ZList::<&'static str>::from_raw(ptr)
    }

    /// Encode certificate metadata into ZMQ wire format.
    ///
    /// ```no_run
    /// # use czmq::{ZCert, ZFrame, ZSock};
    /// # let sock = ZSock::new_rep("...").unwrap();
    /// let cert = ZCert::new().unwrap();
    /// cert.set_meta("key", "value");
    ///
    /// let encoded = cert.encode_meta();
    /// let frame = ZFrame::new(&encoded).unwrap();
    /// frame.send(&sock, None).unwrap();
    /// ```
    pub fn encode_meta(&self) -> Vec<u8> {
        let mut encoded: Vec<u8> = Vec::new();

        for metakey in self.meta_keys() {
            if let Ok(Some(metaval)) = self.meta(metakey) {
                encoded.push(metakey.len() as u8);
                encoded.extend_from_slice(metakey.as_bytes());
                encoded.push(((metaval.len() >> 24) & 0xff) as u8);
                encoded.push(((metaval.len() >> 16) & 0xff) as u8);
                encoded.push(((metaval.len() >> 8) & 0xff) as u8);
                encoded.push((metaval.len() & 0xff) as u8);
                encoded.extend_from_slice(metaval.as_bytes());
            }
        }

        encoded
    }

    /// Decode and set certificate metadata from ZMQ wire format.
    ///
    /// ```no_run
    /// # use czmq::{ZCert, ZFrame, ZSock};
    /// # let sock = ZSock::new_rep("...").unwrap();
    /// let frame = ZFrame::recv(&sock).unwrap();
    /// let encoded = match frame.data().unwrap() {
    ///     Ok(str) => str.into_bytes(),
    ///     Err(bytes) => bytes,
    /// };
    ///
    /// let cert = ZCert::new().unwrap();
    /// cert.decode_meta(&encoded);
    /// ```
    pub fn decode_meta(&self, encoded: &[u8]) -> Result<()> {
        let mut bytes_left = encoded.len();
        let mut index = 0;

        while bytes_left > 1 {
            let name_length: usize = *try!(encoded.get(index).ok_or(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded))) as usize;
            index += 1;
            bytes_left -= 1;

            if bytes_left < name_length {
                return Err(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded));
            }

            let name = try!(str::from_utf8(&encoded[index..index + name_length]));
            index += name_length;
            bytes_left -= name_length;

            if bytes_left < 4 {
                return Err(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded));
            }

            let value_length = (((encoded[index] as u32) << 24) |
                                ((encoded[index + 1] as u32) << 16) |
                                ((encoded[index + 2] as u32) << 8) |
                                  encoded[index + 3] as u32) as usize;
            index += 4;
            bytes_left -= 4;

            if bytes_left < value_length {
                return Err(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded));
            }

            let value = try!(str::from_utf8(&encoded[index..index + value_length]));
            index += value_length;
            bytes_left -= value_length;

            self.set_meta(name, value);
        }

        Ok(())
    }

    pub fn save(&self, filename: &str) -> Result<()> {
        let filename_c = try!(CString::new(filename));

        unsafe {
            let rc = czmq_sys::zcert_save(self.zcert, filename_c.as_ptr());
            if rc == -1 {
                Err(Error::new(ErrorKind::NonZero, ZCertError::SavePath(filename_c.into_string().unwrap())))
            } else {
                Ok(())
            }
        }
    }

    pub fn save_public(&self, filename: &str) -> Result<()> {
        let filename_c = try!(CString::new(filename));

        unsafe {
            let rc = czmq_sys::zcert_save_public(self.zcert, filename_c.as_ptr());
            if rc == -1 {
                Err(Error::new(ErrorKind::NonZero, ZCertError::SavePath(filename_c.into_string().unwrap())))
            } else {
                Ok(())
            }
        }
    }

    pub fn save_secret(&self, filename: &str) -> Result<()> {
        let filename_c = try!(CString::new(filename));

        unsafe {
            let rc = czmq_sys::zcert_save_secret(self.zcert, filename_c.as_ptr());
            if rc == -1 {
                Err(Error::new(ErrorKind::NonZero, ZCertError::SavePath(filename_c.into_string().unwrap())))
            } else {
                Ok(())
            }
        }
    }

    pub fn apply<S: Sockish>(&self, sock: &S) {
        unsafe { czmq_sys::zcert_apply(self.zcert, sock.borrow_raw()) };
    }

    pub fn dup(&self) -> ZCert {
        let ptr = unsafe { czmq_sys::zcert_dup(self.zcert) };

        ZCert {
            zcert: ptr,
            owned: true,
        }
    }

    pub fn eq(&self, cert: &ZCert) -> bool {
        let result = unsafe { czmq_sys::zcert_eq(self.zcert, cert.zcert) };
        result == 1
    }

    pub fn print(&self) {
        unsafe { czmq_sys::zcert_print(self.zcert) };
    }
}

impl RawInterface<czmq_sys::zcert_t> for ZCert {
    fn from_raw(ptr: *mut czmq_sys::zcert_t, owned: bool) -> ZCert {
        ZCert {
            zcert: ptr,
            owned: owned,
        }
    }

    fn into_raw(mut self) -> *mut czmq_sys::zcert_t {
        self.owned = false;
        self.zcert
    }

    fn borrow_raw(&self) -> *mut czmq_sys::zcert_t {
        self.zcert
    }
}

#[derive(Debug)]
pub enum ZCertError {
    Instantiate,
    InvalidCert(String),
    InvalidMetaEncoded,
    SavePath(String),
}

impl fmt::Display for ZCertError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ZCertError::Instantiate => write!(f, "Could not instantiate new ZCert struct"),
            ZCertError::InvalidCert(ref e) => write!(f, "Could not open certificate at path: {}", e),
            ZCertError::InvalidMetaEncoded => write!(f, "Encoded metadata is invalid"),
            ZCertError::SavePath(ref e) => write!(f, "Could not save certificate file to path: {}", e),
        }
    }
}

impl error::Error for ZCertError {
    fn description(&self) -> &str {
        match *self {
            ZCertError::Instantiate => "Could not instantiate new ZCert struct",
            ZCertError::InvalidCert(_) => "Certificate was invalid or non-existent",
            ZCertError::InvalidMetaEncoded => "Encoded metadata is invalid",
            ZCertError::SavePath(_) => "Could not save certificate file to given path",
        }
    }
}

#[cfg(test)]
mod tests {
    use {ZSock, zsys_init};
    use super::*;
    use zmq;

    const PUBLIC_TXT: &'static str = "Ko9/&3Uw)$U]Zyp>+4$-i/yaDea2QqlDPGl-&V1s";
    const SECRET_TXT: &'static str = "[MfOo!1^1N}zZY/x{[A6^9>VRC.+O6vX&]zYvDC-";

    #[test]
    fn test_public_key() {
        let cert = create_cert();
        let key = cert.public_key();
        let test_key = zmq::z85_decode(PUBLIC_TXT);

        let mut iter = 0;
        for _ in key.iter() {
            assert_eq!(key[iter], test_key[iter]);
            iter += 1;
        }
    }

    #[test]
    fn test_secret_key() {
        let cert = create_cert();
        let key = cert.secret_key();
        let test_key = zmq::z85_decode(SECRET_TXT);

        let mut iter = 0;
        for _ in key.iter() {
            assert_eq!(key[iter], test_key[iter]);
            iter += 1;
        }
    }

    #[test]
    fn test_public_txt() {
        let cert = create_cert();
        assert_eq!(cert.public_txt(), PUBLIC_TXT);
    }

    #[test]
    fn test_secret_txt() {
        let cert = create_cert();
        assert_eq!(cert.secret_txt(), SECRET_TXT);
    }

    #[test]
    fn test_getset_meta() {
        let cert = create_cert();
        cert.set_meta("moo", "cow");
        assert_eq!(cert.meta("moo").unwrap().unwrap(), "cow");
    }

    #[test]
    fn test_meta_keys() {
        let cert = create_cert();
        cert.set_meta("moo", "cow");

        let mut keys = cert.meta_keys();
        assert_eq!(keys.next().unwrap(), "moo");
    }

    #[test]
    fn test_encode_decode_meta() {
        let cert = create_cert();
        cert.set_meta("moo", "cow");
        cert.set_meta("foobar", "baz");
        cert.set_meta("ka", "BOOM!!");
        let encoded = cert.encode_meta();

        let cert = create_cert();
        cert.decode_meta(&encoded).unwrap();

        assert_eq!(cert.meta("moo").unwrap().unwrap(), "cow");
        assert_eq!(cert.meta("foobar").unwrap().unwrap(), "baz");
        assert_eq!(cert.meta("ka").unwrap().unwrap(), "BOOM!!");
    }

    #[test]
    fn test_apply_zmq() {
        let cert = create_cert();
        let mut ctx = zmq::Context::new();
        let sock = ctx.socket(zmq::REQ).unwrap();
        cert.apply(&sock);
        assert_eq!(sock.get_curve_publickey().unwrap().unwrap(), PUBLIC_TXT);
        assert_eq!(sock.get_curve_secretkey().unwrap().unwrap(), SECRET_TXT);
    }

    #[test]
    fn test_apply_zsock() {
        zsys_init();

        let cert = create_cert();
        let sock = ZSock::new_rep("inproc://zcert_test_apply_zsock").unwrap();
        cert.apply(&sock);
        assert_eq!(sock.curve_publickey().unwrap().unwrap(), PUBLIC_TXT);
        assert_eq!(sock.curve_secretkey().unwrap().unwrap(), SECRET_TXT);
    }

    #[test]
    fn test_dup() {
        let cert = create_cert();
        let dup = cert.dup();
        assert_eq!(cert.secret_txt(), dup.secret_txt());
    }

    #[test]
    fn test_eq() {
        let c1 = create_cert();
        let c2 = create_cert();
        assert!(c1.eq(&c2));
    }

    fn create_cert() -> ZCert {
        ZCert::from_txt(PUBLIC_TXT, SECRET_TXT)
    }
}
<commit_msg>Implement PartialEq for ZCert<commit_after>//! Module: czmq-zcert

use {czmq_sys, Error, ErrorKind, RawInterface, Result, Sockish, zmq, ZList};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::{error, fmt, ptr, slice, str};

const KEY_SIZE: usize = 32;

#[derive(Debug, Eq)]
pub struct ZCert {
    zcert: *mut czmq_sys::zcert_t,
    owned: bool,
}

unsafe impl Send for ZCert {}
unsafe impl Sync for ZCert {}

impl Drop for ZCert {
    fn drop(&mut self) {
        if self.owned {
            unsafe { czmq_sys::zcert_destroy(&mut self.zcert) };
        }
    }
}

impl PartialEq for ZCert {
    fn eq(&self, other: &ZCert) -> bool {
        ZCert::eq(self, other)
    }
}

impl ZCert {
    pub fn new() -> Result<ZCert> {
        let zcert = unsafe { czmq_sys::zcert_new() };

        if zcert == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZCertError::Instantiate));
        }

        Ok(ZCert {
            zcert: zcert,
            owned: true,
        })
    }

    pub fn from_keys(public_key: &[u8], secret_key: &[u8]) -> ZCert {
        ZCert {
            zcert: unsafe { czmq_sys::zcert_new_from(public_key.as_ptr(), secret_key.as_ptr()) },
            owned: true,
        }
    }

    pub fn from_txt(public_txt: &str, secret_txt: &str) -> ZCert {
        ZCert::from_keys(&zmq::z85_decode(public_txt), &zmq::z85_decode(secret_txt))
    }

    pub fn load(filename: &str) -> Result<ZCert> {
        let filename_c = try!(CString::new(filename));
        let zcert = unsafe { czmq_sys::zcert_load(filename_c.as_ptr()) };

        if zcert == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZCertError::InvalidCert(filename_c.into_string().unwrap())));
        }

        Ok(ZCert {
            zcert: zcert,
            owned: true,
        })
    }

    pub fn public_key<'a>(&'a self) -> &'a [u8] {
        unsafe {
            let ptr = czmq_sys::zcert_public_key(self.zcert);
            slice::from_raw_parts(ptr, KEY_SIZE)
        }
    }

    pub fn secret_key<'a>(&'a self) -> &'a [u8] {
        unsafe {
            let ptr = czmq_sys::zcert_secret_key(self.zcert);
            slice::from_raw_parts(ptr, KEY_SIZE)
        }
    }

    pub fn public_txt<'a>(&'a self) -> &'a str {
        unsafe {
            let ptr = czmq_sys::zcert_public_txt(self.zcert);
            CStr::from_ptr(ptr as *const c_char).to_str().unwrap_or("")
        }
    }

    pub fn secret_txt<'a>(&'a self) -> &'a str {
        unsafe {
            let ptr = czmq_sys::zcert_secret_txt(self.zcert);
            CStr::from_ptr(ptr as *const c_char).to_str().unwrap_or("")
        }
    }

    pub fn set_meta(&self, key: &str, value: &str) {
        let key_c = CString::new(key).unwrap_or(CString::new("").unwrap());
        let value_c = CString::new(value).unwrap_or(CString::new("").unwrap());

        unsafe { czmq_sys::zcert_set_meta(self.zcert, key_c.as_ptr(), "%s\0".as_ptr() as *const i8, value_c.as_ptr()) };
    }

    pub fn meta<'a>(&'a self, key: &str) -> Result<Option<&'a str>> {
        let key_c = try!(CString::new(key));

        let value = unsafe {
            let ptr = czmq_sys::zcert_meta(self.zcert, key_c.as_ptr());
            CStr::from_ptr(ptr as *const c_char)
        };

        match value.to_str() {
            Ok(s) => Ok(Some(s)),
            Err(_) => Ok(None),
        }
    }

    pub fn meta_keys(&self) -> ZList<&'static str> {
        let ptr = unsafe { czmq_sys::zcert_meta_keys(self.zcert) };
        ZList::<&'static str>::from_raw(ptr)
    }

    /// Encode certificate metadata into ZMQ wire format.
    ///
    /// ```no_run
    /// # use czmq::{ZCert, ZFrame, ZSock};
    /// # let sock = ZSock::new_rep("...").unwrap();
    /// let cert = ZCert::new().unwrap();
    /// cert.set_meta("key", "value");
    ///
    /// let encoded = cert.encode_meta();
    /// let frame = ZFrame::new(&encoded).unwrap();
    /// frame.send(&sock, None).unwrap();
    /// ```
    pub fn encode_meta(&self) -> Vec<u8> {
        let mut encoded: Vec<u8> = Vec::new();

        for metakey in self.meta_keys() {
            if let Ok(Some(metaval)) = self.meta(metakey) {
                encoded.push(metakey.len() as u8);
                encoded.extend_from_slice(metakey.as_bytes());
                encoded.push(((metaval.len() >> 24) & 0xff) as u8);
                encoded.push(((metaval.len() >> 16) & 0xff) as u8);
                encoded.push(((metaval.len() >> 8) & 0xff) as u8);
                encoded.push((metaval.len() & 0xff) as u8);
                encoded.extend_from_slice(metaval.as_bytes());
            }
        }

        encoded
    }

    /// Decode and set certificate metadata from ZMQ wire format.
    ///
    /// ```no_run
    /// # use czmq::{ZCert, ZFrame, ZSock};
    /// # let sock = ZSock::new_rep("...").unwrap();
    /// let frame = ZFrame::recv(&sock).unwrap();
    /// let encoded = match frame.data().unwrap() {
    ///     Ok(str) => str.into_bytes(),
    ///     Err(bytes) => bytes,
    /// };
    ///
    /// let cert = ZCert::new().unwrap();
    /// cert.decode_meta(&encoded);
    /// ```
    pub fn decode_meta(&self, encoded: &[u8]) -> Result<()> {
        let mut bytes_left = encoded.len();
        let mut index = 0;

        while bytes_left > 1 {
            let name_length: usize = *try!(encoded.get(index).ok_or(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded))) as usize;
            index += 1;
            bytes_left -= 1;

            if bytes_left < name_length {
                return Err(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded));
            }

            let name = try!(str::from_utf8(&encoded[index..index + name_length]));
            index += name_length;
            bytes_left -= name_length;

            if bytes_left < 4 {
                return Err(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded));
            }

            let value_length = (((encoded[index] as u32) << 24) |
                                ((encoded[index + 1] as u32) << 16) |
                                ((encoded[index + 2] as u32) << 8) |
                                  encoded[index + 3] as u32) as usize;
            index += 4;
            bytes_left -= 4;

            if bytes_left < value_length {
                return Err(Error::new(ErrorKind::InvalidArg, ZCertError::InvalidMetaEncoded));
            }

            let value = try!(str::from_utf8(&encoded[index..index + value_length]));
            index += value_length;
            bytes_left -= value_length;

            self.set_meta(name, value);
        }

        Ok(())
    }

    pub fn save(&self, filename: &str) -> Result<()> {
        let filename_c = try!(CString::new(filename));

        unsafe {
            let rc = czmq_sys::zcert_save(self.zcert, filename_c.as_ptr());
            if rc == -1 {
                Err(Error::new(ErrorKind::NonZero, ZCertError::SavePath(filename_c.into_string().unwrap())))
            } else {
                Ok(())
            }
        }
    }

    pub fn save_public(&self, filename: &str) -> Result<()> {
        let filename_c = try!(CString::new(filename));

        unsafe {
            let rc = czmq_sys::zcert_save_public(self.zcert, filename_c.as_ptr());
            if rc == -1 {
                Err(Error::new(ErrorKind::NonZero, ZCertError::SavePath(filename_c.into_string().unwrap())))
            } else {
                Ok(())
            }
        }
    }

    pub fn save_secret(&self, filename: &str) -> Result<()> {
        let filename_c = try!(CString::new(filename));

        unsafe {
            let rc = czmq_sys::zcert_save_secret(self.zcert, filename_c.as_ptr());
            if rc == -1 {
                Err(Error::new(ErrorKind::NonZero, ZCertError::SavePath(filename_c.into_string().unwrap())))
            } else {
                Ok(())
            }
        }
    }

    pub fn apply<S: Sockish>(&self, sock: &S) {
        unsafe { czmq_sys::zcert_apply(self.zcert, sock.borrow_raw()) };
    }

    pub fn dup(&self) -> ZCert {
        let ptr = unsafe { czmq_sys::zcert_dup(self.zcert) };

        ZCert {
            zcert: ptr,
            owned: true,
        }
    }

    pub fn eq(&self, cert: &ZCert) -> bool {
        let result = unsafe { czmq_sys::zcert_eq(self.zcert, cert.zcert) };
        result == 1
    }

    pub fn print(&self) {
        unsafe { czmq_sys::zcert_print(self.zcert) };
    }
}

impl RawInterface<czmq_sys::zcert_t> for ZCert {
    fn from_raw(ptr: *mut czmq_sys::zcert_t, owned: bool) -> ZCert {
        ZCert {
            zcert: ptr,
            owned: owned,
        }
    }

    fn into_raw(mut self) -> *mut czmq_sys::zcert_t {
        self.owned = false;
        self.zcert
    }

    fn borrow_raw(&self) -> *mut czmq_sys::zcert_t {
        self.zcert
    }
}

#[derive(Debug)]
pub enum ZCertError {
    Instantiate,
    InvalidCert(String),
    InvalidMetaEncoded,
    SavePath(String),
}

impl fmt::Display for ZCertError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ZCertError::Instantiate => write!(f, "Could not instantiate new ZCert struct"),
            ZCertError::InvalidCert(ref e) => write!(f, "Could not open certificate at path: {}", e),
            ZCertError::InvalidMetaEncoded => write!(f, "Encoded metadata is invalid"),
            ZCertError::SavePath(ref e) => write!(f, "Could not save certificate file to path: {}", e),
        }
    }
}

impl error::Error for ZCertError {
    fn description(&self) -> &str {
        match *self {
            ZCertError::Instantiate => "Could not instantiate new ZCert struct",
            ZCertError::InvalidCert(_) => "Certificate was invalid or non-existent",
            ZCertError::InvalidMetaEncoded => "Encoded metadata is invalid",
            ZCertError::SavePath(_) => "Could not save certificate file to given path",
        }
    }
}

#[cfg(test)]
mod tests {
    use {ZSock, zsys_init};
    use super::*;
    use zmq;

    const PUBLIC_TXT: &'static str = "Ko9/&3Uw)$U]Zyp>+4$-i/yaDea2QqlDPGl-&V1s";
    const SECRET_TXT: &'static str = "[MfOo!1^1N}zZY/x{[A6^9>VRC.+O6vX&]zYvDC-";

    #[test]
    fn test_public_key() {
        let cert = create_cert();
        let key = cert.public_key();
        let test_key = zmq::z85_decode(PUBLIC_TXT);

        let mut iter = 0;
        for _ in key.iter() {
            assert_eq!(key[iter], test_key[iter]);
            iter += 1;
        }
    }

    #[test]
    fn test_secret_key() {
        let cert = create_cert();
        let key = cert.secret_key();
        let test_key = zmq::z85_decode(SECRET_TXT);

        let mut iter = 0;
        for _ in key.iter() {
            assert_eq!(key[iter], test_key[iter]);
            iter += 1;
        }
    }

    #[test]
    fn test_public_txt() {
        let cert = create_cert();
        assert_eq!(cert.public_txt(), PUBLIC_TXT);
    }

    #[test]
    fn test_secret_txt() {
        let cert = create_cert();
        assert_eq!(cert.secret_txt(), SECRET_TXT);
    }

    #[test]
    fn test_getset_meta() {
        let cert = create_cert();
        cert.set_meta("moo", "cow");
        assert_eq!(cert.meta("moo").unwrap().unwrap(), "cow");
    }

    #[test]
    fn test_meta_keys() {
        let cert = create_cert();
        cert.set_meta("moo", "cow");

        let mut keys = cert.meta_keys();
        assert_eq!(keys.next().unwrap(), "moo");
    }

    #[test]
    fn test_encode_decode_meta() {
        let cert = create_cert();
        cert.set_meta("moo", "cow");
        cert.set_meta("foobar", "baz");
        cert.set_meta("ka", "BOOM!!");
        let encoded = cert.encode_meta();

        let cert = create_cert();
        cert.decode_meta(&encoded).unwrap();

        assert_eq!(cert.meta("moo").unwrap().unwrap(), "cow");
        assert_eq!(cert.meta("foobar").unwrap().unwrap(), "baz");
        assert_eq!(cert.meta("ka").unwrap().unwrap(), "BOOM!!");
    }

    #[test]
    fn test_apply_zmq() {
        let cert = create_cert();
        let mut ctx = zmq::Context::new();
        let sock = ctx.socket(zmq::REQ).unwrap();
        cert.apply(&sock);
        assert_eq!(sock.get_curve_publickey().unwrap().unwrap(), PUBLIC_TXT);
        assert_eq!(sock.get_curve_secretkey().unwrap().unwrap(), SECRET_TXT);
    }

    #[test]
    fn test_apply_zsock() {
        zsys_init();

        let cert = create_cert();
        let sock = ZSock::new_rep("inproc://zcert_test_apply_zsock").unwrap();
        cert.apply(&sock);
        assert_eq!(sock.curve_publickey().unwrap().unwrap(), PUBLIC_TXT);
        assert_eq!(sock.curve_secretkey().unwrap().unwrap(), SECRET_TXT);
    }

    #[test]
    fn test_dup() {
        let cert = create_cert();
        let dup = cert.dup();
        assert_eq!(cert.secret_txt(), dup.secret_txt());
    }

    #[test]
    fn test_eq() {
        let c1 = create_cert();
        let c2 = create_cert();
        assert_eq!(c1, c2);
    }

    fn create_cert() -> ZCert {
        ZCert::from_txt(PUBLIC_TXT, SECRET_TXT)
    }
}
<|endoftext|>


<commit_before>//! This example demonstrates using Raft to implement a replicated hashmap over `n` servers and
//! interact with them over `m` clients.
//!
//! This example uses Serde serialization.
//!
//! Comments below will aim to be tailored towards Raft and it's usage. If you have any questions,
//! Please, just open an issue.
//!
//! TODO: For the sake of simplicity of this example, we don't implement a `Log` and just use a
//! simple testing one. We should improve this in the future.

// In order to use Serde we need to enable these nightly features.
#![feature(plugin)]
#![feature(custom_derive)]
#![plugin(serde_macros)]

extern crate raft; // <--- Kind of a big deal for this!
extern crate env_logger;
extern crate docopt;
extern crate serde;
extern crate rustc_serialize;

use std::net::SocketAddr;
use std::str::FromStr;
use std::collections::HashMap;

use serde::json::{self, Value};
use docopt::Docopt;

// Raft's major components. See comments in code on usage and things.
use raft::{
    Server,
    Client,
    state_machine,
    persistent_log,
    ServerId,
};
// A payload datatype. We're just using a simple enum. You can use whatever.
use Message::*;

// Using docopt we define the overall usage of the application.
static USAGE: &'static str = "
A replicated mutable hashmap. Operations on the register have serializable
consistency, but no durability (once all register servers are terminated the
map is lost).

Each register server holds a replica of the map, and coordinates with its
peers to update the maps values according to client commands. The register
is available for reading and writing only if a majority of register servers are
available.

Commands:

  get     Returns the current value of the key.

  put     Sets the current value of the key, and returns the previous
          value.

  cas     (compare and set) Conditionally sets the value of the key if the
          current value matches an expected value, returning true if the
          key was set.

  server  Starts a key server. Servers must be provided a unique ID and
          address (ip:port) at startup, along with the ID and address of all
          peer servers.register

Usage:
  hashmap get <key> (<node-address>)...
  hashmap put <key> <new-value> (<node-address>)...
  hashmap cas <key> <expected-value> <new-value> (<node-address>)...
  hashmap server <id> [<node-id> <node-address>]...
  hashmap (-h | --help)

Options:
  -h --help   Show a help message.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_server: bool,
    cmd_get: bool,
    cmd_put: bool,
    cmd_cas: bool,

    // When creating a server you will necessarily need some sort of unique ID for it as well
    // as a list of peers. In this example we just accept them straight from args. You might
    // find it best to use a `toml` or `yaml` or `json` file.
    arg_id: Option<u64>,
    arg_node_id: Vec<u64>,
    arg_node_address: Vec<String>,

    // In this example keys and values are associated. In your application you can model your data
    // however you please.
    arg_key: String,
    arg_new_value: String,
    arg_expected_value: String,
}

/// This is the defined message type for this example. For the sake of simplicity we don't go very
/// far with this. In a "real" application you may want to more distinctly distinguish between
/// data meant for `.query()` and data meant for `.propose()`.
#[derive(Serialize, Deserialize)]
pub enum Message {
    Get(String),
    Put(String, Value),
    Cas(String, Value, Value),
}

/// Just a plain old boring "parse args and dispatch" call.
fn main() {
    let _ = env_logger::init();
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    if args.cmd_server {
        server(&args);
    } else if args.cmd_get {
        get(&args);
    } else if args.cmd_put {
        put(&args);
    } else if args.cmd_cas {
        cas(&args);
    }
}

/// A simple convenience method since this is an example and it should exit if given invalid params.
fn parse_addr(addr: &str) -> SocketAddr {
    SocketAddr::from_str(addr)
               .ok()
               .expect(&format!("unable to parse socket address: {}", addr))
}

/// Creates a Raft server using the specified ID from the list of nodes.
fn server(args: &Args) {
    // Creating a raft server requires several things:

    // A persistent log implementation, which manages the persistent, replicated log...
    let persistent_log = persistent_log::MemLog::new();

    // A state machine which replicates state. This state should be the same on all nodes.
    let state_machine = HashmapStateMachine::new();

    // As well as a unique server id.
    let id = ServerId::from(args.arg_id.unwrap());

    // ...  And a list of peers.
    let mut peers = args.arg_node_id
                    .iter()
                    .zip(args.arg_node_address.iter())
                    .map(|(&id, addr)| (ServerId::from(id), parse_addr(&addr)))
                    .collect::<HashMap<_,_>>();

    // The Raft Server will return an error if it's ID is inside of it's peer set. Don't do that.
    // Instead, take it out and use it!
    let addr = peers.remove(&id).unwrap();

    // Using all of the above components.
    // You probably shouldn't `.unwrap()` in production code unless you're totally sure it works
    // 100% of the time, all the time.
    Server::run(id, addr, peers, persistent_log, state_machine).unwrap();
}

/// Gets a value for a given key from the provided Raft cluster.
fn get(args: &Args) {
    // Clients necessarily need to now the valid set of nodes which they can talk to.
    // This is both so they can try to talk to all the nodes if some are failing, and so that it
    // can verify that it's not being lead astray somehow in redirections on leadership changes.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    // Clients and be stored and reused, or used once and discarded.
    // There is very small overhead in connecting a new client to a cluster as it must discover and
    // identify itself to the leader.
    let mut client = Client::new(cluster);

    // In this example `serde::json` is used to serialize and deserialize messages.
    // Since Raft accepts `[u8]` the way you structure your data, the serialization method you
    // choose, and how you interpret that data is entirely up to you.
    let payload = json::to_string(&Message::Get(args.arg_key.clone())).unwrap();

    // A query executes **immutably** on the leader of the cluster and does not pass through the
    // persistent log. This is intended for querying the current state of the state machine.
    let response = client.query(payload.as_bytes()).unwrap();

    // A response will block until it's query is complete. This is intended and expected behavior
    // based on the papers specifications.
    println!("{}", String::from_utf8(response).unwrap())
}

/// Sets a value for a given key in the provided Raft cluster.
fn put(args: &Args) {
    // Same as above.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    let mut client = Client::new(cluster);

    let new_value = json::to_value(&args.arg_new_value);
    let payload = json::to_string(&Message::Put(args.arg_key.clone(), new_value)).unwrap();

    // A propose will go through the persistent log and mutably modify the state machine in some
    // way. This is **much** slower than `.query()`.
    let response = client.propose(payload.as_bytes()).unwrap();

    // A response will block until it's proposal is complete. This is intended and expected behavior
    // based on the papers specifications.
    println!("{}", String::from_utf8(response).unwrap())
}

/// Compares and sets a value for a given key in the provided Raft cluster if the value is what is
/// expected.
fn cas(args: &Args) {
    // Same as above.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    let mut client = Client::new(cluster);

    let new_value = json::to_value(&args.arg_new_value);
    let expected_value = json::to_value(&args.arg_new_value);
    let payload = json::to_string(&Message::Cas(args.arg_key.clone(), expected_value, new_value)).unwrap();

    let response = client.propose(payload.as_bytes()).unwrap();

    println!("{}", String::from_utf8(response).unwrap())
}

/// A state machine that holds a hashmap.
#[derive(Debug)]
pub struct HashmapStateMachine {
    map: HashMap<String, Value>,
}

/// Implement anything you want... A `new()` is generally a great idea.
impl HashmapStateMachine {
    pub fn new() -> HashmapStateMachine {
        HashmapStateMachine {
            map: HashMap::new(),
        }
    }
}

/// Implementing `state_machine::StateMachine` allows your application specific state machine to be
/// used in Raft. Feel encouraged to base yours of one of ours in these examples.
impl state_machine::StateMachine for HashmapStateMachine {

    /// `apply()` is called on when a client's `.propose()` is commited and reaches the state
    /// machine. At this point it is durable and is going to be applied on at least half the nodes
    /// within the next couple round trips.
    fn apply(&mut self, new_value: &[u8]) -> Vec<u8> {
        // Deserialize
        let string = String::from_utf8_lossy(new_value);
        let message = json::from_str(&string).unwrap();

        // Handle
        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            Put(key, value) => {
                let old_value = &self.map.insert(key, value);
                json::to_string(old_value)
            },
            Cas(key, old_check, new) => {
                if *self.map.get(&key).unwrap() == old_check {
                    let _ = self.map.insert(key, new);
                    json::to_string(&true)
                } else {
                    json::to_string(&false)
                }
            },
        };

        // Respond.
        response.unwrap().into_bytes()
    }

    /// `query()` is called on when a client's `.query()` is recieved. It does not go through the
    /// persistent log, it does not mutate the state of the state machine, and it is intended to be
    /// fast.
    fn query(&self, query: &[u8]) -> Vec<u8> {
        // Deserialize
        let string = String::from_utf8_lossy(query);
        let message = json::from_str(&string).unwrap();

        // Handle
        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            _ => panic!("Can't do mutating requests in query"),
        };

        // Respond.
        response.unwrap().into_bytes()
    }

    fn snapshot(&self) -> Vec<u8> {
        json::to_string(&self.map)
            .unwrap()
            .into_bytes()
    }

    fn restore_snapshot(&mut self, snapshot_value: Vec<u8>) {
        self.map = json::from_str(&String::from_utf8_lossy(&snapshot_value)).unwrap();
        ()
    }
}
<commit_msg>Bugfix: CAS mode was using wrong argument for expected value.<commit_after>//! This example demonstrates using Raft to implement a replicated hashmap over `n` servers and
//! interact with them over `m` clients.
//!
//! This example uses Serde serialization.
//!
//! Comments below will aim to be tailored towards Raft and it's usage. If you have any questions,
//! Please, just open an issue.
//!
//! TODO: For the sake of simplicity of this example, we don't implement a `Log` and just use a
//! simple testing one. We should improve this in the future.

// In order to use Serde we need to enable these nightly features.
#![feature(plugin)]
#![feature(custom_derive)]
#![plugin(serde_macros)]

extern crate raft; // <--- Kind of a big deal for this!
extern crate env_logger;
extern crate docopt;
extern crate serde;
extern crate rustc_serialize;

use std::net::SocketAddr;
use std::str::FromStr;
use std::collections::HashMap;

use serde::json::{self, Value};
use docopt::Docopt;

// Raft's major components. See comments in code on usage and things.
use raft::{
    Server,
    Client,
    state_machine,
    persistent_log,
    ServerId,
};
// A payload datatype. We're just using a simple enum. You can use whatever.
use Message::*;

// Using docopt we define the overall usage of the application.
static USAGE: &'static str = "
A replicated mutable hashmap. Operations on the register have serializable
consistency, but no durability (once all register servers are terminated the
map is lost).

Each register server holds a replica of the map, and coordinates with its
peers to update the maps values according to client commands. The register
is available for reading and writing only if a majority of register servers are
available.

Commands:

  get     Returns the current value of the key.

  put     Sets the current value of the key, and returns the previous
          value.

  cas     (compare and set) Conditionally sets the value of the key if the
          current value matches an expected value, returning true if the
          key was set.

  server  Starts a key server. Servers must be provided a unique ID and
          address (ip:port) at startup, along with the ID and address of all
          peer servers.register

Usage:
  hashmap get <key> (<node-address>)...
  hashmap put <key> <new-value> (<node-address>)...
  hashmap cas <key> <expected-value> <new-value> (<node-address>)...
  hashmap server <id> [<node-id> <node-address>]...
  hashmap (-h | --help)

Options:
  -h --help   Show a help message.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_server: bool,
    cmd_get: bool,
    cmd_put: bool,
    cmd_cas: bool,

    // When creating a server you will necessarily need some sort of unique ID for it as well
    // as a list of peers. In this example we just accept them straight from args. You might
    // find it best to use a `toml` or `yaml` or `json` file.
    arg_id: Option<u64>,
    arg_node_id: Vec<u64>,
    arg_node_address: Vec<String>,

    // In this example keys and values are associated. In your application you can model your data
    // however you please.
    arg_key: String,
    arg_new_value: String,
    arg_expected_value: String,
}

/// This is the defined message type for this example. For the sake of simplicity we don't go very
/// far with this. In a "real" application you may want to more distinctly distinguish between
/// data meant for `.query()` and data meant for `.propose()`.
#[derive(Serialize, Deserialize)]
pub enum Message {
    Get(String),
    Put(String, Value),
    Cas(String, Value, Value),
}

/// Just a plain old boring "parse args and dispatch" call.
fn main() {
    let _ = env_logger::init();
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    if args.cmd_server {
        server(&args);
    } else if args.cmd_get {
        get(&args);
    } else if args.cmd_put {
        put(&args);
    } else if args.cmd_cas {
        cas(&args);
    }
}

/// A simple convenience method since this is an example and it should exit if given invalid params.
fn parse_addr(addr: &str) -> SocketAddr {
    SocketAddr::from_str(addr)
               .ok()
               .expect(&format!("unable to parse socket address: {}", addr))
}

/// Creates a Raft server using the specified ID from the list of nodes.
fn server(args: &Args) {
    // Creating a raft server requires several things:

    // A persistent log implementation, which manages the persistent, replicated log...
    let persistent_log = persistent_log::MemLog::new();

    // A state machine which replicates state. This state should be the same on all nodes.
    let state_machine = HashmapStateMachine::new();

    // As well as a unique server id.
    let id = ServerId::from(args.arg_id.unwrap());

    // ...  And a list of peers.
    let mut peers = args.arg_node_id
                    .iter()
                    .zip(args.arg_node_address.iter())
                    .map(|(&id, addr)| (ServerId::from(id), parse_addr(&addr)))
                    .collect::<HashMap<_,_>>();

    // The Raft Server will return an error if it's ID is inside of it's peer set. Don't do that.
    // Instead, take it out and use it!
    let addr = peers.remove(&id).unwrap();

    // Using all of the above components.
    // You probably shouldn't `.unwrap()` in production code unless you're totally sure it works
    // 100% of the time, all the time.
    Server::run(id, addr, peers, persistent_log, state_machine).unwrap();
}

/// Gets a value for a given key from the provided Raft cluster.
fn get(args: &Args) {
    // Clients necessarily need to now the valid set of nodes which they can talk to.
    // This is both so they can try to talk to all the nodes if some are failing, and so that it
    // can verify that it's not being lead astray somehow in redirections on leadership changes.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    // Clients and be stored and reused, or used once and discarded.
    // There is very small overhead in connecting a new client to a cluster as it must discover and
    // identify itself to the leader.
    let mut client = Client::new(cluster);

    // In this example `serde::json` is used to serialize and deserialize messages.
    // Since Raft accepts `[u8]` the way you structure your data, the serialization method you
    // choose, and how you interpret that data is entirely up to you.
    let payload = json::to_string(&Message::Get(args.arg_key.clone())).unwrap();

    // A query executes **immutably** on the leader of the cluster and does not pass through the
    // persistent log. This is intended for querying the current state of the state machine.
    let response = client.query(payload.as_bytes()).unwrap();

    // A response will block until it's query is complete. This is intended and expected behavior
    // based on the papers specifications.
    println!("{}", String::from_utf8(response).unwrap())
}

/// Sets a value for a given key in the provided Raft cluster.
fn put(args: &Args) {
    // Same as above.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    let mut client = Client::new(cluster);

    let new_value = json::to_value(&args.arg_new_value);
    let payload = json::to_string(&Message::Put(args.arg_key.clone(), new_value)).unwrap();

    // A propose will go through the persistent log and mutably modify the state machine in some
    // way. This is **much** slower than `.query()`.
    let response = client.propose(payload.as_bytes()).unwrap();

    // A response will block until it's proposal is complete. This is intended and expected behavior
    // based on the papers specifications.
    println!("{}", String::from_utf8(response).unwrap())
}

/// Compares and sets a value for a given key in the provided Raft cluster if the value is what is
/// expected.
fn cas(args: &Args) {
    // Same as above.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    let mut client = Client::new(cluster);

    let new_value = json::to_value(&args.arg_new_value);
    let expected_value = json::to_value(&args.arg_expected_value);
    let payload = json::to_string(&Message::Cas(args.arg_key.clone(), expected_value, new_value)).unwrap();

    let response = client.propose(payload.as_bytes()).unwrap();

    println!("{}", String::from_utf8(response).unwrap())
}

/// A state machine that holds a hashmap.
#[derive(Debug)]
pub struct HashmapStateMachine {
    map: HashMap<String, Value>,
}

/// Implement anything you want... A `new()` is generally a great idea.
impl HashmapStateMachine {
    pub fn new() -> HashmapStateMachine {
        HashmapStateMachine {
            map: HashMap::new(),
        }
    }
}

/// Implementing `state_machine::StateMachine` allows your application specific state machine to be
/// used in Raft. Feel encouraged to base yours of one of ours in these examples.
impl state_machine::StateMachine for HashmapStateMachine {

    /// `apply()` is called on when a client's `.propose()` is commited and reaches the state
    /// machine. At this point it is durable and is going to be applied on at least half the nodes
    /// within the next couple round trips.
    fn apply(&mut self, new_value: &[u8]) -> Vec<u8> {
        // Deserialize
        let string = String::from_utf8_lossy(new_value);
        let message = json::from_str(&string).unwrap();

        // Handle
        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            Put(key, value) => {
                let old_value = &self.map.insert(key, value);
                json::to_string(old_value)
            },
            Cas(key, old_check, new) => {
                if *self.map.get(&key).unwrap() == old_check {
                    let _ = self.map.insert(key, new);
                    json::to_string(&true)
                } else {
                    json::to_string(&false)
                }
            },
        };

        // Respond.
        response.unwrap().into_bytes()
    }

    /// `query()` is called on when a client's `.query()` is recieved. It does not go through the
    /// persistent log, it does not mutate the state of the state machine, and it is intended to be
    /// fast.
    fn query(&self, query: &[u8]) -> Vec<u8> {
        // Deserialize
        let string = String::from_utf8_lossy(query);
        let message = json::from_str(&string).unwrap();

        // Handle
        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            _ => panic!("Can't do mutating requests in query"),
        };

        // Respond.
        response.unwrap().into_bytes()
    }

    fn snapshot(&self) -> Vec<u8> {
        json::to_string(&self.map)
            .unwrap()
            .into_bytes()
    }

    fn restore_snapshot(&mut self, snapshot_value: Vec<u8>) {
        self.map = json::from_str(&String::from_utf8_lossy(&snapshot_value)).unwrap();
        ()
    }
}
<|endoftext|>


<commit_before>#[crate_id = "vm#0.0"];
#[crate_type = "bin"];
#[feature(managed_boxes, macro_rules, globs)];
extern mod extra;
use std::hashmap::HashMap;
use std::rc::Rc;
use std::path::Path;
use std::io::File;
use std::str::{from_utf8};
use typecheck::TypeEnvironment;
use compiler::{Compiler, Assembly,
    Instruction, Add, Sub, Multiply, Divide, Remainder, Push, PushGlobal, PushInt, Mkap, Eval, Unwind, Update, Pop, Slide, Split, Pack, CaseJump, Jump,
    SuperCombinator};
use parser::Parser;

mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod module;
mod graph;

struct Scope<'a, T> {
    variables: HashMap<~str, T>,
    parent: Option<&'a Scope<'a, T>>
}

impl <'a, T> Scope<'a, T> {

    fn new() -> Scope<T> {
        Scope { variables : HashMap::new(), parent : None }
    }

    fn insert(&mut self, identifier : ~str, value : T) {
        self.variables.insert(identifier, value);
    }

    fn find(&'a self, identifier : &str) -> Option<&'a T> {
       match self.variables.find_equiv(&identifier) {
            Some(var) => Some(var),
            None => match self.parent {
                Some(parent) => parent.find(identifier),
                None => None
            }
       }
    }

    fn child(&'a self) -> Scope<'a, T> {
        Scope { variables : HashMap::new(), parent : Some(self) }
    }
}

#[deriving(Clone)]
enum Node<'a> {
    Application(Rc<Node<'a>>, Rc<Node<'a>>),
    Int(int),
    Combinator(&'a SuperCombinator),
    Indirection(Rc<Node<'a>>),
    Constructor(u16, ~[Rc<Node<'a>>])
}

struct VM<'a> {
    assembly : Assembly,
    heap : ~[Node<'a>]
}

impl <'a> VM<'a> {
    fn new() -> VM {
        VM { assembly : Assembly { superCombinators : ~[] }, heap : ~[] }
    }

    fn evaluate(&'a self, code: &[Instruction]) -> Node<'a> {
        let mut stack = ~[];
        self.execute(&mut stack, code);
        static evalCode : &'static [Instruction] = &[Eval];
        self.execute(&mut stack, evalCode);
        assert_eq!(stack.len(), 1);
        stack[0].borrow().clone()
    }

    fn execute(&'a self, stack : &mut ~[Rc<Node<'a>>], code : &[Instruction]) {
        debug!("----------------------------");
        debug!("Entering frame with stack");
        for x in stack.iter() {
            debug!("{:?}", x.borrow());
        }
        debug!("");
        let mut i = 0;
        while i < code.len() {
            debug!("Executing instruction : {:?}", code[i]);
            match &code[i] {
                &Add => primitive(stack, |l, r| { l + r }),
                &Sub => primitive(stack, |l, r| { l - r }),
                &Multiply => primitive(stack, |l, r| { l * r }),
                &Divide => primitive(stack, |l, r| { l / r }),
                &Remainder => primitive(stack, |l, r| { l % r }),
                &PushInt(value) => { stack.push(Rc::new(Int(value))); }
                &Push(index) => {
                    let x = stack[index].clone();
                    debug!("Pushed {:?}", x.borrow());
                    for j in range(0, stack.len()) {
                        debug!(" {}  {:?}", j, stack[j].borrow());
                    }
                    stack.push(x);
                }
                &PushGlobal(index) => {
                    match &self.assembly.superCombinators[index] {
                        &(_, ref sc) => stack.push(Rc::new(Combinator(sc)))
                    }
                }
                &Mkap => {
                    let func = stack.pop();
                    let arg = stack.pop();
                    debug!("Mkap {:?} {:?}", func.borrow(), arg.borrow());
                    stack.push(Rc::new(Application(func, arg)));
                }
                &Eval => {
                    static unwindCode : &'static [Instruction] = &[Unwind];
                    let mut newStack = ~[stack.pop()];
                    self.execute(&mut newStack, unwindCode);
                    assert_eq!(newStack.len(), 1);
                    stack.push(newStack.pop());
                }
                &Pop(num) => {
                    for _ in range(0, num) {
                        stack.pop();
                    }
                }
                &Update(index) => {
                    stack[index] = Rc::new(Indirection(stack[stack.len() - 1].clone()));
                }
                &Unwind => {
                    match (*stack[stack.len() - 1].borrow()).clone() {
                        Application(func, _) => {
                            stack.push(func);
                            i -= 1;//Redo the unwind instruction
                        }
                        Combinator(comb) => {
                            if stack.len() - 1 < comb.arity as uint {
                                while stack.len() > 1 {
                                    stack.pop();
                                }
                            }
                            else {
                                for j in range(stack.len() - (comb.arity as uint) - 1, stack.len() - 1) {
                                    stack[j] = match stack[j].borrow() {
                                        &Application(_, ref arg) => arg.clone(),
                                        _ => fail!("Expected Application")
                                    };
                                }
                                let mut newStack = ~[];
                                for i in range(0, comb.arity as uint) {
                                    let index = stack.len() - i - 2;
                                    newStack.push(stack[index].clone());
                                }

                                debug!("Call");
                                for j in range(0, newStack.len()) {
                                    debug!(" {}  {:?}", j, newStack[j].borrow());
                                }
                                self.execute(&mut newStack, comb.instructions);
                                assert_eq!(newStack.len(), 1);
                                for _ in range(0, comb.arity + 1) {
                                    stack.pop();
                                }
                                stack.push(newStack.pop());
                            }
                        }
                        Indirection(node) => {
                            stack[stack.len() - 1] = node;
                            i -= 1;
                        }
                        _ => ()
                    }
                }
                &Slide(size) => {
                    let top = stack.pop();
                    for _ in range(0, size) {
                        stack.pop();
                    }
                    stack.push(top);
                }
                &Split(_) => {
                    let x = stack.pop();
                    match x.borrow() {
                        &Constructor(_, ref fields) => {
                            for field in fields.iter() {
                                stack.push(field.clone());
                            }
                        }
                        _ => fail!("Expected constructor in Split instruction")
                    }
                }
                &Pack(tag, arity) => {
                    let args = std::vec::from_fn(arity as uint, |_| stack.pop());
                    stack.push(Rc::new(Constructor(tag, args)));
                }
                &CaseJump(jump_tag) => {
                    match stack[stack.len() - 1].borrow() {
                        &Constructor(tag, _) => {
                            if jump_tag != tag as uint {
                                i += 1;//Skip the jump instruction
                            }
                        }
                        _ => fail!("Expected constructor when executing CaseJump")
                    }
                }
                &Jump(to) => {
                    i = to - 1;
                }
                //undefined => fail!("Use of undefined instruction {:?}", undefined)
            }
            i += 1;
        }
        debug!("End frame");
        debug!("--------------------------");
    }
}

fn primitive(stack: &mut ~[Rc<Node>], f: |int, int| -> int) {
    let r = stack.pop();
    let l = stack.pop();
    match (l.borrow(), r.borrow()) {
        (&Int(lhs), &Int(rhs)) => stack.push(Rc::new(Int(f(lhs, rhs)))),
        (lhs, rhs) => fail!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs)
    }
}

fn main() {
    let arguments = std::os::args();
    match arguments {
        [_, expr_str] => {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = parser.expression_();

            let mut type_env = TypeEnvironment::new();
            type_env.typecheck(&mut expr);

            let mut compiler = Compiler::new();
            let instr = compiler.compileExpression(&expr);

            let vm = VM::new();
            let mut stack = ~[];
            vm.execute(&mut stack, instr);
            println!("{:?}", stack[0].borrow());
        }
        [_, ~"-l", filename] => {
            let path = &Path::new(filename);
            let s  = File::open(path).read_to_end();
            let contents : &str = from_utf8(s);
            let result = execute_main(contents.chars());
            match result {
                Some(x) => println!("{:?}", x),
                None => println!("Error running file {:?}", path)
            }
        }
        _ => return println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

#[deriving(Eq)]
enum VMResult {
    IntResult(int),
    ConstructorResult(u16, ~[VMResult])
}

fn compile_iter<T : Iterator<char>>(iterator: T) -> Assembly {
    let mut parser = Parser::new(iterator);
    let mut module = parser.module();

    let mut typer = TypeEnvironment::new();
    typer.typecheck_module(&mut module);

    let mut compiler = Compiler::new();
    compiler.compileModule(&module)
}

fn extract_result(node: Node) -> Option<VMResult> {
    match node {
        Constructor(tag, fields) => {
            let mut result = ~[];
            for field in fields.iter() {
                match extract_result(field.borrow().clone()) {
                    Some(x) => result.push(x),
                    None => return None
                }
            }
            Some(ConstructorResult(tag, result))
        }
        Int(i) => Some(IntResult(i)),
        x => {
            println!("Can't evalute result to {:?}", x);
            None
        }
    }
}

fn execute_main<T : Iterator<char>>(iterator: T) -> Option<VMResult> {
    let mut vm = VM::new();
    vm.assembly = compile_iter(iterator);
    let x = vm.assembly.superCombinators.iter().find(|& &(ref name, _)| *name == ~"main");
    match x {
        Some(&(_, ref sc)) => {
            assert!(sc.arity == 0);
            let result = vm.evaluate(sc.instructions);
            extract_result(result)
        }
        None => None
    }
}

#[test]
fn test_primitive()
{
    assert_eq!(execute_main("main = primIntAdd 10 5".chars()), Some(IntResult(15)));
    assert_eq!(execute_main("main = primIntSubtract 7 (primIntMultiply 2 3)".chars()), Some(IntResult(1)));
    assert_eq!(execute_main("main = primIntDivide 10 (primIntRemainder 6 4)".chars()), Some(IntResult(5)));
}
<commit_msg>Added some tests for the VM, basic arithmetic and function calling<commit_after>#[crate_id = "vm#0.0"];
#[crate_type = "bin"];
#[feature(managed_boxes, macro_rules, globs)];
extern mod extra;
use std::hashmap::HashMap;
use std::rc::Rc;
use std::path::Path;
use std::io::File;
use std::str::{from_utf8};
use typecheck::TypeEnvironment;
use compiler::{Compiler, Assembly,
    Instruction, Add, Sub, Multiply, Divide, Remainder, Push, PushGlobal, PushInt, Mkap, Eval, Unwind, Update, Pop, Slide, Split, Pack, CaseJump, Jump,
    SuperCombinator};
use parser::Parser;

mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod module;
mod graph;

struct Scope<'a, T> {
    variables: HashMap<~str, T>,
    parent: Option<&'a Scope<'a, T>>
}

impl <'a, T> Scope<'a, T> {

    fn new() -> Scope<T> {
        Scope { variables : HashMap::new(), parent : None }
    }

    fn insert(&mut self, identifier : ~str, value : T) {
        self.variables.insert(identifier, value);
    }

    fn find(&'a self, identifier : &str) -> Option<&'a T> {
       match self.variables.find_equiv(&identifier) {
            Some(var) => Some(var),
            None => match self.parent {
                Some(parent) => parent.find(identifier),
                None => None
            }
       }
    }

    fn child(&'a self) -> Scope<'a, T> {
        Scope { variables : HashMap::new(), parent : Some(self) }
    }
}

#[deriving(Clone)]
enum Node<'a> {
    Application(Rc<Node<'a>>, Rc<Node<'a>>),
    Int(int),
    Combinator(&'a SuperCombinator),
    Indirection(Rc<Node<'a>>),
    Constructor(u16, ~[Rc<Node<'a>>])
}

struct VM<'a> {
    assembly : Assembly,
    heap : ~[Node<'a>]
}

impl <'a> VM<'a> {
    fn new() -> VM {
        VM { assembly : Assembly { superCombinators : ~[] }, heap : ~[] }
    }

    fn evaluate(&'a self, code: &[Instruction]) -> Node<'a> {
        let mut stack = ~[];
        self.execute(&mut stack, code);
        static evalCode : &'static [Instruction] = &[Eval];
        self.execute(&mut stack, evalCode);
        assert_eq!(stack.len(), 1);
        stack[0].borrow().clone()
    }

    fn execute(&'a self, stack : &mut ~[Rc<Node<'a>>], code : &[Instruction]) {
        debug!("----------------------------");
        debug!("Entering frame with stack");
        for x in stack.iter() {
            debug!("{:?}", x.borrow());
        }
        debug!("");
        let mut i = 0;
        while i < code.len() {
            debug!("Executing instruction : {:?}", code[i]);
            match &code[i] {
                &Add => primitive(stack, |l, r| { l + r }),
                &Sub => primitive(stack, |l, r| { l - r }),
                &Multiply => primitive(stack, |l, r| { l * r }),
                &Divide => primitive(stack, |l, r| { l / r }),
                &Remainder => primitive(stack, |l, r| { l % r }),
                &PushInt(value) => { stack.push(Rc::new(Int(value))); }
                &Push(index) => {
                    let x = stack[index].clone();
                    debug!("Pushed {:?}", x.borrow());
                    for j in range(0, stack.len()) {
                        debug!(" {}  {:?}", j, stack[j].borrow());
                    }
                    stack.push(x);
                }
                &PushGlobal(index) => {
                    match &self.assembly.superCombinators[index] {
                        &(_, ref sc) => stack.push(Rc::new(Combinator(sc)))
                    }
                }
                &Mkap => {
                    let func = stack.pop();
                    let arg = stack.pop();
                    debug!("Mkap {:?} {:?}", func.borrow(), arg.borrow());
                    stack.push(Rc::new(Application(func, arg)));
                }
                &Eval => {
                    static unwindCode : &'static [Instruction] = &[Unwind];
                    let mut newStack = ~[stack.pop()];
                    self.execute(&mut newStack, unwindCode);
                    assert_eq!(newStack.len(), 1);
                    stack.push(newStack.pop());
                }
                &Pop(num) => {
                    for _ in range(0, num) {
                        stack.pop();
                    }
                }
                &Update(index) => {
                    stack[index] = Rc::new(Indirection(stack[stack.len() - 1].clone()));
                }
                &Unwind => {
                    match (*stack[stack.len() - 1].borrow()).clone() {
                        Application(func, _) => {
                            stack.push(func);
                            i -= 1;//Redo the unwind instruction
                        }
                        Combinator(comb) => {
                            if stack.len() - 1 < comb.arity as uint {
                                while stack.len() > 1 {
                                    stack.pop();
                                }
                            }
                            else {
                                for j in range(stack.len() - (comb.arity as uint) - 1, stack.len() - 1) {
                                    stack[j] = match stack[j].borrow() {
                                        &Application(_, ref arg) => arg.clone(),
                                        _ => fail!("Expected Application")
                                    };
                                }
                                let mut newStack = ~[];
                                for i in range(0, comb.arity as uint) {
                                    let index = stack.len() - i - 2;
                                    newStack.push(stack[index].clone());
                                }

                                debug!("Call");
                                for j in range(0, newStack.len()) {
                                    debug!(" {}  {:?}", j, newStack[j].borrow());
                                }
                                self.execute(&mut newStack, comb.instructions);
                                assert_eq!(newStack.len(), 1);
                                for _ in range(0, comb.arity + 1) {
                                    stack.pop();
                                }
                                stack.push(newStack.pop());
                            }
                        }
                        Indirection(node) => {
                            stack[stack.len() - 1] = node;
                            i -= 1;
                        }
                        _ => ()
                    }
                }
                &Slide(size) => {
                    let top = stack.pop();
                    for _ in range(0, size) {
                        stack.pop();
                    }
                    stack.push(top);
                }
                &Split(_) => {
                    let x = stack.pop();
                    match x.borrow() {
                        &Constructor(_, ref fields) => {
                            for field in fields.iter() {
                                stack.push(field.clone());
                            }
                        }
                        _ => fail!("Expected constructor in Split instruction")
                    }
                }
                &Pack(tag, arity) => {
                    let args = std::vec::from_fn(arity as uint, |_| stack.pop());
                    stack.push(Rc::new(Constructor(tag, args)));
                }
                &CaseJump(jump_tag) => {
                    match stack[stack.len() - 1].borrow() {
                        &Constructor(tag, _) => {
                            if jump_tag != tag as uint {
                                i += 1;//Skip the jump instruction
                            }
                        }
                        _ => fail!("Expected constructor when executing CaseJump")
                    }
                }
                &Jump(to) => {
                    i = to - 1;
                }
                //undefined => fail!("Use of undefined instruction {:?}", undefined)
            }
            i += 1;
        }
        debug!("End frame");
        debug!("--------------------------");
    }
}

fn primitive(stack: &mut ~[Rc<Node>], f: |int, int| -> int) {
    let r = stack.pop();
    let l = stack.pop();
    match (l.borrow(), r.borrow()) {
        (&Int(lhs), &Int(rhs)) => stack.push(Rc::new(Int(f(lhs, rhs)))),
        (lhs, rhs) => fail!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs)
    }
}

fn main() {
    let arguments = std::os::args();
    match arguments {
        [_, expr_str] => {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = parser.expression_();

            let mut type_env = TypeEnvironment::new();
            type_env.typecheck(&mut expr);

            let mut compiler = Compiler::new();
            let instr = compiler.compileExpression(&expr);

            let vm = VM::new();
            let mut stack = ~[];
            vm.execute(&mut stack, instr);
            println!("{:?}", stack[0].borrow());
        }
        [_, ~"-l", filename] => {
            let path = &Path::new(filename);
            let s  = File::open(path).read_to_end();
            let contents : &str = from_utf8(s);
            let result = execute_main(contents.chars());
            match result {
                Some(x) => println!("{:?}", x),
                None => println!("Error running file {:?}", path)
            }
        }
        _ => return println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

#[deriving(Eq)]
enum VMResult {
    IntResult(int),
    ConstructorResult(u16, ~[VMResult])
}

fn compile_iter<T : Iterator<char>>(iterator: T) -> Assembly {
    let mut parser = Parser::new(iterator);
    let mut module = parser.module();

    let mut typer = TypeEnvironment::new();
    typer.typecheck_module(&mut module);

    let mut compiler = Compiler::new();
    compiler.compileModule(&module)
}

fn extract_result(node: Node) -> Option<VMResult> {
    match node {
        Constructor(tag, fields) => {
            let mut result = ~[];
            for field in fields.iter() {
                match extract_result(field.borrow().clone()) {
                    Some(x) => result.push(x),
                    None => return None
                }
            }
            Some(ConstructorResult(tag, result))
        }
        Int(i) => Some(IntResult(i)),
        x => {
            println!("Can't evalute result to {:?}", x);
            None
        }
    }
}

fn execute_main<T : Iterator<char>>(iterator: T) -> Option<VMResult> {
    let mut vm = VM::new();
    vm.assembly = compile_iter(iterator);
    let x = vm.assembly.superCombinators.iter().find(|& &(ref name, _)| *name == ~"main");
    match x {
        Some(&(_, ref sc)) => {
            assert!(sc.arity == 0);
            let result = vm.evaluate(sc.instructions);
            extract_result(result)
        }
        None => None
    }
}

#[test]
fn test_primitive()
{
    assert_eq!(execute_main("main = primIntAdd 10 5".chars()), Some(IntResult(15)));
    assert_eq!(execute_main("main = primIntSubtract 7 (primIntMultiply 2 3)".chars()), Some(IntResult(1)));
    assert_eq!(execute_main("main = primIntDivide 10 (primIntRemainder 6 4)".chars()), Some(IntResult(5)));
}

#[test]
fn test_function()
{
    let module =
r"mult2 x = primIntMultiply x 2

main = mult2 10";
    assert_eq!(execute_main(module.chars()), Some(IntResult(20)));

    let module2 =
r"mult2 x = primIntMultiply x 2

add x y = primIntAdd y x

main = add 3 (mult2 10)";
    assert_eq!(execute_main(module2.chars()), Some(IntResult(23)));
}
#[test]
fn test_case()
{
    let module =
r"mult2 x = primIntMultiply x 2

main = case [mult2 123, 0] of
    : x xs -> x
    [] -> 10";
    assert_eq!(execute_main(module.chars()), Some(IntResult(246)));
}
<|endoftext|>