<commit_before>// Copyright 2017 The Exonum Team
//
// 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.

//! The time oracle service for Exonum.

#![deny(missing_debug_implementations)]
#![deny(missing_docs)]

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use iron::prelude::*;
use iron::Handler;
use router::Router;

use std::time::SystemTime;

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, Transaction, ApiContext};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, MapIndex, Entry};
use exonum::crypto::PublicKey;
use exonum::encoding;
use exonum::helpers::fabric::{ServiceFactory, Context};
use exonum::api::Api;

/// Time service id.
const SERVICE_ID: u16 = 4;
/// `TxTime` transaction id.
const TX_TIME_ID: u16 = 1;
/// Time service name.
const SERVICE_NAME: &str = "exonum_time";

encoding_struct! {
    /// Time information.
    struct Time {
        const SIZE = 12;

        /// Field that stores `SystemTime`.
        field time:     SystemTime  [00 => 12]
    }
}

/// `Exonum-time` service database schema.
#[derive(Debug)]
pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    /// Constructs schema for the given `snapshot`.
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    /// Returns the table that stores `Time` struct for every validator.
    pub fn validators_time(&self) -> MapIndex<&Snapshot, PublicKey, Time> {
        MapIndex::new(
            format!("{}.validators_time", SERVICE_NAME),
            self.view.as_ref(),
        )
    }

    /// Returns stored `Time`.
    pub fn time(&self) -> Entry<&Snapshot, Time> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view.as_ref())
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    /// Mutable reference to the ['validators_time'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.validators_time
    pub fn validators_time_mut(&mut self) -> MapIndex<&mut Fork, PublicKey, Time> {
        MapIndex::new(format!("{}.validators_time", SERVICE_NAME), self.view)
    }

    /// Mutable reference to the ['time'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.time
    pub fn time_mut(&mut self) -> Entry<&mut Fork, Time> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view)
    }
}

message! {
    /// Transaction that is sent by the validator after the commit of the block.
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        const SIZE = 44;
        /// Validator's time.
        field time:     SystemTime  [00 => 12]
        /// Validator's public key.
        field pub_key:  &PublicKey  [12 => 44]
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;
        // The transaction must be signed by the validator.
        if !validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        })
        {
            return;
        }

        let mut schema = TimeSchema::new(view);
        match schema.validators_time().get(self.pub_key()) {
            // The validator time in the storage should be less than in the transaction.
            Some(ref storage_time) if storage_time.time() >= self.time() => {
                return;
            }
            // Write the time for the validator.
            _ => {
                schema.validators_time_mut().put(
                    self.pub_key(),
                    Time::new(self.time()),
                )
            }
        }

        // Find all known times for the validators.
        let mut validators_time: Vec<SystemTime>;
        {
            let idx = schema.validators_time();
            validators_time = idx.iter()
                .filter_map(|pair| {
                    validator_keys
                        .iter()
                        .find(|validator| validator.service_key == pair.0)
                        .map(|_| pair.1.time())
                })
                .collect();
        }

        // The largest number of Byzantine nodes.
        let max_byzantine_nodes = validator_keys.len() / 3;
        if validators_time.len() <= max_byzantine_nodes {
            return;
        }
        // Ordering time from highest to lowest.
        validators_time.sort_by(|a, b| b.cmp(a));

        match schema.time().get() {
            // Selected time should be longer than the time in the storage.
            Some(ref current_time)
                if current_time.time() >= validators_time[max_byzantine_nodes] => {
                return;
            }
            _ => {
                // Change the time in the storage.
                schema.time_mut().set(Time::new(
                    validators_time[max_byzantine_nodes],
                ));
            }
        }
    }
}

/// Implements the node API.
#[derive(Clone)]
struct TimeApi {
    blockchain: Blockchain,
}

/// Shortcut to get data from storage.
impl TimeApi {
    /// Endpoint for getting value of the time that is saved in storage.
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let current_time = schema.time().get();
        self.ok_response(&serde_json::to_value(current_time).unwrap())
    }

    /// Endpoint for getting time values for all validators.
    fn get_validators_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_time();
        let validators_time: Vec<Time> = idx.values().collect();
        if validators_time.is_empty() {
            self.not_found_response(&serde_json::to_value("Validators time database if empty")
                .unwrap())
        } else {
            self.ok_response(&serde_json::to_value(validators_time).unwrap())
        }
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_validators_time = move |req: &mut Request| self_.get_validators_time(req);
        router.get(
            "/validators_time",
            get_validators_time,
            "get_validators_time",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("/current_time", get_current_time, "get_current_time");
    }
}

/// A helper trait that provides the node with a current time.
pub trait TimeProvider: Send + Sync + ::std::fmt::Debug {
    /// Returns the current time.
    fn current_time(&self) -> SystemTime;
}

#[derive(Debug)]
struct SystemTimeProvider;

impl TimeProvider for SystemTimeProvider {
    fn current_time(&self) -> SystemTime {
        SystemTime::now()
    }
}

/// Define the service.
#[derive(Debug)]
pub struct TimeService {
    /// Current time.
    time: Box<TimeProvider>,
}

impl Default for TimeService {
    fn default() -> TimeService {
        TimeService { time: Box::new(SystemTimeProvider) as Box<TimeProvider> }
    }
}

impl TimeService {
    /// Create a new `TimeService`.
    pub fn new() -> TimeService {
        TimeService::default()
    }

    /// Create a new `TimeService` with time provider `T`.
    pub fn with_provider<T: Into<Box<TimeProvider>>>(time_provider: T) -> TimeService {
        TimeService { time: time_provider.into() }
    }
}

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        SERVICE_NAME
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    /// Creates transaction after commit of the block.
    fn handle_commit(&self, context: &ServiceContext) {
        // The transaction must be created by the validator.
        if context.validator_id().is_none() {
            return;
        }
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context
            .transaction_sender()
            .send(Box::new(
                TxTime::new(self.time.current_time(), &pub_key, &sec_key),
            ))
            .unwrap();
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

/// A time service creator for the `NodeBuilder`.
#[derive(Debug)]
pub struct TimeServiceFactory;

impl ServiceFactory for TimeServiceFactory {
    fn make_service(&mut self, _: &Context) -> Box<Service> {
        Box::new(TimeService::new())
    }
}
<commit_msg>Suppress clippy warning.<commit_after>// Copyright 2017 The Exonum Team
//
// 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.

//! The time oracle service for Exonum.

#![deny(missing_debug_implementations, missing_docs)]

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use iron::prelude::*;
use iron::Handler;
use router::Router;

use std::time::SystemTime;

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, Transaction, ApiContext};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, MapIndex, Entry};
use exonum::crypto::PublicKey;
use exonum::encoding;
use exonum::helpers::fabric::{ServiceFactory, Context};
use exonum::api::Api;

/// Time service id.
const SERVICE_ID: u16 = 4;
/// `TxTime` transaction id.
const TX_TIME_ID: u16 = 1;
/// Time service name.
const SERVICE_NAME: &str = "exonum_time";

encoding_struct! {
    /// Time information.
    struct Time {
        const SIZE = 12;

        /// Field that stores `SystemTime`.
        field time:     SystemTime  [00 => 12]
    }
}

/// `Exonum-time` service database schema.
#[derive(Debug)]
pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    /// Constructs schema for the given `snapshot`.
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    /// Returns the table that stores `Time` struct for every validator.
    pub fn validators_time(&self) -> MapIndex<&Snapshot, PublicKey, Time> {
        MapIndex::new(
            format!("{}.validators_time", SERVICE_NAME),
            self.view.as_ref(),
        )
    }

    /// Returns stored `Time`.
    pub fn time(&self) -> Entry<&Snapshot, Time> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view.as_ref())
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    /// Mutable reference to the ['validators_time'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.validators_time
    pub fn validators_time_mut(&mut self) -> MapIndex<&mut Fork, PublicKey, Time> {
        MapIndex::new(format!("{}.validators_time", SERVICE_NAME), self.view)
    }

    /// Mutable reference to the ['time'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.time
    pub fn time_mut(&mut self) -> Entry<&mut Fork, Time> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view)
    }
}

message! {
    /// Transaction that is sent by the validator after the commit of the block.
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        const SIZE = 44;
        /// Validator's time.
        field time:     SystemTime  [00 => 12]
        /// Validator's public key.
        field pub_key:  &PublicKey  [12 => 44]
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;
        // The transaction must be signed by the validator.
        if !validator_keys.iter().any(|&validator| validator.service_key == *self.pub_key())
        {
            return;
        }

        let mut schema = TimeSchema::new(view);
        match schema.validators_time().get(self.pub_key()) {
            // The validator time in the storage should be less than in the transaction.
            Some(ref storage_time) if storage_time.time() >= self.time() => {
                return;
            }
            // Write the time for the validator.
            _ => {
                schema.validators_time_mut().put(
                    self.pub_key(),
                    Time::new(self.time()),
                )
            }
        }

        // Find all known times for the validators.
        let mut validators_time: Vec<SystemTime>;
        {
            let idx = schema.validators_time();
            validators_time = idx.iter()
                .filter_map(|pair| {
                    validator_keys
                        .iter()
                        .find(|validator| validator.service_key == pair.0)
                        .map(|_| pair.1.time())
                })
                .collect();
        }

        // The largest number of Byzantine nodes.
        let max_byzantine_nodes = validator_keys.len() / 3;
        if validators_time.len() <= max_byzantine_nodes {
            return;
        }
        // Ordering time from highest to lowest.
        validators_time.sort_by(|a, b| b.cmp(a));

        match schema.time().get() {
            // Selected time should be longer than the time in the storage.
            Some(ref current_time)
                if current_time.time() >= validators_time[max_byzantine_nodes] => {
                return;
            }
            _ => {
                // Change the time in the storage.
                schema.time_mut().set(Time::new(
                    validators_time[max_byzantine_nodes],
                ));
            }
        }
    }
}

/// Implements the node API.
#[derive(Clone)]
struct TimeApi {
    blockchain: Blockchain,
}

/// Shortcut to get data from storage.
impl TimeApi {
    /// Endpoint for getting value of the time that is saved in storage.
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let current_time = schema.time().get();
        self.ok_response(&serde_json::to_value(current_time).unwrap())
    }

    /// Endpoint for getting time values for all validators.
    fn get_validators_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_time();
        let validators_time: Vec<Time> = idx.values().collect();
        if validators_time.is_empty() {
            self.not_found_response(&serde_json::to_value("Validators time database if empty")
                .unwrap())
        } else {
            self.ok_response(&serde_json::to_value(validators_time).unwrap())
        }
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_validators_time = move |req: &mut Request| self_.get_validators_time(req);
        router.get(
            "/validators_time",
            get_validators_time,
            "get_validators_time",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("/current_time", get_current_time, "get_current_time");
    }
}

/// A helper trait that provides the node with a current time.
pub trait TimeProvider: Send + Sync + ::std::fmt::Debug {
    /// Returns the current time.
    fn current_time(&self) -> SystemTime;
}

#[derive(Debug)]
struct SystemTimeProvider;

impl TimeProvider for SystemTimeProvider {
    fn current_time(&self) -> SystemTime {
        SystemTime::now()
    }
}

/// Define the service.
#[derive(Debug)]
pub struct TimeService {
    /// Current time.
    time: Box<TimeProvider>,
}

impl Default for TimeService {
    fn default() -> TimeService {
        TimeService { time: Box::new(SystemTimeProvider) as Box<TimeProvider> }
    }
}

impl TimeService {
    /// Create a new `TimeService`.
    pub fn new() -> TimeService {
        TimeService::default()
    }

    /// Create a new `TimeService` with time provider `T`.
    pub fn with_provider<T: Into<Box<TimeProvider>>>(time_provider: T) -> TimeService {
        TimeService { time: time_provider.into() }
    }
}

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        SERVICE_NAME
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    /// Creates transaction after commit of the block.
    fn handle_commit(&self, context: &ServiceContext) {
        // The transaction must be created by the validator.
        if context.validator_id().is_none() {
            return;
        }
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context
            .transaction_sender()
            .send(Box::new(
                TxTime::new(self.time.current_time(), &pub_key, &sec_key),
            ))
            .unwrap();
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

/// A time service creator for the `NodeBuilder`.
#[derive(Debug)]
pub struct TimeServiceFactory;

impl ServiceFactory for TimeServiceFactory {
    fn make_service(&mut self, _: &Context) -> Box<Service> {
        Box::new(TimeService::new())
    }
}
<|endoftext|>


<commit_before>extern crate xml;

use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;

use xml::reader::{EventReader, XmlEvent};
use xml::attribute::OwnedAttribute;

mod error;
use error::{ErrorKind, AttributeError};

pub type Coordinate = f64;
pub type Id = i64;

#[derive(Debug, PartialEq)]
pub struct Tag {
    pub key: String,
    pub val: String
}

#[derive(Debug, PartialEq)]
pub struct Bounds {
    pub minlat: Coordinate,
    pub minlon: Coordinate,
    pub maxlat: Coordinate,
    pub maxlon: Coordinate,
}

#[derive(Debug, PartialEq)]
pub struct Node {
    pub id: i64,
    pub lat: Coordinate,
    pub lon: Coordinate,
    pub tags: Vec<Tag>
}

#[derive(Debug)]
pub struct OSM {
    pub bounds: Option<Bounds>,
    pub nodes: Vec<Node>
}

impl OSM {
    fn empty() -> OSM {
        OSM {
            bounds: None,
            nodes: Vec::new(),
        }
    }

    pub fn parse(file: File) -> Option<OSM> {
        let mut osm = OSM::empty();

        let reader = BufReader::new(file);
        let mut parser = EventReader::new(reader);

        loop {
            match parse_element_data(&mut parser) {
                Err(ErrorKind::UnknownElement) => continue,
                Err(ErrorKind::MalformedElement) => continue,
                Err(ErrorKind::BoundsMissing(_)) => osm.bounds = None,
                Err(_) => return None,
                Ok(data) => {
                    match data {
                        ElementData::EndOfDocument => return Some(osm),
                        ElementData::Ignored => continue,
                        ElementData::Bounds(minlat, minlon, maxlat, maxlon) => {
                            osm.bounds = Some(Bounds {
                                minlat: minlat,
                                minlon: minlon,
                                maxlat: maxlat,
                                maxlon: maxlon
                            });
                        },
                        ElementData::Node(id, lat, lon, tags) => {
                            osm.nodes.push(Node {
                                id: id,
                                lat: lat,
                                lon: lon,
                                tags: tags
                            });
                        },
                        _ => ()
                    }
                }
            }
        }
    }
}

enum ElementType {
    Bounds,
    Node,
    Way,
    Relation,
    Tag
}

enum ElementData {
    Bounds(Coordinate, Coordinate, Coordinate, Coordinate),
    NodeAttrs(Id, Coordinate, Coordinate),
    Node(Id, Coordinate, Coordinate, Vec<Tag>),
    // These two are here so we can terminate and skip uninteresting data without
    // using error handling.
    EndOfDocument,
    Ignored
}

impl FromStr for ElementType {
    type Err = ErrorKind;

    fn from_str(s: &str) -> Result<ElementType, ErrorKind> {
        let downcased = s.to_lowercase();

        if downcased == "bounds" {
            return Ok(ElementType::Bounds);
        }

        if downcased == "node" {
            return Ok(ElementType::Node);
        }

        if downcased == "way" {
            return Ok(ElementType::Way);
        }

        if downcased == "relation" {
            return Ok(ElementType::Relation);
        }

        if downcased == "tag" {
            return Ok(ElementType::Tag);
        }

        Err(ErrorKind::UnknownElement)
    }
}

fn parse_element_data(parser: &mut EventReader<BufReader<File>>) -> Result<ElementData, ErrorKind> {
    let element = try!(parser.next());
    match element {
        XmlEvent::EndDocument => Ok(ElementData::EndOfDocument),
        XmlEvent::StartElement { name, attributes, .. } => {
            let element_type = try!(ElementType::from_str(&name.local_name));

            match element_type {
                ElementType::Bounds => parse_bounds(&attributes),
                ElementType::Node => parse_node(parser, &attributes),
                _ => Err(ErrorKind::UnknownElement)
            }
        },
        _ => Ok(ElementData::Ignored)
    }
}

fn parse_node(parser: &mut EventReader<BufReader<File>>, attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let node_attrs = try!(parse_node_attributes(&attrs));

    if let ElementData::NodeAttrs(id, lat, lon) = node_attrs {
        let mut tags = Vec::new();

        // Parse Node child elements, if any
        loop {
            match try!(parser.next()) {
                XmlEvent::EndElement { name } => {
                    let element_type = try!(ElementType::from_str(&name.local_name));

                    match element_type {
                        ElementType::Node => return Ok(ElementData::Node(id, lat, lon, tags)),
                        _ => continue
                    }
                },
                XmlEvent::StartElement { name, attributes, .. } => {
                    let element_type = try!(ElementType::from_str(&name.local_name));

                    match element_type {
                        ElementType::Tag => {
                            if let Some(tag) = parse_tag_attributes(&attributes) {
                                tags.push(tag);
                            }
                        },
                        // Malformed node containing illegal children, ignore whole Node
                        ElementType::Bounds |
                        ElementType::Node |
                        ElementType::Relation |
                        ElementType::Way => return Err(ErrorKind::MalformedElement)
                    }
                },
                _ => continue
            }
        }
    } else {
        Err(ErrorKind::MalformedElement)
    }
}

fn parse_tag_attributes(attributes: &Vec<OwnedAttribute>) -> Option<Tag> {
    let mut iter = attributes.iter();
    iter.find(|attr| attr.name.local_name == "k")
        .and_then(|attr| Some(attr.value.clone()))
        .and_then(|key| {
            iter.find(|attr| attr.name.local_name == "v")
            .and_then(|attr| Some(attr.value.clone()))
            .and_then(|val| Some(Tag { key: key, val: val }))
        })
}

fn parse_bounds(attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let minlat = try!(find_attribute("minlat", attrs).map_err(ErrorKind::BoundsMissing));
    let minlon = try!(find_attribute("minlon", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlat = try!(find_attribute("maxlat", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlon = try!(find_attribute("maxlon", attrs).map_err(ErrorKind::BoundsMissing));

    Ok(ElementData::Bounds(minlat, minlon, maxlat, maxlon))
}

fn parse_node_attributes(attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let id = try!(find_attribute("id", attrs).map_err(ErrorKind::IdMissing));
    let lat = try!(find_attribute("lat", attrs).map_err(ErrorKind::CoordinateMissing));
    let lon = try!(find_attribute("lon", attrs).map_err(ErrorKind::CoordinateMissing));

    Ok(ElementData::NodeAttrs(id, lat, lon))
}

fn find_attribute<T>(name: &str, attrs: &Vec<OwnedAttribute>) -> Result<T, AttributeError>
    where AttributeError: std::convert::From<<T as std::str::FromStr>::Err>,
          T: FromStr
{
    let attr = attrs.iter().find(|attr| attr.name.local_name == name);
    match attr {
        Some(a) => {
            let val = try!(a.value.parse::<T>());
            Ok(val)
        },
        None => Err(AttributeError::Missing)
    }
}
<commit_msg>Parse raw Way data<commit_after>extern crate xml;

use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;

use xml::reader::{EventReader, XmlEvent};
use xml::attribute::OwnedAttribute;

mod error;
use error::{ErrorKind, AttributeError};

pub type Coordinate = f64;
pub type Id = i64;

#[derive(Debug, PartialEq)]
pub struct Tag {
    pub key: String,
    pub val: String
}

#[derive(Debug, PartialEq)]
pub struct Bounds {
    pub minlat: Coordinate,
    pub minlon: Coordinate,
    pub maxlat: Coordinate,
    pub maxlon: Coordinate,
}

#[derive(Debug, PartialEq)]
pub struct Node {
    pub id: i64,
    pub lat: Coordinate,
    pub lon: Coordinate,
    pub tags: Vec<Tag>
}

#[derive(Debug)]
pub struct OSM {
    pub bounds: Option<Bounds>,
    pub nodes: Vec<Node>
}

impl OSM {
    fn empty() -> OSM {
        OSM {
            bounds: None,
            nodes: Vec::new(),
        }
    }

    pub fn parse(file: File) -> Option<OSM> {
        let mut osm = OSM::empty();

        let reader = BufReader::new(file);
        let mut parser = EventReader::new(reader);

        loop {
            match parse_element_data(&mut parser) {
                Err(ErrorKind::UnknownElement) => continue,
                Err(ErrorKind::MalformedElement) => continue,
                Err(ErrorKind::BoundsMissing(_)) => osm.bounds = None,
                Err(_) => return None,
                Ok(data) => {
                    match data {
                        ElementData::EndOfDocument => return Some(osm),
                        ElementData::Ignored => continue,
                        ElementData::Bounds(minlat, minlon, maxlat, maxlon) => {
                            osm.bounds = Some(Bounds {
                                minlat: minlat,
                                minlon: minlon,
                                maxlat: maxlat,
                                maxlon: maxlon
                            });
                        },
                        ElementData::Node(id, lat, lon, tags) => {
                            osm.nodes.push(Node {
                                id: id,
                                lat: lat,
                                lon: lon,
                                tags: tags
                            });
                        },
                        _ => ()
                    }
                }
            }
        }
    }
}

enum ElementType {
    Bounds,
    Node,
    Way,
    Relation,
    Tag,
    NodeRef,
}

enum ElementData {
    Bounds(Coordinate, Coordinate, Coordinate, Coordinate),
    NodeAttrs(Id, Coordinate, Coordinate),
    Node(Id, Coordinate, Coordinate, Vec<Tag>),
    Way(Id, Vec<Id>, Vec<Tag>),
    // These two are here so we can terminate and skip uninteresting data without
    // using error handling.
    EndOfDocument,
    Ignored
}

impl FromStr for ElementType {
    type Err = ErrorKind;

    fn from_str(s: &str) -> Result<ElementType, ErrorKind> {
        let downcased = s.to_lowercase();

        if downcased == "bounds" {
            return Ok(ElementType::Bounds);
        }

        if downcased == "node" {
            return Ok(ElementType::Node);
        }

        if downcased == "way" {
            return Ok(ElementType::Way);
        }

        if downcased == "relation" {
            return Ok(ElementType::Relation);
        }

        if downcased == "tag" {
            return Ok(ElementType::Tag);
        }

        if downcased == "nd" {
            return Ok(ElementType::NodeRef);
        }

        Err(ErrorKind::UnknownElement)
    }
}

fn parse_element_data(parser: &mut EventReader<BufReader<File>>) -> Result<ElementData, ErrorKind> {
    let element = try!(parser.next());
    match element {
        XmlEvent::EndDocument => Ok(ElementData::EndOfDocument),
        XmlEvent::StartElement { name, attributes, .. } => {
            let element_type = try!(ElementType::from_str(&name.local_name));

            match element_type {
                ElementType::Bounds => parse_bounds(&attributes),
                ElementType::Node => parse_node(parser, &attributes),
                ElementType::Way => parse_way(parser, &attributes),
                _ => Err(ErrorKind::UnknownElement)
            }
        },
        _ => Ok(ElementData::Ignored)
    }
}

fn parse_way(parser: &mut EventReader<BufReader<File>>, attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let id = try!(find_attribute("id", attrs).map_err(ErrorKind::IdMissing));

    let mut node_refs = Vec::new();
    let mut tags = Vec::new();

    loop {
        match try!(parser.next()) {
            XmlEvent::EndElement { name } => {
                let element_type = try!(ElementType::from_str(&name.local_name));

                match element_type {
                    ElementType::Way => return Ok(ElementData::Way(id, node_refs, tags)),
                    _ => continue
                }
            },
            XmlEvent::StartElement { name, attributes, .. } => {
                let element_type = try!(ElementType::from_str(&name.local_name));

                match element_type {
                    ElementType::Tag => {
                        if let Some(tag) = parse_tag_attributes(&attributes) {
                            tags.push(tag);
                        }
                    },
                    ElementType::NodeRef => {
                        let node_ref = try!(find_attribute("ref", &attributes).map_err(ErrorKind::IdMissing));
                        node_refs.push(node_ref);
                    },
                    // Malformed node containing illegal children, ignore whole Node
                    ElementType::Bounds |
                    ElementType::Node |
                    ElementType::Relation |
                    ElementType::Way => return Err(ErrorKind::MalformedElement)
                }
            },
            _ => continue
        }
    }

}

fn parse_node(parser: &mut EventReader<BufReader<File>>, attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let node_attrs = try!(parse_node_attributes(&attrs));

    if let ElementData::NodeAttrs(id, lat, lon) = node_attrs {
        let mut tags = Vec::new();

        // Parse Node child elements, if any
        loop {
            match try!(parser.next()) {
                XmlEvent::EndElement { name } => {
                    let element_type = try!(ElementType::from_str(&name.local_name));

                    match element_type {
                        ElementType::Node => return Ok(ElementData::Node(id, lat, lon, tags)),
                        _ => continue
                    }
                },
                XmlEvent::StartElement { name, attributes, .. } => {
                    let element_type = try!(ElementType::from_str(&name.local_name));

                    match element_type {
                        ElementType::Tag => {
                            if let Some(tag) = parse_tag_attributes(&attributes) {
                                tags.push(tag);
                            }
                        },
                        // Malformed node containing illegal children, ignore whole Node
                        ElementType::Bounds |
                        ElementType::Node |
                        ElementType::Relation |
                        ElementType::Way |
                        ElementType::NodeRef => return Err(ErrorKind::MalformedElement)
                    }
                },
                _ => continue
            }
        }
    } else {
        Err(ErrorKind::MalformedElement)
    }
}

fn parse_tag_attributes(attributes: &Vec<OwnedAttribute>) -> Option<Tag> {
    let mut iter = attributes.iter();
    iter.find(|attr| attr.name.local_name == "k")
        .and_then(|attr| Some(attr.value.clone()))
        .and_then(|key| {
            iter.find(|attr| attr.name.local_name == "v")
            .and_then(|attr| Some(attr.value.clone()))
            .and_then(|val| Some(Tag { key: key, val: val }))
        })
}

fn parse_bounds(attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let minlat = try!(find_attribute("minlat", attrs).map_err(ErrorKind::BoundsMissing));
    let minlon = try!(find_attribute("minlon", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlat = try!(find_attribute("maxlat", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlon = try!(find_attribute("maxlon", attrs).map_err(ErrorKind::BoundsMissing));

    Ok(ElementData::Bounds(minlat, minlon, maxlat, maxlon))
}

fn parse_node_attributes(attrs: &Vec<OwnedAttribute>) -> Result<ElementData, ErrorKind> {
    let id = try!(find_attribute("id", attrs).map_err(ErrorKind::IdMissing));
    let lat = try!(find_attribute("lat", attrs).map_err(ErrorKind::CoordinateMissing));
    let lon = try!(find_attribute("lon", attrs).map_err(ErrorKind::CoordinateMissing));

    Ok(ElementData::NodeAttrs(id, lat, lon))
}

fn find_attribute<T>(name: &str, attrs: &Vec<OwnedAttribute>) -> Result<T, AttributeError>
    where AttributeError: std::convert::From<<T as std::str::FromStr>::Err>,
          T: FromStr
{
    let attr = attrs.iter().find(|attr| attr.name.local_name == name);
    match attr {
        Some(a) => {
            let val = try!(a.value.parse::<T>());
            Ok(val)
        },
        None => Err(AttributeError::Missing)
    }
}
<|endoftext|>


<commit_before>#![cfg(any(unix, windows))]

/// Allocates `size` Bytes aligned to `align` Bytes. Returns a null pointer on allocation failure.
///
/// The returned pointer must be deallocated by using `aligned_free`.
///
/// Note: This function is meant to be used for infrequent large allocations (as `malloc` already
/// guarantees suitable alignment for all native datatypes) and might be quite slow when used
/// heavily.
///
/// # Parameters
///
/// * `size`: The size of the allocation in bytes.
/// * `align`: The alignment of the allocation (at least the size of `usize` on the current
///   platform). Must also be a power of two.
#[inline]
pub fn aligned_alloc(size: usize, align: usize) -> *mut () {
    imp::aligned_alloc(size, align)
}

/// Deallocates aligned memory that was allocated with `aligned_alloc`. Unsafe because calling this
/// with a pointer that was not allocated with `aligned_alloc` (or already released) causes
/// undefined behavior.
#[inline]
pub unsafe fn aligned_free(ptr: *mut ()) {
    imp::aligned_free(ptr)
}

#[cfg(unix)]
mod imp {
    extern crate libc;

    use self::libc::{c_void, c_int, size_t, EINVAL, ENOMEM, free};

    use std::{mem, ptr};

    extern "C" {
        fn posix_memalign(memptr: *mut *mut c_void, alignment: size_t, size: size_t) -> c_int;
    }

    pub fn aligned_alloc(size: usize, align: usize) -> *mut () {
        let mut memptr: *mut c_void = ptr::null_mut();
        let result = unsafe { posix_memalign(&mut memptr, align as size_t, size as size_t) };
        match result {
            0 => return memptr as *mut (),
            EINVAL => {
                if align < mem::size_of::<usize>() {
                    panic!("EINVAL: invalid alignment: {} (minimum is {})", align,
                        mem::size_of::<usize>());
                }
                if !align.is_power_of_two() {
                    panic!("EINVAL: invalid alignment: {} (must be a power of two)", align)
                }
                panic!("EINVAL: invalid alignment: {}", align);
            }
            ENOMEM => return ptr::null_mut(),
            _ => unreachable!(),
        }
    }

    #[inline]
    pub unsafe fn aligned_free(ptr: *mut ()) {
        free(ptr as *mut c_void)
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32;

    use self::kernel32::{GetLastError, GetSystemInfo, VirtualAlloc, VirtualFree};
    use self::winapi::{MEM_COMMIT, MEM_RESERVE, MEM_RELEASE, PAGE_NOACCESS, PAGE_READWRITE, SIZE_T,
        LPVOID, DWORD, SYSTEM_INFO};

    use std::mem;
    use std::ptr;

    static mut PAGE_SIZE: DWORD = 0;

    #[cold]
    fn get_page_size() {
        let mut info: SYSTEM_INFO = unsafe { mem::uninitialized() };
        unsafe { GetSystemInfo(&mut info); }

        unsafe {
            PAGE_SIZE = info.dwPageSize;
        }
    }

    pub fn aligned_alloc(size: usize, align: usize) -> *mut () {
        assert!(align.is_power_of_two(), "align must be a power of two");

        if unsafe { PAGE_SIZE } == 0 { get_page_size() }

        unsafe {
            if align <= PAGE_SIZE as usize {
                // Page alignment is guaranteed by `VirtualAlloc`
                let ptr = VirtualAlloc(ptr::null_mut(), size as SIZE_T, MEM_COMMIT | MEM_RESERVE,
                    PAGE_READWRITE);
                return ptr as *mut ()
            }

            // Step 1: Reserve `size+align-1` Bytes of address space to find a suitable address
            let ptr = VirtualAlloc(ptr::null_mut(), (size + align - 1) as SIZE_T, MEM_RESERVE,
                PAGE_NOACCESS);
            if ptr.is_null() { return ptr::null_mut() }

            // Step 2: Calculate an aligned address within the reserved range
            // (this works because `align` must be a power of two)
            let aligned_ptr = (ptr as usize + align - 1) & !(align - 1);

            // Step 3: Actually allocate (commit) the memory
            let res = VirtualFree(ptr as LPVOID, 0, MEM_RELEASE);
            if res == 0 {
                panic!("WINAPI error {} while freeing reserved memory", GetLastError());
            }
            let ptr = VirtualAlloc(aligned_ptr as LPVOID, size as SIZE_T, MEM_COMMIT | MEM_RESERVE,
                PAGE_READWRITE);
            ptr as *mut ()
        }
    }

    pub unsafe fn aligned_free(ptr: *mut ()) {
        let res = VirtualFree(ptr as LPVOID, 0, MEM_RELEASE);
        if res == 0 {
            panic!("WINAPI error {} while releasing memory", GetLastError());
        }
    }
}

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

    #[test]
    fn small_low_align() {
        let ptr = aligned_alloc(1, 128);
        assert!(!ptr.is_null());
        assert!(ptr as usize % 128 == 0);
        unsafe { aligned_free(ptr) }
    }

    #[test]
    fn small_high_align() {
        let ptr = aligned_alloc(1, 1024 * 1024);
        assert!(!ptr.is_null());
        assert!(ptr as usize % (1024 * 1024) == 0);
        unsafe { aligned_free(ptr) }
    }

    #[test]
    fn large_high_align() {
        // allocate 1 MiB aligned to 1 MiB
        let ptr = aligned_alloc(1024 * 1024, 1024 * 1024);
        assert!(!ptr.is_null());
        assert!(ptr as usize % (1024 * 1024) == 0);
        unsafe { aligned_free(ptr) }
    }

    #[test]
    #[should_panic]
    fn align_less_than_sizeof_usize() {
        // alignment of less than sizeof(usize)
        aligned_alloc(1, 3);
    }

    #[test]
    #[should_panic]
    fn align_not_power_of_two() {
        aligned_alloc(1, 27);
    }

    #[test]
    #[should_panic]
    fn align_zero() {
        aligned_alloc(1, 0);
    }
}
<commit_msg>Correctly reject alignment < size_of::<usize><commit_after>#![cfg(any(unix, windows))]

/// Allocates `size` Bytes aligned to `align` Bytes. Returns a null pointer on allocation failure.
///
/// The returned pointer must be deallocated by using `aligned_free`.
///
/// Note: This function is meant to be used for infrequent large allocations (as `malloc` already
/// guarantees suitable alignment for all native datatypes) and might be quite slow when used
/// heavily.
///
/// # Parameters
///
/// * `size`: The size of the allocation in bytes.
/// * `align`: The alignment of the allocation (at least the size of `usize` on the current
///   platform). Must also be a power of two.
#[inline]
pub fn aligned_alloc(size: usize, align: usize) -> *mut () {
    imp::aligned_alloc(size, align)
}

/// Deallocates aligned memory that was allocated with `aligned_alloc`. Unsafe because calling this
/// with a pointer that was not allocated with `aligned_alloc` (or already released) causes
/// undefined behavior.
#[inline]
pub unsafe fn aligned_free(ptr: *mut ()) {
    imp::aligned_free(ptr)
}

#[cfg(unix)]
mod imp {
    extern crate libc;

    use self::libc::{c_void, c_int, size_t, EINVAL, ENOMEM, free};

    use std::{mem, ptr};

    extern "C" {
        fn posix_memalign(memptr: *mut *mut c_void, alignment: size_t, size: size_t) -> c_int;
    }

    pub fn aligned_alloc(size: usize, align: usize) -> *mut () {
        let mut memptr: *mut c_void = ptr::null_mut();
        let result = unsafe { posix_memalign(&mut memptr, align as size_t, size as size_t) };
        match result {
            0 => return memptr as *mut (),
            EINVAL => {
                if align < mem::size_of::<usize>() {
                    panic!("EINVAL: invalid alignment: {} (minimum is {})", align,
                        mem::size_of::<usize>());
                }
                if !align.is_power_of_two() {
                    panic!("EINVAL: invalid alignment: {} (must be a power of two)", align)
                }
                panic!("EINVAL: invalid alignment: {}", align);
            }
            ENOMEM => return ptr::null_mut(),
            _ => unreachable!(),
        }
    }

    #[inline]
    pub unsafe fn aligned_free(ptr: *mut ()) {
        free(ptr as *mut c_void)
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32;

    use self::kernel32::{GetLastError, GetSystemInfo, VirtualAlloc, VirtualFree};
    use self::winapi::{MEM_COMMIT, MEM_RESERVE, MEM_RELEASE, PAGE_NOACCESS, PAGE_READWRITE, SIZE_T,
        LPVOID, DWORD, SYSTEM_INFO};

    use std::mem;
    use std::ptr;

    static mut PAGE_SIZE: DWORD = 0;

    #[cold]
    fn get_page_size() {
        let mut info: SYSTEM_INFO = unsafe { mem::uninitialized() };
        unsafe { GetSystemInfo(&mut info); }

        unsafe {
            PAGE_SIZE = info.dwPageSize;
        }
    }

    pub fn aligned_alloc(size: usize, align: usize) -> *mut () {
        assert!(align.is_power_of_two(), "align must be a power of two");
        assert!(align >= mem::size_of::<usize>(), "align must be at least as large as a usize");

        if unsafe { PAGE_SIZE } == 0 { get_page_size() }

        unsafe {
            if align <= PAGE_SIZE as usize {
                // Page alignment is guaranteed by `VirtualAlloc`
                let ptr = VirtualAlloc(ptr::null_mut(), size as SIZE_T, MEM_COMMIT | MEM_RESERVE,
                    PAGE_READWRITE);
                return ptr as *mut ()
            }

            // Step 1: Reserve `size+align-1` Bytes of address space to find a suitable address
            let ptr = VirtualAlloc(ptr::null_mut(), (size + align - 1) as SIZE_T, MEM_RESERVE,
                PAGE_NOACCESS);
            if ptr.is_null() { return ptr::null_mut() }

            // Step 2: Calculate an aligned address within the reserved range
            // (this works because `align` must be a power of two)
            let aligned_ptr = (ptr as usize + align - 1) & !(align - 1);

            // Step 3: Actually allocate (commit) the memory
            let res = VirtualFree(ptr as LPVOID, 0, MEM_RELEASE);
            if res == 0 {
                panic!("WINAPI error {} while freeing reserved memory", GetLastError());
            }
            let ptr = VirtualAlloc(aligned_ptr as LPVOID, size as SIZE_T, MEM_COMMIT | MEM_RESERVE,
                PAGE_READWRITE);
            ptr as *mut ()
        }
    }

    pub unsafe fn aligned_free(ptr: *mut ()) {
        let res = VirtualFree(ptr as LPVOID, 0, MEM_RELEASE);
        if res == 0 {
            panic!("WINAPI error {} while releasing memory", GetLastError());
        }
    }
}

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

    #[test]
    fn small_low_align() {
        let ptr = aligned_alloc(1, 128);
        assert!(!ptr.is_null());
        assert!(ptr as usize % 128 == 0);
        unsafe { aligned_free(ptr) }
    }

    #[test]
    fn small_high_align() {
        let ptr = aligned_alloc(1, 1024 * 1024);
        assert!(!ptr.is_null());
        assert!(ptr as usize % (1024 * 1024) == 0);
        unsafe { aligned_free(ptr) }
    }

    #[test]
    fn large_high_align() {
        // allocate 1 MiB aligned to 1 MiB
        let ptr = aligned_alloc(1024 * 1024, 1024 * 1024);
        assert!(!ptr.is_null());
        assert!(ptr as usize % (1024 * 1024) == 0);
        unsafe { aligned_free(ptr) }
    }

    #[test]
    #[should_panic]
    fn align_less_than_sizeof_usize() {
        // alignment of less than sizeof(usize)
        aligned_alloc(1, 2);
    }

    #[test]
    #[should_panic]
    fn align_not_power_of_two() {
        aligned_alloc(1, 27);
    }

    #[test]
    #[should_panic]
    fn align_zero() {
        aligned_alloc(1, 0);
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(os)]
#![feature(fs)]
#![feature(std_misc)]
#![feature(unsafe_destructor)]

use std::fs::File;
use std::os::{MemoryMap, MapOption};
use std::os::unix::AsRawFd;
use std::mem;
use std::slice;
use std::marker;
use std::num::Int;

/**
 * Maps a file into memory and represents this memory
 * as a read-only Rust slice.
 */
pub struct MmapSlice<T:Sized> {
    /// Underlying file
    file: File,

    /// The mmap handle
    mmap: MemoryMap,

    /// Number of elements of type `T`
    nelems: usize,

    ///
    marker: marker::PhantomData<T>,
}

impl<T:Sized> MmapSlice<T> {
    /**
     * Creates a MmapSlice. Maps `nelems` of type `T`.
     */
    pub fn new(file: File, nelems: usize) -> Result<MmapSlice<T>, &'static str> {
        match nelems.checked_mul(mem::size_of::<T>()) {
            Some(map_len) => {
                match file.metadata() {
                    Ok(meta) => {
                        if map_len as u64 > meta.len() {
                            return Err("File too small to mmap")
                        }
                        let opts = [MapOption::MapReadable,
                                    MapOption::MapFd(file.as_raw_fd())];
                        match MemoryMap::new(map_len, &opts) {
                            Ok(map) => {
                                if map.len() > 0 && map.len() >= map_len {
                                    Ok(MmapSlice {
                                        file:   file,
                                        mmap:   map,
                                        nelems: nelems,
                                        marker: marker::PhantomData
                                    })
                                }
                                else {
                                    Err("Mmaped region too small")
                                }
                            }
                            Err(_) => {
                                Err("Mmap failed")
                            }
                        }
                    }
                    Err(_) => {
                        Err("Failed to stat file")
                    }
                }
            }
            None => {
                Err("Size overflow")
            }
        }
    }
}

impl<T:Sized> AsSlice<T> for MmapSlice<T> {
    fn as_slice<'a>(&'a self) -> &'a [T] {
         unsafe {
             slice::from_raw_parts(self.mmap.data() as *const T, self.nelems)
         }
    }
}

// FIXME: Do we really need our custom Drop?
#[unsafe_destructor]
impl<T:Sized> Drop for MmapSlice<T> {
    fn drop(&mut self) {
        drop(&mut self.mmap);
        drop(&mut self.file);
    }
}
<commit_msg>Return io::Result instead of std::result::Result<commit_after>#![feature(core, os, fs, std_misc, unsafe_destructor, io)]

use std::fs::File;
use std::os::{MemoryMap, MapOption};
use std::os::unix::AsRawFd;
use std::mem;
use std::slice;
use std::marker;
use std::num::Int;
use std::io::{Result, Error, ErrorKind};

/**
 * Maps a file into memory and represents this memory
 * as a read-only Rust slice.
 */
pub struct MmapSlice<T:Sized> {
    /// Underlying file
    file: File,

    /// The mmap handle
    mmap: MemoryMap,

    /// Number of elements of type `T`
    nelems: usize,

    ///
    marker: marker::PhantomData<T>,
}

fn other_io_error(description: &'static str) -> Error {
    Error::new(ErrorKind::Other, description, None)
}

impl<T:Sized> MmapSlice<T> {
    /**
     * Creates a MmapSlice. Maps `nelems` of type `T`.
     */
    pub fn new(file: File, nelems: usize) -> Result<MmapSlice<T>> {
        match nelems.checked_mul(mem::size_of::<T>()) {
            Some(map_len) => {
                let meta = try!(file.metadata());
                if map_len as u64 > meta.len() {
                    return Err(other_io_error("File too small to mmap"))
                }
                let opts = [MapOption::MapReadable,
                            MapOption::MapFd(file.as_raw_fd())];
                let map = try!(MemoryMap::new(map_len, &opts).map_err(|_| other_io_error("Mmap error")));
                if map.len() > 0 && map.len() >= map_len {
                    Ok(MmapSlice {
                        file:   file,
                        mmap:   map,
                        nelems: nelems,
                        marker: marker::PhantomData
                    })
                }
                else {
                    Err(other_io_error("Mmaped region too small"))
                }
            }
            None => {
                Err(other_io_error("Size overflow"))
            }
        }
    }
}

impl<T:Sized> AsSlice<T> for MmapSlice<T> {
    fn as_slice<'a>(&'a self) -> &'a [T] {
         unsafe {
             slice::from_raw_parts(self.mmap.data() as *const T, self.nelems)
         }
    }
}

// FIXME: Do we really need our custom Drop?
#[unsafe_destructor]
impl<T:Sized> Drop for MmapSlice<T> {
    fn drop(&mut self) {
        drop(&mut self.mmap);
        drop(&mut self.file);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate mopa;
extern crate pulse;
extern crate threadpool;
extern crate fnv;

use std::any::TypeId;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use mopa::Any;
use pulse::{Pulse, Signal};
use threadpool::ThreadPool;

pub use storage::{Storage, StorageBase, VecStorage, HashMapStorage};

mod storage;

/// Index generation. When a new entity is placed at the old index,
/// it bumps the generation by 1. This allows to avoid using components
/// from the entities that were deleted.
/// G<=0 - the entity of generation G is dead
/// G >0 - the entity of generation G is alive
pub type Generation = i32;
/// Index type is arbitrary. It doesn't show up in any interfaces.
/// Keeping it 32bit allows for a single 64bit word per entity.
pub type Index = u32;
/// Entity type, as seen by the user.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Entity(Index, Generation);

impl Entity {
    #[cfg(test)]
    /// Create a new entity (externally from ECS)
    pub fn new(index: u32, gen: i32) -> Entity {
        Entity(index, gen)
    }

    /// Get the index of the entity.
    pub fn get_id(&self) -> usize { self.0 as usize }
    /// Get the generation of the entity.
    pub fn get_gen(&self) -> Generation { self.1 }
}

/// A custom entity iterator. Needed because the world doesn't really store
/// entities directly, but rather has just a vector of Index -> Generation.
pub struct EntityIter<'a> {
    guard: RwLockReadGuard<'a, Vec<Generation>>,
    index: usize,
}

impl<'a> Iterator for EntityIter<'a> {
    type Item = Entity;
    fn next(&mut self) -> Option<Entity> {
        loop {
            match self.guard.get(self.index) {
                Some(&gen) if gen > 0 => {
                    let ent = Entity(self.index as Index, gen);
                    self.index += 1;
                    return Some(ent)
                },
                Some(_) => self.index += 1, // continue
                None => return None,
            }
        }
    }
}

/// Abstract component type. Doesn't have to be Copy or even Clone.
pub trait Component: Any + Sized {
    type Storage: Storage<Self> + Any + Send + Sync;
}

trait StorageLock: Any + Send + Sync {
    fn del_slice(&self, &[Entity]);
}

mopafy!(StorageLock);

impl<S: StorageBase + Any + Send + Sync> StorageLock for RwLock<S> {
    fn del_slice(&self, entities: &[Entity]) {
        let mut guard = self.write().unwrap();
        for &e in entities.iter() {
            guard.del(e);
        }
    }
}

/// The world struct contains all the data, which is entities and their components.
/// The methods are supposed to be valid for any context they are available in.
pub struct World {
    generations: RwLock<Vec<Generation>>,
    components: HashMap<TypeId, Box<StorageLock>>,
}

impl World {
    /// Create a new empty world.
    pub fn new() -> World {
        World {
            generations: RwLock::new(Vec::new()),
            components: HashMap::new(),
        }
    }
    /// Register a new component type.
    pub fn register<T: Component>(&mut self) {
        let any = RwLock::new(T::Storage::new());
        self.components.insert(TypeId::of::<T>(), Box::new(any));
    }
    /// Unregister a component type.
    pub fn unregister<T: Component>(&mut self) -> Option<T::Storage> {
        self.components.remove(&TypeId::of::<T>()).map(|boxed|
            match boxed.downcast::<RwLock<T::Storage>>() {
                Ok(b) => (*b).into_inner().unwrap(),
                Err(_) => panic!("Unable to downcast the storage type"),
            }
        )
    }
    fn lock<T: Component>(&self) -> &RwLock<T::Storage> {
        let boxed = self.components.get(&TypeId::of::<T>()).unwrap();
        boxed.downcast_ref().unwrap()
    }
    /// Lock a component for reading.
    pub fn read<'a, T: Component>(&'a self) -> RwLockReadGuard<'a, T::Storage> {
        self.lock::<T>().read().unwrap()
    }
    /// Lock a component for writing.
    pub fn write<'a, T: Component>(&'a self) -> RwLockWriteGuard<'a, T::Storage> {
        self.lock::<T>().write().unwrap()
    }
    /// Return the entity iterator.
    pub fn entities<'a>(&'a self) -> EntityIter<'a> {
        EntityIter {
            guard: self.generations.read().unwrap(),
            index: 0,
        }
    }
    fn find_next(&self, base: usize) -> Entity {
        let gens = self.generations.read().unwrap();
        match gens.iter().enumerate().skip(base).find(|&(_, g)| *g <= 0) {
            Some((id, gen)) => Entity(id as Index, 1 - gen),
            None => Entity(gens.len() as Index, 1),
        }
    }
    /// Return the generations array locked for reading. Useful for debugging.
    pub fn get_generations<'a>(&'a self) -> RwLockReadGuard<'a, Vec<Generation>> {
        self.generations.read().unwrap()
    }
}

struct Appendix {
    next: Entity,
    add_queue: Vec<Entity>,
    sub_queue: Vec<Entity>
}

/// A custom entity iterator for dynamically added entities.
pub struct NewEntityIter<'a> {
    guard: RwLockReadGuard<'a, Appendix>,
    index: usize,
}

impl<'a> Iterator for NewEntityIter<'a> {
    type Item = Entity;
    fn next(&mut self) -> Option<Entity> {
        let ent = self.guard.add_queue.get(self.index);
        self.index += 1;
        ent.map(|e| *e)
    }
}

/// World argument for a system closure.
pub struct WorldArg {
    world: Arc<World>,
    pulse: RefCell<Option<Pulse>>,
    app: Arc<RwLock<Appendix>>,
}

impl WorldArg {
    /// Borrows the world, allowing the system lock some components and get the entity
    /// iterator. Has to be called only once. Fires a pulse at the end.
    pub fn fetch<'a, U, F>(&'a self, f: F) -> U
        where F: FnOnce(&'a World) -> U
    {
        let pulse = self.pulse.borrow_mut().take()
                        .expect("fetch may only be called once.");
        let u = f(&self.world);
        pulse.pulse();
        u
    }
    /// Create a new entity dynamically.
    pub fn create(&self) -> Entity {
        let mut app = self.app.write().unwrap();
        let ent = app.next;
        app.add_queue.push(ent);
        app.next = self.world.find_next(ent.get_id() + 1);
        ent
    }
    /// Delete an entity dynamically.
    pub fn delete(&self, entity: Entity) {
        let mut app = self.app.write().unwrap();
        app.sub_queue.push(entity);
    }
    /// Iterate dynamically added entities.
    pub fn new_entities<'a>(&'a self) -> NewEntityIter<'a> {
        NewEntityIter {
            guard: self.app.read().unwrap(),
            index: 0,
        }
    }
}

/// Helper builder for entities.
pub struct EntityBuilder<'a>(Entity, &'a World);

impl<'a> EntityBuilder<'a> {
    /// Add a component value to the new entity.
    pub fn with<T: Component>(self, value: T) -> EntityBuilder<'a> {
        self.1.write::<T>().insert(self.0, value);
        self
    }
    /// Finish entity construction.
    pub fn build(self) -> Entity {
        self.0
    }
}

pub struct Scheduler {
    world: Arc<World>,
    threads: ThreadPool,
    appendix: Arc<RwLock<Appendix>>,
}

impl Scheduler {
    pub fn new(world: World, num_threads: usize) -> Scheduler {
        let next = Appendix {
            next: world.find_next(0),
            add_queue: Vec::new(),
            sub_queue: Vec::new(),
        };
        Scheduler {
            world: Arc::new(world),
            threads: ThreadPool::new(num_threads),
            appendix: Arc::new(RwLock::new(next)),
        }
    }
    pub fn get_world(&self) -> &World {
        &self.world
    }
    pub fn run<F>(&mut self, functor: F) where
        F: 'static + Send + FnOnce(WorldArg)
    {
        let (signal, pulse) = Signal::new();
        let world = self.world.clone();
        let app = self.appendix.clone();
        self.threads.execute(|| {
            functor(WorldArg {
                world: world,
                pulse: RefCell::new(Some(pulse)),
                app: app,
            });
        });
        signal.wait().unwrap();
    }
    pub fn add_entity<'a>(&'a mut self) -> EntityBuilder<'a> {
        let mut appendix = self.appendix.write().unwrap();
        let ent = appendix.next;
        assert!(ent.get_gen() > 0);
        if ent.get_gen() == 1 {
            let mut gens = self.world.generations.write().unwrap();
            assert!(gens.len() == ent.get_id());
            gens.push(ent.get_gen());
        }
        appendix.next = self.world.find_next(ent.get_id() + 1);
        EntityBuilder(ent, &self.world)
    }
    pub fn del_entity(&mut self, entity: Entity) {
        for boxed in self.world.components.values() {
            boxed.del_slice(&[entity]);
        }
        let mut gens = self.world.generations.write().unwrap();
        let mut gen = &mut gens[entity.get_id() as usize];
        assert!(*gen > 0);
        let mut appendix = self.appendix.write().unwrap();
        if entity.get_id() < appendix.next.get_id() {
            appendix.next = Entity(entity.0, *gen+1);
        }
        *gen *= -1;
    }
    pub fn rest(&self) {
        let mut gens = self.world.generations.write().unwrap();
        let mut app = self.appendix.write().unwrap();
        for ent in app.add_queue.drain(..) {
            while gens.len() <= ent.get_id() {
                gens.push(0);
            }
            assert_eq!(ent.get_gen(), 1 - gens[ent.get_id()]);
            gens[ent.get_id()] = ent.get_gen();
        }
        let mut next = app.next;
        for ent in app.sub_queue.drain(..) {
            assert_eq!(ent.get_gen(), gens[ent.get_id()]);
            if ent.get_id() < next.get_id() {
                next = Entity(ent.0, ent.1 + 1);
            }
            gens[ent.get_id()] *= -1;
        }
        app.next = next;
    }
}

macro_rules! impl_run {
    ($name:ident [$( $write:ident ),*] [$( $read:ident ),*]) => (impl Scheduler {
        #[allow(non_snake_case, unused_mut)]
        pub fn $name<
            $($write:Component,)* $($read:Component,)*
            F: 'static + Send + FnMut( $(&mut $write,)* $(&$read,)* )
        >(&mut self, functor: F) {
            self.run(|warg| {
                let mut fun = functor;
                let ($(mut $write,)* $($read,)* entities) = warg.fetch(|w|
                    ($(w.write::<$write>(),)*
                     $(w.read::<$read>(),)*
                       w.entities())
                );
                for ent in entities {
                    if let ( $( Some($write), )* $( Some($read), )* ) =
                        ( $( $write.get_mut(ent), )* $( $read.get(ent), )* ) {
                        fun( $($write,)* $($read,)* );
                    }
                }
                for ent in warg.new_entities() {
                    if let ( $( Some($write), )* $( Some($read), )* ) =
                        ( $( $write.get_mut(ent), )* $( $read.get(ent), )* ) {
                        fun( $($write,)* $($read,)* );
                    }
                }
            });
        }
    })
}

impl_run!( run0w1r [] [R0] );
impl_run!( run0w2r [] [R0, R1] );
impl_run!( run1w0r [W0] [] );
impl_run!( run1w1r [W0] [R0] );
impl_run!( run1w2r [W0] [R0, R1] );
impl_run!( run1w3r [W0] [R0, R1, R2] );
impl_run!( run1w4r [W0] [R0, R1, R2, R3] );
impl_run!( run1w5r [W0] [R0, R1, R2, R3, R4] );
impl_run!( run1w6r [W0] [R0, R1, R2, R3, R4, R5] );
impl_run!( run1w7r [W0] [R0, R1, R2, R3, R5, R6, R7] );
impl_run!( run2w0r [W0, W1] [] );
impl_run!( run2w1r [W0, W1] [R0] );
impl_run!( run2w2r [W0, W1] [R0, R1] );
<commit_msg>Moved Appendix into the World<commit_after>#[macro_use]
extern crate mopa;
extern crate pulse;
extern crate threadpool;
extern crate fnv;

use std::any::TypeId;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use mopa::Any;
use pulse::{Pulse, Signal};
use threadpool::ThreadPool;

pub use storage::{Storage, StorageBase, VecStorage, HashMapStorage};

mod storage;

/// Index generation. When a new entity is placed at the old index,
/// it bumps the generation by 1. This allows to avoid using components
/// from the entities that were deleted.
/// G<=0 - the entity of generation G is dead
/// G >0 - the entity of generation G is alive
pub type Generation = i32;
/// Index type is arbitrary. It doesn't show up in any interfaces.
/// Keeping it 32bit allows for a single 64bit word per entity.
pub type Index = u32;
/// Entity type, as seen by the user.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Entity(Index, Generation);

impl Entity {
    #[cfg(test)]
    /// Create a new entity (externally from ECS)
    pub fn new(index: u32, gen: i32) -> Entity {
        Entity(index, gen)
    }

    /// Get the index of the entity.
    pub fn get_id(&self) -> usize { self.0 as usize }
    /// Get the generation of the entity.
    pub fn get_gen(&self) -> Generation { self.1 }
}

/// A custom entity iterator. Needed because the world doesn't really store
/// entities directly, but rather has just a vector of Index -> Generation.
pub struct EntityIter<'a> {
    guard: RwLockReadGuard<'a, Vec<Generation>>,
    index: usize,
}

impl<'a> Iterator for EntityIter<'a> {
    type Item = Entity;
    fn next(&mut self) -> Option<Entity> {
        loop {
            match self.guard.get(self.index) {
                Some(&gen) if gen > 0 => {
                    let ent = Entity(self.index as Index, gen);
                    self.index += 1;
                    return Some(ent)
                },
                Some(_) => self.index += 1, // continue
                None => return None,
            }
        }
    }
}

/// Abstract component type. Doesn't have to be Copy or even Clone.
pub trait Component: Any + Sized {
    type Storage: Storage<Self> + Any + Send + Sync;
}

trait StorageLock: Any + Send + Sync {
    fn del_slice(&self, &[Entity]);
}

mopafy!(StorageLock);

impl<S: StorageBase + Any + Send + Sync> StorageLock for RwLock<S> {
    fn del_slice(&self, entities: &[Entity]) {
        let mut guard = self.write().unwrap();
        for &e in entities.iter() {
            guard.del(e);
        }
    }
}

struct Appendix {
    next: Entity,
    add_queue: Vec<Entity>,
    sub_queue: Vec<Entity>
}

/// The world struct contains all the data, which is entities and their components.
/// The methods are supposed to be valid for any context they are available in.
pub struct World {
    generations: RwLock<Vec<Generation>>,
    components: HashMap<TypeId, Box<StorageLock>>,
    appendix: RwLock<Appendix>,
}

impl World {
    /// Create a new empty world.
    pub fn new() -> World {
        World {
            generations: RwLock::new(Vec::new()),
            components: HashMap::new(),
            appendix: RwLock::new(Appendix {
                next: Entity(0, 1),
                add_queue: Vec::new(),
                sub_queue: Vec::new(),
            }),
        }
    }
    /// Register a new component type.
    pub fn register<T: Component>(&mut self) {
        let any = RwLock::new(T::Storage::new());
        self.components.insert(TypeId::of::<T>(), Box::new(any));
    }
    /// Unregister a component type.
    pub fn unregister<T: Component>(&mut self) -> Option<T::Storage> {
        self.components.remove(&TypeId::of::<T>()).map(|boxed|
            match boxed.downcast::<RwLock<T::Storage>>() {
                Ok(b) => (*b).into_inner().unwrap(),
                Err(_) => panic!("Unable to downcast the storage type"),
            }
        )
    }
    fn lock<T: Component>(&self) -> &RwLock<T::Storage> {
        let boxed = self.components.get(&TypeId::of::<T>()).unwrap();
        boxed.downcast_ref().unwrap()
    }
    /// Lock a component for reading.
    pub fn read<'a, T: Component>(&'a self) -> RwLockReadGuard<'a, T::Storage> {
        self.lock::<T>().read().unwrap()
    }
    /// Lock a component for writing.
    pub fn write<'a, T: Component>(&'a self) -> RwLockWriteGuard<'a, T::Storage> {
        self.lock::<T>().write().unwrap()
    }
    /// Return the entity iterator.
    pub fn entities<'a>(&'a self) -> EntityIter<'a> {
        EntityIter {
            guard: self.generations.read().unwrap(),
            index: 0,
        }
    }
    fn find_next(&self, base: usize) -> Entity {
        let gens = self.generations.read().unwrap();
        match gens.iter().enumerate().skip(base).find(|&(_, g)| *g <= 0) {
            Some((id, gen)) => Entity(id as Index, 1 - gen),
            None => Entity(gens.len() as Index, 1),
        }
    }
    /// Return the generations array locked for reading. Useful for debugging.
    pub fn get_generations<'a>(&'a self) -> RwLockReadGuard<'a, Vec<Generation>> {
        self.generations.read().unwrap()
    }
}

/// A custom entity iterator for dynamically added entities.
pub struct NewEntityIter<'a> {
    guard: RwLockReadGuard<'a, Appendix>,
    index: usize,
}

impl<'a> Iterator for NewEntityIter<'a> {
    type Item = Entity;
    fn next(&mut self) -> Option<Entity> {
        let ent = self.guard.add_queue.get(self.index);
        self.index += 1;
        ent.map(|e| *e)
    }
}

/// World argument for a system closure.
pub struct WorldArg {
    world: Arc<World>,
    pulse: RefCell<Option<Pulse>>,
}

impl WorldArg {
    /// Borrows the world, allowing the system lock some components and get the entity
    /// iterator. Has to be called only once. Fires a pulse at the end.
    pub fn fetch<'a, U, F>(&'a self, f: F) -> U
        where F: FnOnce(&'a World) -> U
    {
        let pulse = self.pulse.borrow_mut().take()
                        .expect("fetch may only be called once.");
        let u = f(&self.world);
        pulse.pulse();
        u
    }
    /// Create a new entity dynamically.
    pub fn create(&self) -> Entity {
        let mut app = self.world.appendix.write().unwrap();
        let ent = app.next;
        app.add_queue.push(ent);
        app.next = self.world.find_next(ent.get_id() + 1);
        ent
    }
    /// Delete an entity dynamically.
    pub fn delete(&self, entity: Entity) {
        let mut app = self.world.appendix.write().unwrap();
        app.sub_queue.push(entity);
    }
    /// Iterate dynamically added entities.
    pub fn new_entities<'a>(&'a self) -> NewEntityIter<'a> {
        NewEntityIter {
            guard: self.world.appendix.read().unwrap(),
            index: 0,
        }
    }
}

/// Helper builder for entities.
pub struct EntityBuilder<'a>(Entity, &'a World);

impl<'a> EntityBuilder<'a> {
    /// Add a component value to the new entity.
    pub fn with<T: Component>(self, value: T) -> EntityBuilder<'a> {
        self.1.write::<T>().insert(self.0, value);
        self
    }
    /// Finish entity construction.
    pub fn build(self) -> Entity {
        self.0
    }
}

pub struct Scheduler {
    world: Arc<World>,
    threads: ThreadPool,
}

impl Scheduler {
    pub fn new(world: World, num_threads: usize) -> Scheduler {
        Scheduler {
            world: Arc::new(world),
            threads: ThreadPool::new(num_threads),
        }
    }
    pub fn get_world(&self) -> &World {
        &self.world
    }
    pub fn run<F>(&mut self, functor: F) where
        F: 'static + Send + FnOnce(WorldArg)
    {
        let (signal, pulse) = Signal::new();
        let world = self.world.clone();
        self.threads.execute(|| {
            functor(WorldArg {
                world: world,
                pulse: RefCell::new(Some(pulse)),
            });
        });
        signal.wait().unwrap();
    }
    pub fn add_entity<'a>(&'a mut self) -> EntityBuilder<'a> {
        let mut appendix = self.world.appendix.write().unwrap();
        let ent = appendix.next;
        assert!(ent.get_gen() > 0);
        if ent.get_gen() == 1 {
            let mut gens = self.world.generations.write().unwrap();
            assert!(gens.len() == ent.get_id());
            gens.push(ent.get_gen());
        }
        appendix.next = self.world.find_next(ent.get_id() + 1);
        EntityBuilder(ent, &self.world)
    }
    pub fn del_entity(&mut self, entity: Entity) {
        for boxed in self.world.components.values() {
            boxed.del_slice(&[entity]);
        }
        let mut gens = self.world.generations.write().unwrap();
        let mut gen = &mut gens[entity.get_id() as usize];
        assert!(*gen > 0);
        let mut app = self.world.appendix.write().unwrap();
        if entity.get_id() < app.next.get_id() {
            app.next = Entity(entity.0, *gen+1);
        }
        *gen *= -1;
    }
    pub fn rest(&self) {
        let mut gens = self.world.generations.write().unwrap();
        let mut app = self.world.appendix.write().unwrap();
        for ent in app.add_queue.drain(..) {
            while gens.len() <= ent.get_id() {
                gens.push(0);
            }
            assert_eq!(ent.get_gen(), 1 - gens[ent.get_id()]);
            gens[ent.get_id()] = ent.get_gen();
        }
        let mut next = app.next;
        for ent in app.sub_queue.drain(..) {
            assert_eq!(ent.get_gen(), gens[ent.get_id()]);
            if ent.get_id() < next.get_id() {
                next = Entity(ent.0, ent.1 + 1);
            }
            gens[ent.get_id()] *= -1;
        }
        app.next = next;
    }
}

macro_rules! impl_run {
    ($name:ident [$( $write:ident ),*] [$( $read:ident ),*]) => (impl Scheduler {
        #[allow(non_snake_case, unused_mut)]
        pub fn $name<
            $($write:Component,)* $($read:Component,)*
            F: 'static + Send + FnMut( $(&mut $write,)* $(&$read,)* )
        >(&mut self, functor: F) {
            self.run(|warg| {
                let mut fun = functor;
                let ($(mut $write,)* $($read,)* entities) = warg.fetch(|w|
                    ($(w.write::<$write>(),)*
                     $(w.read::<$read>(),)*
                       w.entities())
                );
                for ent in entities {
                    if let ( $( Some($write), )* $( Some($read), )* ) =
                        ( $( $write.get_mut(ent), )* $( $read.get(ent), )* ) {
                        fun( $($write,)* $($read,)* );
                    }
                }
                for ent in warg.new_entities() {
                    if let ( $( Some($write), )* $( Some($read), )* ) =
                        ( $( $write.get_mut(ent), )* $( $read.get(ent), )* ) {
                        fun( $($write,)* $($read,)* );
                    }
                }
            });
        }
    })
}

impl_run!( run0w1r [] [R0] );
impl_run!( run0w2r [] [R0, R1] );
impl_run!( run1w0r [W0] [] );
impl_run!( run1w1r [W0] [R0] );
impl_run!( run1w2r [W0] [R0, R1] );
impl_run!( run1w3r [W0] [R0, R1, R2] );
impl_run!( run1w4r [W0] [R0, R1, R2, R3] );
impl_run!( run1w5r [W0] [R0, R1, R2, R3, R4] );
impl_run!( run1w6r [W0] [R0, R1, R2, R3, R4, R5] );
impl_run!( run1w7r [W0] [R0, R1, R2, R3, R5, R6, R7] );
impl_run!( run2w0r [W0, W1] [] );
impl_run!( run2w1r [W0, W1] [R0] );
impl_run!( run2w2r [W0, W1] [R0, R1] );
<|endoftext|>


<commit_before>#![feature(plugin_registrar, macro_rules)]
#![crate_type = "dylib"]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap::{Span};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, DummyResult};
use rustc::plugin::Registry;

enum Severity {
    Note,
    Warning,
    Error,
    Fatal,
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    macro_rules! register_specifics {
        ($($name: expr => $sev: ident),*) => {
            {
                $(
                    reg.register_macro($name, {
                        fn f(cx: &mut ExtCtxt, sp: Span,
                             args: &[ast::TokenTree]) -> Box<base::MacResult+'static> {
                            expand_msg($sev, cx, sp, args)
                        }
                        f
                    });
                    )*
            }
        }
    }

    register_specifics! {
        "compile_note" => Note,
        "compile_warning" => Warning,
        "compile_error" => Error,
        "compile_fatal" => Fatal
    }
}

fn expand_msg(sev: Severity,
              cx: &mut ExtCtxt, sp: Span, args: &[ast::TokenTree]) -> Box<base::MacResult+'static> {
    // copied from syntax::ext::concat.
    let es = match base::get_exprs_from_tts(cx, sp, args) {
        Some(e) => e,
        None => return base::DummyResult::expr(sp)
    };
    let mut accumulator = String::new();
    for e in es.move_iter() {
        match e.node {
            ast::ExprLit(lit) => {
                match lit.node {
                    ast::LitStr(ref s, _) |
                    ast::LitFloat(ref s, _) |
                    ast::LitFloatUnsuffixed(ref s) => {
                        accumulator.push_str(s.get());
                    }
                    ast::LitChar(c) => {
                        accumulator.push_char(c);
                    }
                    ast::LitInt(i, ast::UnsignedIntLit(_)) |
                    ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) |
                    ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => {
                        accumulator.push_str(format!("{}", i).as_slice());
                    }
                    ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) |
                    ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => {
                        accumulator.push_str(format!("-{}", i).as_slice());
                    }
                    ast::LitNil => {}
                    ast::LitBool(b) => {
                        accumulator.push_str(format!("{}", b).as_slice());
                    }
                    ast::LitByte(..) |
                    ast::LitBinary(..) => {
                        cx.span_err(e.span, "cannot concatenate a binary literal");
                    }
                }
            }
            _ => {
                cx.span_err(e.span, "expected a literal");
            }
        }
    }

    macro_rules! emit {
        ($($sev: ident => $method: ident),*) => {
            match sev {
                $($sev => cx.$method(sp, accumulator.as_slice()),)*
            }
        }
    }
    emit! {
        Note => span_note,
        Warning => span_warn,
        Error => span_err,
        Fatal => span_fatal
    }

    DummyResult::any(sp)
}
<commit_msg>Update for 21d1f4d7c 2014-09-14 10:36:08 +0000<commit_after>#![feature(plugin_registrar, macro_rules)]
#![crate_type = "dylib"]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap::{Span};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, DummyResult};
use rustc::plugin::Registry;

enum Severity {
    Note,
    Warning,
    Error,
    Fatal,
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    macro_rules! register_specifics {
        ($($name: expr => $sev: ident),*) => {
            {
                $(
                    reg.register_macro($name, {
                        fn f(cx: &mut ExtCtxt, sp: Span,
                             args: &[ast::TokenTree]) -> Box<base::MacResult+'static> {
                            expand_msg($sev, cx, sp, args)
                        }
                        f
                    });
                    )*
            }
        }
    }

    register_specifics! {
        "compile_note" => Note,
        "compile_warning" => Warning,
        "compile_error" => Error,
        "compile_fatal" => Fatal
    }
}

fn expand_msg(sev: Severity,
              cx: &mut ExtCtxt, sp: Span, args: &[ast::TokenTree]) -> Box<base::MacResult+'static> {
    // copied from syntax::ext::concat.
    let es = match base::get_exprs_from_tts(cx, sp, args) {
        Some(e) => e,
        None => return base::DummyResult::expr(sp)
    };
    let mut accumulator = String::new();
    for e in es.move_iter() {
        match e.node {
            ast::ExprLit(ref lit) => {
                match lit.node {
                    ast::LitStr(ref s, _) |
                    ast::LitFloat(ref s, _) |
                    ast::LitFloatUnsuffixed(ref s) => {
                        accumulator.push_str(s.get());
                    }
                    ast::LitChar(c) => {
                        accumulator.push_char(c);
                    }
                    ast::LitInt(i, ast::UnsignedIntLit(_)) |
                    ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) |
                    ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => {
                        accumulator.push_str(format!("{}", i).as_slice());
                    }
                    ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) |
                    ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => {
                        accumulator.push_str(format!("-{}", i).as_slice());
                    }
                    ast::LitNil => {}
                    ast::LitBool(b) => {
                        accumulator.push_str(format!("{}", b).as_slice());
                    }
                    ast::LitByte(..) |
                    ast::LitBinary(..) => {
                        cx.span_err(e.span, "cannot concatenate a binary literal");
                    }
                }
            }
            _ => {
                cx.span_err(e.span, "expected a literal");
            }
        }
    }

    macro_rules! emit {
        ($($sev: ident => $method: ident),*) => {
            match sev {
                $($sev => cx.$method(sp, accumulator.as_slice()),)*
            }
        }
    }
    emit! {
        Note => span_note,
        Warning => span_warn,
        Error => span_err,
        Fatal => span_fatal
    }

    DummyResult::any(sp)
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]
//! [TIS-100.superoptimizer](https://github.com/dvberkel/TIS-100.superoptimizer) is a
//!
//! > Supertoptimization for TIS-100 game
//!
//! ## Goal
//! This project contains code that attempts to super-optimize certain
//! programming tasks for TIS-100.
//!
//! ### TIS-100
//! Developed by [Zachary Barth](https://en.wikipedia.org/wiki/Zachary_Barth)
//! under the banner of [Zachtronics Industries](http://www.zachtronics.com/),
//! [TIS-100](http://www.zachtronics.com/tis-100/) is a
//!
//! > open-ended programming game in which you rewrite corrupted code segments to
//! > repair the TIS-100 and unlock its secrets. It’s the assembly language
//! > programming game you never asked for!
//!
//! ### Super-optimization
//! Wikipedia defines
//! [super-optimization](https://en.wikipedia.org/wiki/Superoptimization) as
//!
//! > Superoptimization is the task of finding the optimal code sequence for a
//! > single, loop-free sequence of instructions

#[allow(non_snake_case)]
mod TIS_100;
<commit_msg>Make TIS-100 module public<commit_after>#![warn(missing_docs)]
//! [TIS-100.superoptimizer](https://github.com/dvberkel/TIS-100.superoptimizer) is a
//!
//! > Supertoptimization for TIS-100 game
//!
//! ## Goal
//! This project contains code that attempts to super-optimize certain
//! programming tasks for TIS-100.
//!
//! ### TIS-100
//! Developed by [Zachary Barth](https://en.wikipedia.org/wiki/Zachary_Barth)
//! under the banner of [Zachtronics Industries](http://www.zachtronics.com/),
//! [TIS-100](http://www.zachtronics.com/tis-100/) is a
//!
//! > open-ended programming game in which you rewrite corrupted code segments to
//! > repair the TIS-100 and unlock its secrets. It’s the assembly language
//! > programming game you never asked for!
//!
//! ### Super-optimization
//! Wikipedia defines
//! [super-optimization](https://en.wikipedia.org/wiki/Superoptimization) as
//!
//! > Superoptimization is the task of finding the optimal code sequence for a
//! > single, loop-free sequence of instructions

#[allow(non_snake_case)]
pub mod TIS_100;
<|endoftext|>


<commit_before>#![feature(core, std_misc)]
use std::thread::Thread;

/// Execute `f` on each element of `iter`, in their own `scoped`
/// thread.
///
/// If `f` panics, so does `for_`. If this occurs, the number of
/// elements of `iter` that have for executed is unspecified.
pub fn for_<I: Iterator, F>(iter: I, ref f: F)
    where I::Item: Send, F: Fn(I::Item) + Sync
{
    let _guards: Vec<_> = iter.map(|elem| {
        Thread::scoped(move || {
            f(elem)
        })
    }).collect();
}
<commit_msg>Adjust `for_` docs.<commit_after>#![feature(core, std_misc)]
use std::thread::Thread;

/// Execute `f` on each element of `iter`, in their own `scoped`
/// thread.
///
/// If `f` panics, so does `for_`. If this occurs, the number of
/// elements of `iter` that have had `f` called on them is
/// unspecified.
pub fn for_<I: Iterator, F>(iter: I, ref f: F)
    where I::Item: Send, F: Fn(I::Item) + Sync
{
    let _guards: Vec<_> = iter.map(|elem| {
        Thread::scoped(move || {
            f(elem)
        })
    }).collect();
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, stmt_expr_attributes)]
#![plugin(serde_macros, clippy)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces, unused_qualifications,
        warnings, clippy)]

//! Serializes and psudo-deserializes structs implementing the Error trait. This should only be done if you know you won't ever need an actual error value, only the description and causes.
//!
//! This crate assumes that the error descriptions are complete, and are indicative of the error going on.
//! There is also no way to get any values accoated with the error, since that would require real serialization of arbratrary structs, implementing a trait you didn't make.
//!
//! #Examples
//!
//! ```
//! use std::convert::From;
//! use std::fmt::Error;
//! use errorser::serialize_error_string;
//!
//! let error = Error;
//! let errser = serialize_error_string(&error);
//! assert_eq!(errser, "???");
//! ```

extern crate bincode;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;

mod real_error_impls;

use std::convert::{From, AsRef};
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};

use bincode::SizeLimit;
use bincode::serde::serialize as bin_serialize;
use serde_json::to_string as json_serialize;

/// An error that can be serialized by serde or rustc_seralize.
#[derive(Serialize, Deserialize, Debug, RustcEncodable, RustcDecodable)]
pub enum SeralizableError {
    /// If the error is commonly used, such as something from std, some of it's fields may be preserved. This variant represents these kinds of errors.
    RealError(real_error_impls::RealError),
    /// If the error isn't in std or isn't common, it is automatically made a PseudoError, loosing it's fields.
    PseudoError(PseudoError),
}

/// An error that has been made seralization-capable, but has lost it's fields, due to incompatibility with the library or preserving fields being unnesacary.
///
/// See the crate root for more info.
#[derive(Serialize, Deserialize, Debug, RustcEncodable, RustcDecodable)]
pub struct PseudoError {
    cause: Option<Box<PseudoError>>,
    desc: String,
}

impl Display for PseudoError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", self.desc)
    }
}

impl<'a> From<&'a Error> for PseudoError {
    fn from(err: &Error) -> PseudoError {
        PseudoError {
            cause: err.cause().map(|cause| Box::new(PseudoError::from(cause))), /* In prevous versions of this line, it was almost lisp with the number of close perens here. */
            desc: err.description().to_owned(),
        }
    }
}

impl Error for PseudoError {
    fn description(&self) -> &str {
        &self.desc
    }

    #[allow(trivial_casts)]
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|cause| &**cause as &Error)    // Good luck. Also &**cause looks like it's cencoring profanity. Kinda feels like it would too, with how complacated it is.
        // Actually, I'm not that mean, I'll try to explain.

        // So cause.as_ref is Option::as_ref, turning Option<Box<PseudoError>> into Option<&Box<PseudoError>>.
        // Mapping lets me take an &Box<_>.
        // &**cause is best read right to left. The transforms work like this:
        // &Box<_> -> Box<_> -> _ -> &PseudoError
        // From there it's just &PseudoError as &Error.
    }
}

/// Serializes any type implementing Error to a string that can be deseralized with deserialize_bytes.
///
/// #Examples
///
/// ```
/// use std::convert::From;
/// use std::fmt::Error;
/// use errorser::serialize_error_bytes;
///
/// let error = Error;
/// let errser = serialize_error_bytes(&error);
/// assert_eq!(errser, [0, 1]);
/// ```
pub fn serialize_error_bytes(to_ser: &Error) -> Vec<u8> {
    bin_serialize(&PseudoError::from(to_ser), SizeLimit::Infinite).unwrap()
}

/// Serializes any type implementing Error to a string that can be deseralized with deserialize_string.
///
/// #Examples
///
/// ```
/// use std::convert::From;
/// use std::fmt::Error;
/// use errorser::serialize_error_string;
///
/// let error = Error;
/// let errser = serialize_error_string(&error);
/// assert_eq!(errser, "???");
/// ```
pub fn serialize_error_string(to_ser: &Error) -> String {
    json_serialize(&PseudoError::from(to_ser)).unwrap()
}

#[cfg(test)]
mod test {
    #[test]
    fn serialize_error_bytes() {}
}
<commit_msg>impl Error for SerializableError<commit_after>#![feature(custom_derive, plugin, stmt_expr_attributes)]
#![plugin(serde_macros, clippy)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces, unused_qualifications,
        warnings, clippy)]

//! Serializes and psudo-deserializes structs implementing the Error trait. This should only be done if you know you won't ever need an actual error value, only the description and causes.
//!
//! This crate assumes that the error descriptions are complete, and are indicative of the error going on.
//! There is also no way to get any values accoated with the error, since that would require real serialization of arbratrary structs, implementing a trait you didn't make.
//!
//! #Examples
//!
//! ```
//! use std::convert::From;
//! use std::fmt::Error;
//! use errorser::serialize_error_string;
//!
//! let error = Error;
//! let errser = serialize_error_string(&error);
//! assert_eq!(errser, "???");
//! ```

extern crate bincode;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;

mod real_error_impls;

use std::convert::{From, AsRef};
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};

use bincode::SizeLimit;
use bincode::serde::serialize as bin_serialize;
use serde_json::to_string as json_serialize;

/// An error that can be serialized by serde or rustc_seralize.
#[derive(Serialize, Deserialize, Debug, RustcEncodable, RustcDecodable)]
pub enum SeralizableError {
    /// If the error is commonly used, such as something from std, some of it's fields may be preserved. This variant represents these kinds of errors.
    RealError(real_error_impls::RealError),
    /// If the error isn't in std or isn't common, it is automatically made a PseudoError, loosing it's fields.
    PseudoError(PseudoError),
}

impl Display for SeralizableError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        use SeralizableError::*;
        match *self {
            RealError(ref _rerr) => unimplemented!(),
            PseudoError(ref perr) => write!(fmt, "{}", perr),
        }
    }
}

impl<'a> From<&'a Error> for SeralizableError {
    fn from(err: &Error) -> SeralizableError {
        // TODO: Check if can be seralized as RealError.
        SeralizableError::PseudoError(PseudoError::from(err))
    }
}

impl Error for SeralizableError {
    fn description(&self) -> &str {
        use SeralizableError::*;
        match *self {
            RealError(ref _rerr) => unimplemented!(),
            PseudoError(ref perr) => perr.description(),
        }
    }

    #[allow(trivial_casts)]
    fn cause(&self) -> Option<&Error> {
        use SeralizableError::*;
        match *self {
            RealError(ref _rerr) => unimplemented!(),
            PseudoError(ref perr) => perr.cause(),
        }
    }
}

/// An error that has been made seralization-capable, but has lost it's fields, due to incompatibility with the library or preserving fields being unnesacary.
///
/// See the crate root for more info.
#[derive(Serialize, Deserialize, Debug, RustcEncodable, RustcDecodable)]
pub struct PseudoError {
    cause: Option<Box<PseudoError>>,
    desc: String,
}

impl Display for PseudoError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", self.desc)
    }
}

impl<'a> From<&'a Error> for PseudoError {
    fn from(err: &Error) -> PseudoError {
        PseudoError {
            cause: err.cause().map(|cause| Box::new(PseudoError::from(cause))), /* In prevous versions of this line, it was almost lisp with the number of close perens here. */
            desc: err.description().to_owned(),
        }
    }
}

impl Error for PseudoError {
    fn description(&self) -> &str {
        &self.desc
    }

    #[allow(trivial_casts)]
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|cause| &**cause as &Error)    // Good luck. Also &**cause looks like it's cencoring profanity. Kinda feels like it would too, with how complacated it is.
        // Actually, I'm not that mean, I'll try to explain.

        // So cause.as_ref is Option::as_ref, turning Option<Box<PseudoError>> into Option<&Box<PseudoError>>.
        // Mapping lets me take an &Box<_>.
        // &**cause is best read right to left. The transforms work like this:
        // &Box<_> -> Box<_> -> _ -> &PseudoError
        // From there it's just &PseudoError as &Error.
    }
}

/// Serializes any type implementing Error to a string that can be deseralized with deserialize_bytes.
///
/// #Examples
///
/// ```
/// use std::convert::From;
/// use std::fmt::Error;
/// use errorser::serialize_error_bytes;
///
/// let error = Error;
/// let errser = serialize_error_bytes(&error);
/// assert_eq!(errser, [0, 1]);
/// ```
pub fn serialize_error_bytes(to_ser: &Error) -> Vec<u8> {
    bin_serialize(&PseudoError::from(to_ser), SizeLimit::Infinite).unwrap()
}

/// Serializes any type implementing Error to a string that can be deseralized with deserialize_string.
///
/// #Examples
///
/// ```
/// use std::convert::From;
/// use std::fmt::Error;
/// use errorser::serialize_error_string;
///
/// let error = Error;
/// let errser = serialize_error_string(&error);
/// assert_eq!(errser, "???");
/// ```
pub fn serialize_error_string(to_ser: &Error) -> String {
    json_serialize(&PseudoError::from(to_ser)).unwrap()
}

#[cfg(test)]
mod test {
    #[test]
    fn serialize_error_bytes() {}
}
<|endoftext|>