<commit_before>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use ::source::{Source, SourceError};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string())
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value::to_value(&value),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string())
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    pub fn new() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.remove::<HandlebarsEngine>()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                if let Some(ref name) = h.name {
                    return Some(hbs.render(name, &h.value).map_err(TemplateRenderError::from));
                } else if let Some(ref content) = h.content {
                    return Some(hbs.template_render(content, &h.value));
                } else {
                    unreachable!();
                }
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<commit_msg>(feat) also render on error branch [#39]<commit_after>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use ::source::{Source, SourceError};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string())
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value::to_value(&value),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string())
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    pub fn new() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.remove::<HandlebarsEngine>()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                if let Some(ref name) = h.name {
                    return Some(hbs.render(name, &h.value).map_err(TemplateRenderError::from));
                } else if let Some(ref content) = h.content {
                    return Some(hbs.template_render(content, &h.value));
                } else {
                    unreachable!();
                }
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }

    fn catch(&self, req: &mut Request, e: IronError) -> IronResult<Response> {
        let mut err = e;
        err.response = try!(self.after(req, err.response));
        Err(err)
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(inclusive_range_syntax, conservative_impl_trait, plugin)]
#![plugin(tarpc_plugins)]

extern crate chrono;
extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate log;
#[macro_use]
extern crate tarpc;
extern crate futures_cpupool;

use futures::Future;
use futures_cpupool::{CpuFuture, CpuPool};
use std::thread;
use std::time::{Duration, Instant, SystemTime};
use tarpc::future::{Connect};
use tarpc::util::{FirstSocketAddr, Never};

service! {
    rpc read(size: u32) -> Vec<u8>;
}

#[derive(Clone)]
struct Server(CpuPool);

impl Server {
    fn new() -> Self {
        Server(CpuPool::new_num_cpus())
    }
}

impl FutureService for Server {
    type ReadFut = CpuFuture<Vec<u8>, Never>;

    fn read(&self, size: u32) -> Self::ReadFut {
        self.0
            .spawn(futures::lazy(move || {
                let mut vec: Vec<u8> = Vec::with_capacity(size as usize);
                for i in 0..size {
                    vec.push((i % 1 << 8) as u8);
                }
                futures::finished::<_, Never>(vec)
            }))
    }
}

fn run_once(clients: &[FutureClient], concurrency: u32, print: bool) {
    let _ = env_logger::init();

    let start = Instant::now();
    let futures: Vec<_> = clients.iter()
        .cycle()
        .take(concurrency as usize)
        .map(|client| {
            let start = SystemTime::now();
            let future = client.read(CHUNK_SIZE).map(move |_| start.elapsed().unwrap());
            thread::yield_now();
            future
        })
        .collect();

    let latencies: Vec<_> = futures.into_iter()
        .map(|future| {
            future.wait().unwrap()
        })
        .collect();
    let total_time = start.elapsed();

    let sum_latencies = latencies.iter().fold(Duration::new(0, 0), |sum, &dur| sum + dur);
    let mean = sum_latencies / latencies.len() as u32;
    let min_latency = *latencies.iter().min().unwrap();
    let max_latency = *latencies.iter().max().unwrap();

    if print {
        println!("{} requests => Mean={}µs, Min={}µs, Max={}µs, Total={}µs",
                 latencies.len(),
                 mean.microseconds(),
                 min_latency.microseconds(),
                 max_latency.microseconds(),
                 total_time.microseconds());
    }
}

trait Microseconds {
    fn microseconds(&self) -> i64;
}

impl Microseconds for Duration {
    fn microseconds(&self) -> i64 {
         chrono::Duration::from_std(*self)
             .unwrap()
             .num_microseconds()
             .unwrap()
    }
}

const CHUNK_SIZE: u32 = 1 << 10;
const MAX_CONCURRENCY: u32 = 100;

fn main() {
    let _ = env_logger::init();
    let server = Server::new().listen("localhost:0".first_socket_addr()).wait().unwrap();
    println!("Server listening on {}.", server.local_addr());
    let clients: Vec<_> = (1...5)
        .map(|i| {
            println!("Client {} connecting...", i);
            FutureClient::connect(server.local_addr()).wait().unwrap()
        })
        .collect();
    println!("Starting...");

    run_once(&clients, MAX_CONCURRENCY, false);
    for concurrency in 1...MAX_CONCURRENCY {
        run_once(&clients, concurrency, true);
    }
}
<commit_msg>Re-work concurrency example to not use wait() everywhere.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(inclusive_range_syntax, conservative_impl_trait, plugin)]
#![plugin(tarpc_plugins)]

extern crate chrono;
extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate log;
#[macro_use]
extern crate tarpc;
extern crate tokio_core;
extern crate futures_cpupool;

use futures::Future;
use futures_cpupool::{CpuFuture, CpuPool};
use std::thread;
use std::time::{Duration, Instant, SystemTime};
use tarpc::future::{Connect};
use tarpc::util::{FirstSocketAddr, Never};
use tokio_core::reactor;

service! {
    rpc read(size: u32) -> Vec<u8>;
}

#[derive(Clone)]
struct Server(CpuPool);

impl Server {
    fn new() -> Self {
        Server(CpuPool::new_num_cpus())
    }
}

impl FutureService for Server {
    type ReadFut = CpuFuture<Vec<u8>, Never>;

    fn read(&self, size: u32) -> Self::ReadFut {
        self.0
            .spawn(futures::lazy(move || {
                let mut vec: Vec<u8> = Vec::with_capacity(size as usize);
                for i in 0..size {
                    vec.push((i % 1 << 8) as u8);
                }
                futures::finished::<_, Never>(vec)
            }))
    }
}

fn run_once<'a>(clients: &'a [FutureClient], concurrency: u32, print: bool)
    -> Box<Future<Item=(), Error=()> + 'a>
{
    let start = Instant::now();
    let futs = clients.iter()
        .cycle()
        .take(concurrency as usize)
        .map(|client| {
            let start = SystemTime::now();
            info!("Reading...");
            let future = client.read(CHUNK_SIZE).map(move |_| start.elapsed().unwrap());
            info!("Yielding...");
            thread::yield_now();
            future
        });
    let futs = futures::collect(futs);

    Box::new(futs.map(move |latencies| {
        let total_time = start.elapsed();

        let sum_latencies = latencies.iter().fold(Duration::new(0, 0), |sum, &dur| sum + dur);
        let mean = sum_latencies / latencies.len() as u32;
        let min_latency = *latencies.iter().min().unwrap();
        let max_latency = *latencies.iter().max().unwrap();

        if print {
            println!("{} requests => Mean={}µs, Min={}µs, Max={}µs, Total={}µs",
                     latencies.len(),
                     mean.microseconds(),
                     min_latency.microseconds(),
                     max_latency.microseconds(),
                     total_time.microseconds());
        }
    }).map_err(|e| panic!(e)))
}

trait Microseconds {
    fn microseconds(&self) -> i64;
}

impl Microseconds for Duration {
    fn microseconds(&self) -> i64 {
         chrono::Duration::from_std(*self)
             .unwrap()
             .num_microseconds()
             .unwrap()
    }
}

const CHUNK_SIZE: u32 = 1 << 10;
const MAX_CONCURRENCY: u32 = 100;

fn main() {
    let _ = env_logger::init();

    let server = Server::new().listen("localhost:0".first_socket_addr()).wait().unwrap();
    println!("Server listening on {}.", server.local_addr());

    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();
    let clients = (1...5)
        .map(|i| {
            println!("Client {} connecting...", i);
            FutureClient::connect_with(server.local_addr(), &handle).map_err(|e| panic!(e))
        });
    let clients = core.run(futures::collect(clients)).unwrap();
    println!("Starting...");
    let runs = ::std::iter::once(run_once(&clients, MAX_CONCURRENCY, false))
        .chain((1...MAX_CONCURRENCY).map(|concurrency| run_once(&clients, concurrency, true)));
    core.run(futures::collect(runs)).unwrap();
}
<|endoftext|>


<commit_before>use descartes::{N, P2, Norm, WithUniqueOrthogonal};
use rand::Rng;
use monet::{Vertex, Geometry};

use super::Lot;

#[derive(Compact, Clone)]
pub struct BuildingGeometry {
    pub wall: Geometry,
    pub brick_roof: Geometry,
    pub flat_roof: Geometry,
    pub field: Geometry,
}

#[derive(Copy, Clone)]
pub enum BuildingStyle {
    FamilyHouse,
    GroceryShop,
    Field,
    Mill,
    Bakery,
    NeihboringTownConnection,
}

pub fn build_building<R: Rng>(
    lot: &Lot,
    building_type: BuildingStyle,
    rng: &mut R,
) -> BuildingGeometry {
    let (main_footprint, entrance_footprint) = generate_house_footprint(lot, rng);

    match building_type {
        BuildingStyle::FamilyHouse => {
            let height = 3.0 + 3.0 * rng.next_f32();
            let entrance_height = 2.0 + rng.next_f32();

            let (roof_brick_geometry, roof_wall_geometry) =
                main_footprint.open_gable_roof_geometry(height, 0.3);
            let (entrance_roof_brick_geometry, entrance_roof_wall_geometry) =
                entrance_footprint.open_gable_roof_geometry(entrance_height, 0.3);

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(entrance_height) +
                    roof_wall_geometry + entrance_roof_wall_geometry,
                brick_roof: roof_brick_geometry + entrance_roof_brick_geometry,
                flat_roof: Geometry::empty(),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::GroceryShop => {
            let height = 3.0 + rng.next_f32();
            let entrance_height = height - 0.7;

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(entrance_height),
                brick_roof: Geometry::empty(),
                flat_roof: main_footprint.flat_roof_geometry(height) +
                    entrance_footprint.flat_roof_geometry(entrance_height),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::Field => {
            BuildingGeometry {
                wall: Geometry::empty(),
                brick_roof: Geometry::empty(),
                flat_roof: Geometry::empty(),
                field: main_footprint.flat_roof_geometry(0.0),
            }
        }
        BuildingStyle::Mill => {
            let height = 3.0 + rng.next_f32();
            let tower_height = 5.0 + rng.next_f32();

            let (roof_brick_geometry, roof_wall_geometry) =
                main_footprint.open_gable_roof_geometry(height, 0.3);
            let (tower_roof_brick_geometry, tower_roof_wall_geometry) =
                entrance_footprint.open_gable_roof_geometry(tower_height, 0.3);

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(tower_height) +
                    roof_wall_geometry + tower_roof_wall_geometry,
                brick_roof: roof_brick_geometry + tower_roof_brick_geometry,
                flat_roof: Geometry::empty(),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::Bakery => {
            let height = 3.0 + rng.next_f32();
            let entrance_height = height - 0.7;

            let (entrance_roof_brick_geometry, entrance_roof_wall_geometry) =
                entrance_footprint.open_gable_roof_geometry(entrance_height, 0.3);

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(entrance_height) +
                    entrance_roof_wall_geometry,
                brick_roof: entrance_roof_brick_geometry,
                flat_roof: main_footprint.flat_roof_geometry(height),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::NeihboringTownConnection => {
            let length = 100.0;
            let orientation_orth = lot.orientation.orthogonal();

            let vertices = vec![
                lot.position - length / 4.0 * orientation_orth,
                lot.position + length / 2.0 * lot.orientation,
                lot.position + length / 4.0 * orientation_orth,
                lot.position - length / 2.0 * lot.orientation,
            ].into_iter()
                .map(|v| Vertex { position: [v.x, v.y, 3.0] })
                .collect();

            let indices = vec![0, 1, 2, 2, 3, 0];

            BuildingGeometry {
                wall: Geometry::new(vertices, indices),
                brick_roof: Geometry::empty(),
                flat_roof: Geometry::empty(),
                field: Geometry::empty(),
            }
        }
    }
}

pub struct Footprint {
    back_right: P2,
    back_left: P2,
    front_right: P2,
    front_left: P2,
}

impl Footprint {
    fn wall_geometry(&self, wall_height: N) -> Geometry {
        let vertices =
            vec![
                Vertex { position: [self.back_right.x, self.back_right.y, 0.0] },
                Vertex { position: [self.back_left.x, self.back_left.y, 0.0] },
                Vertex { position: [self.front_left.x, self.front_left.y, 0.0] },
                Vertex { position: [self.front_right.x, self.front_right.y, 0.0] },

                Vertex { position: [self.back_right.x, self.back_right.y, wall_height] },
                Vertex { position: [self.back_left.x, self.back_left.y, wall_height] },
                Vertex { position: [self.front_left.x, self.front_left.y, wall_height] },
                Vertex { position: [self.front_right.x, self.front_right.y, wall_height] },
            ];

        let indices = vec![
            0,
            1,
            4,
            1,
            5,
            4,
            1,
            2,
            5,
            2,
            6,
            5,
            2,
            3,
            6,
            3,
            7,
            6,
            3,
            0,
            7,
            0,
            4,
            7,
        ];

        Geometry::new(vertices, indices)
    }

    fn flat_roof_geometry(&self, base_height: N) -> Geometry {
        let vertices =
            vec![
                Vertex { position: [self.back_right.x, self.back_right.y, base_height] },
                Vertex { position: [self.back_left.x, self.back_left.y, base_height] },
                Vertex { position: [self.front_left.x, self.front_left.y, base_height] },
                Vertex { position: [self.front_right.x, self.front_right.y, base_height] },
            ];

        let indices = vec![0, 1, 3, 1, 2, 3];

        Geometry::new(vertices, indices)
    }

    fn open_gable_roof_geometry(&self, base_height: N, angle: N) -> (Geometry, Geometry) {
        let roof_height = (self.back_right - self.front_right).norm() * angle.sin();
        let mid_right = (self.back_right + self.front_right.to_vector()) / 2.0;
        let mid_left = (self.back_left + self.front_left.to_vector()) / 2.0;

        let vertices =
            vec![
                Vertex { position: [self.back_right.x, self.back_right.y, base_height] },
                Vertex { position: [self.back_left.x, self.back_left.y, base_height] },
                Vertex { position: [mid_left.x, mid_left.y, base_height + roof_height] },
                Vertex { position: [self.front_left.x, self.front_left.y, base_height] },
                Vertex { position: [self.front_right.x, self.front_right.y, base_height] },
                Vertex { position: [mid_right.x, mid_right.y, base_height + roof_height] },
            ];

        let roof_indices = vec![0, 1, 2, 2, 5, 0, 2, 3, 4, 4, 5, 2];

        let wall_indices = vec![1, 2, 3, 4, 5, 0];

        (
            Geometry::new(vertices.clone(), roof_indices),
            Geometry::new(vertices, wall_indices),
        )
    }
}

pub fn generate_house_footprint<R: Rng>(lot: &Lot, rng: &mut R) -> (Footprint, Footprint) {
    let orientation_orth = lot.orientation.orthogonal();

    let footprint_width = 10.0 + rng.next_f32() * 7.0;
    let footprint_depth = 7.0 + rng.next_f32() * 5.0;

    let entrance_position = lot.position +
        lot.orientation * (0.5 - 1.0 * rng.next_f32()) * footprint_width -
        orientation_orth * (rng.next_f32() * 0.3 + 0.1) * footprint_depth;
    let entrance_width = 5.0 + rng.next_f32() * 4.0;
    let entrance_depth = 3.0 + rng.next_f32() * 3.0;

    (
        Footprint {
            back_right: lot.position + lot.orientation * footprint_width / 2.0 -
                orientation_orth * footprint_depth / 2.0,
            back_left: lot.position - lot.orientation * footprint_width / 2.0 -
                orientation_orth * footprint_depth / 2.0,
            front_left: lot.position - lot.orientation * footprint_width / 2.0 +
                orientation_orth * footprint_depth / 2.0,
            front_right: lot.position + lot.orientation * footprint_width / 2.0 +
                orientation_orth * footprint_depth / 2.0,
        },
        Footprint {
            back_right: entrance_position + orientation_orth * entrance_width / 2.0 +
                lot.orientation * entrance_depth / 2.0,
            back_left: entrance_position - orientation_orth * entrance_width / 2.0 +
                lot.orientation * entrance_depth / 2.0,
            front_left: entrance_position - orientation_orth * entrance_width / 2.0 -
                lot.orientation * entrance_depth / 2.0,
            front_right: entrance_position + orientation_orth * entrance_width / 2.0 -
                lot.orientation * entrance_depth / 2.0,
        },
    )
}
<commit_msg>Make fields and Mills and Bakeries more noticeable<commit_after>use descartes::{N, P2, Norm, WithUniqueOrthogonal};
use rand::Rng;
use monet::{Vertex, Geometry};

use super::Lot;

#[derive(Compact, Clone)]
pub struct BuildingGeometry {
    pub wall: Geometry,
    pub brick_roof: Geometry,
    pub flat_roof: Geometry,
    pub field: Geometry,
}

#[derive(Copy, Clone)]
pub enum BuildingStyle {
    FamilyHouse,
    GroceryShop,
    Field,
    Mill,
    Bakery,
    NeihboringTownConnection,
}

pub fn build_building<R: Rng>(
    lot: &Lot,
    building_type: BuildingStyle,
    rng: &mut R,
) -> BuildingGeometry {
    let (main_footprint, entrance_footprint) = generate_house_footprint(lot, rng);

    match building_type {
        BuildingStyle::FamilyHouse => {
            let height = 3.0 + 3.0 * rng.next_f32();
            let entrance_height = 2.0 + rng.next_f32();

            let (roof_brick_geometry, roof_wall_geometry) =
                main_footprint.open_gable_roof_geometry(height, 0.3);
            let (entrance_roof_brick_geometry, entrance_roof_wall_geometry) =
                entrance_footprint.open_gable_roof_geometry(entrance_height, 0.3);

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(entrance_height) +
                    roof_wall_geometry + entrance_roof_wall_geometry,
                brick_roof: roof_brick_geometry + entrance_roof_brick_geometry,
                flat_roof: Geometry::empty(),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::GroceryShop => {
            let height = 3.0 + rng.next_f32();
            let entrance_height = height - 0.7;

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(entrance_height),
                brick_roof: Geometry::empty(),
                flat_roof: main_footprint.flat_roof_geometry(height) +
                    entrance_footprint.flat_roof_geometry(entrance_height),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::Field => {
            BuildingGeometry {
                wall: Geometry::empty(),
                brick_roof: Geometry::empty(),
                flat_roof: Geometry::empty(),
                field: main_footprint.scale(3.0).flat_roof_geometry(0.0),
            }
        }
        BuildingStyle::Mill => {
            let height = 3.0 + rng.next_f32();
            let tower_height = 5.0 + rng.next_f32();

            let (roof_brick_geometry, roof_wall_geometry) =
                main_footprint.open_gable_roof_geometry(height, 0.3);
            let (tower_roof_brick_geometry, tower_roof_wall_geometry) =
                entrance_footprint.open_gable_roof_geometry(tower_height, 0.3);

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(tower_height) +
                    roof_wall_geometry + tower_roof_wall_geometry,
                brick_roof: Geometry::empty(),
                flat_roof: roof_brick_geometry + tower_roof_brick_geometry,
                field: Geometry::empty(),
            }
        }
        BuildingStyle::Bakery => {
            let height = 3.0 + rng.next_f32();
            let entrance_height = height;

            let (entrance_roof_brick_geometry, entrance_roof_wall_geometry) =
                entrance_footprint.open_gable_roof_geometry(entrance_height, 0.3);

            BuildingGeometry {
                wall: main_footprint.wall_geometry(height) +
                    entrance_footprint.wall_geometry(entrance_height) +
                    entrance_roof_wall_geometry,
                brick_roof: entrance_roof_brick_geometry,
                flat_roof: main_footprint.flat_roof_geometry(height),
                field: Geometry::empty(),
            }
        }
        BuildingStyle::NeihboringTownConnection => {
            let length = 100.0;
            let orientation_orth = lot.orientation.orthogonal();

            let vertices = vec![
                lot.position - length / 4.0 * orientation_orth,
                lot.position + length / 2.0 * lot.orientation,
                lot.position + length / 4.0 * orientation_orth,
                lot.position - length / 2.0 * lot.orientation,
            ].into_iter()
                .map(|v| Vertex { position: [v.x, v.y, 3.0] })
                .collect();

            let indices = vec![0, 1, 2, 2, 3, 0];

            BuildingGeometry {
                wall: Geometry::new(vertices, indices),
                brick_roof: Geometry::empty(),
                flat_roof: Geometry::empty(),
                field: Geometry::empty(),
            }
        }
    }
}

pub struct Footprint {
    back_right: P2,
    back_left: P2,
    front_right: P2,
    front_left: P2,
}

impl Footprint {
    fn wall_geometry(&self, wall_height: N) -> Geometry {
        let vertices =
            vec![
                Vertex { position: [self.back_right.x, self.back_right.y, 0.0] },
                Vertex { position: [self.back_left.x, self.back_left.y, 0.0] },
                Vertex { position: [self.front_left.x, self.front_left.y, 0.0] },
                Vertex { position: [self.front_right.x, self.front_right.y, 0.0] },

                Vertex { position: [self.back_right.x, self.back_right.y, wall_height] },
                Vertex { position: [self.back_left.x, self.back_left.y, wall_height] },
                Vertex { position: [self.front_left.x, self.front_left.y, wall_height] },
                Vertex { position: [self.front_right.x, self.front_right.y, wall_height] },
            ];

        let indices = vec![
            0,
            1,
            4,
            1,
            5,
            4,
            1,
            2,
            5,
            2,
            6,
            5,
            2,
            3,
            6,
            3,
            7,
            6,
            3,
            0,
            7,
            0,
            4,
            7,
        ];

        Geometry::new(vertices, indices)
    }

    fn flat_roof_geometry(&self, base_height: N) -> Geometry {
        let vertices =
            vec![
                Vertex { position: [self.back_right.x, self.back_right.y, base_height] },
                Vertex { position: [self.back_left.x, self.back_left.y, base_height] },
                Vertex { position: [self.front_left.x, self.front_left.y, base_height] },
                Vertex { position: [self.front_right.x, self.front_right.y, base_height] },
            ];

        let indices = vec![0, 1, 3, 1, 2, 3];

        Geometry::new(vertices, indices)
    }

    fn open_gable_roof_geometry(&self, base_height: N, angle: N) -> (Geometry, Geometry) {
        let roof_height = (self.back_right - self.front_right).norm() * angle.sin();
        let mid_right = (self.back_right + self.front_right.to_vector()) / 2.0;
        let mid_left = (self.back_left + self.front_left.to_vector()) / 2.0;

        let vertices =
            vec![
                Vertex { position: [self.back_right.x, self.back_right.y, base_height] },
                Vertex { position: [self.back_left.x, self.back_left.y, base_height] },
                Vertex { position: [mid_left.x, mid_left.y, base_height + roof_height] },
                Vertex { position: [self.front_left.x, self.front_left.y, base_height] },
                Vertex { position: [self.front_right.x, self.front_right.y, base_height] },
                Vertex { position: [mid_right.x, mid_right.y, base_height + roof_height] },
            ];

        let roof_indices = vec![0, 1, 2, 2, 5, 0, 2, 3, 4, 4, 5, 2];

        let wall_indices = vec![1, 2, 3, 4, 5, 0];

        (
            Geometry::new(vertices.clone(), roof_indices),
            Geometry::new(vertices, wall_indices),
        )
    }

    fn scale(&self, factor: f32) -> Footprint {
        let center = ((self.back_left.to_vector() + self.back_right.to_vector() +
                           self.front_left.to_vector() +
                           self.front_right.to_vector()) / 4.0)
            .to_point();

        Footprint {
            back_left: center + factor * (self.back_left - center),
            back_right: center + factor * (self.back_right - center),
            front_left: center + factor * (self.front_left - center),
            front_right: center + factor * (self.front_right - center),
        }
    }
}

pub fn generate_house_footprint<R: Rng>(lot: &Lot, rng: &mut R) -> (Footprint, Footprint) {
    let orientation_orth = lot.orientation.orthogonal();

    let footprint_width = 10.0 + rng.next_f32() * 7.0;
    let footprint_depth = 7.0 + rng.next_f32() * 5.0;

    let entrance_position = lot.position +
        lot.orientation * (0.5 - 1.0 * rng.next_f32()) * footprint_width -
        orientation_orth * (rng.next_f32() * 0.3 + 0.1) * footprint_depth;
    let entrance_width = 5.0 + rng.next_f32() * 4.0;
    let entrance_depth = 3.0 + rng.next_f32() * 3.0;

    (
        Footprint {
            back_right: lot.position + lot.orientation * footprint_width / 2.0 -
                orientation_orth * footprint_depth / 2.0,
            back_left: lot.position - lot.orientation * footprint_width / 2.0 -
                orientation_orth * footprint_depth / 2.0,
            front_left: lot.position - lot.orientation * footprint_width / 2.0 +
                orientation_orth * footprint_depth / 2.0,
            front_right: lot.position + lot.orientation * footprint_width / 2.0 +
                orientation_orth * footprint_depth / 2.0,
        },
        Footprint {
            back_right: entrance_position + orientation_orth * entrance_width / 2.0 +
                lot.orientation * entrance_depth / 2.0,
            back_left: entrance_position - orientation_orth * entrance_width / 2.0 +
                lot.orientation * entrance_depth / 2.0,
            front_left: entrance_position - orientation_orth * entrance_width / 2.0 -
                lot.orientation * entrance_depth / 2.0,
            front_right: entrance_position + orientation_orth * entrance_width / 2.0 -
                lot.orientation * entrance_depth / 2.0,
        },
    )
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate prodbg_api;
extern crate libc;
use prodbg_api::*;
use libc::c_void;
pub mod gdb;
use gdb::{GdbRemote, Memory, NeedsAck};
//use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
//use std::io::Read;
//use std::{slice, str};

//use std::ptr;

//static CODE: &'static [u8] = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75";

struct AmigaUaeBackend {
    capstone: Capstone,
    conn: gdb::GdbRemote,
    exception_location: u32,
}

impl AmigaUaeBackend {
    fn from_hex(ch: u8) -> u8 {
        if (ch >= b'a') && (ch <= b'f') {
            return ch - b'a' + 10;
        }

        if (ch >= b'0') && (ch <= b'9') {
            return ch - b'0';
        }

        if (ch >= b'A') && (ch <= b'F') {
            return ch - b'A' + 10;
        }

        return 0;
    }

    fn get_u32(data: &[u8]) -> u32 {
        let t0 = ((Self::from_hex(data[0]) << 4) | Self::from_hex(data[1])) as u32;
        let t1 = ((Self::from_hex(data[2]) << 4) | Self::from_hex(data[3])) as u32;
        let t2 = ((Self::from_hex(data[4]) << 4) | Self::from_hex(data[5])) as u32;
        let t3 = ((Self::from_hex(data[6]) << 4) | Self::from_hex(data[7])) as u32;
        (t0 << 24) | (t1 << 16) | (t2 << 8) | t3
    }

    fn write_register(writer: &mut Writer, name: &str, data: u32, read_only: bool) {
        writer.array_entry_begin();
        writer.write_string("name", name);
        writer.write_u8("size", 4);

        if read_only {
            writer.write_u8("read_only", 1);
        }

        writer.write_u32("register", data);

        writer.array_entry_end();
    }

    fn write_registers(&mut self, writer: &mut Writer, data: &Vec<u8>) {
        let mut index = 1;  // 1 to skip starting $

        writer.event_begin(EventType::SetRegisters as u16);
        writer.array_begin("registers");

        // d registers

        for i in 0..8 {
            let name = format!("d{}", i);
            let reg = Self::get_u32(&data[index..]);
            Self::write_register(writer, &name, reg, false);
            index += 8;
        }

        // a registers

        for i in 0..8 {
            let name = format!("a{}", i);
            let reg = Self::get_u32(&data[index..]);
            Self::write_register(writer, &name, reg, false);
            index += 8;
        }

        // Status registers & pc

        let sr = Self::get_u32(&data[index..]);
        let pc = Self::get_u32(&data[index + 8..]);

        self.exception_location = pc;

        Self::write_register(writer, "sr", sr, true);
        Self::write_register(writer, "pc", pc, true);

        writer.array_end();
        writer.event_end();
    }

    fn write_disassembly(&mut self, writer: &mut Writer, mem: &Memory) {
        match self.capstone.open(Arch::M68K, CS_MODE_M68K_000) {
            Err(e) => {
                println!("Unable to open Capstone {}", e as i32);
                return;
            }
            _ => (),
        }

        if let Ok(insns) = self.capstone.disasm(&mem.data, mem.address, 0) {
            writer.event_begin(EventType::SetDisassembly as u16);
            writer.array_begin("disassembly");

            for i in insns.iter() {
                let text = format!("{0: <10} {1: <10}", i.mnemonic().unwrap(), i.op_str().unwrap_or(""));
                writer.array_entry_begin();
                writer.write_u32("address", i.address as u32);
                writer.write_string("line", &text);

                //println!("{:?}", i);

                writer.array_entry_end();
            }

            writer.array_end();
            writer.event_end();
        } else {
            println!("No instructions :(");
        }
    }

    fn write_exception_location(&mut self, writer: &mut Writer) {
        writer.event_begin(EventType::SetExceptionLocation as u16);
        writer.write_u64("address", self.exception_location as u64);
        writer.write_u8("size", 4);
        writer.event_end();
    }

    /*
    fn test_capstone(&mut self) {
        match self.capstone.open(Arch::M68K, CS_MODE_M68K_000) {
            Err(e) => {
                println!("Unable to open Capstone {}", e as i32);
                return;
            }
            _ => (),
        }

        if let Ok(insns) = self.capstone.disasm(CODE, 0x1000, 0) {
            println!("Got {} instructions", insns.len());

            for i in insns.iter() {
                println!("{:?}", i);
            }
        } else {
            println!("No instructions :(");
        }
    }
    */
}

impl Backend for AmigaUaeBackend {
    fn new(service: &Service) -> Self {
        AmigaUaeBackend {
            capstone: service.get_capstone(),
            conn: GdbRemote::new(NeedsAck::No),
            exception_location: 0,
        }
    }

    // TODO: Something about action action as i32
    fn update(&mut self, action: i32, reader: &mut Reader, writer: &mut Writer) {
        for event in reader.get_event() {
            match event {
                 35 => {
                    if self.conn.connect("127.0.0.1:6860").is_ok() {
                        println!("Connected!");
                    }
                }
                _ => (),
            }
        }

        match action {
            ACTION_BREAK => {
                println!("Break");
            }

            ACTION_STEP => {
                self.conn.step_sync();

                if let Some(data) = self.conn.get_registers_sync() {
                    self.write_registers(writer, &data.clone());
                }

                if let Some(memory) = self.conn.get_memory_sync(self.exception_location - 128, 256) {
                    self.write_disassembly(writer, &memory);
                }

                self.write_exception_location(writer);
            }
            _ => (),
        }

        //self.conn.update();
    }

    fn register_menu(&mut self, menu_funcs: &mut MenuFuncs) -> *mut c_void {
        let menu = menu_funcs.create_menu("Amiga UAE Debugger");
        menu_funcs.add_menu_item(menu, "Connect to UAE...", 0, 0, 0);
        menu
    }
}

#[no_mangle]
pub fn init_plugin(plugin_handler: &mut PluginHandler) {
    define_backend_plugin!(PLUGIN, b"Amiga UAE Debugger\0", AmigaUaeBackend);
    plugin_handler.register_backend(&PLUGIN);
}

<commit_msg>Cleanup<commit_after>#[macro_use]
extern crate prodbg_api;
extern crate libc;
use prodbg_api::*;
use libc::c_void;
pub mod gdb;
use gdb::{GdbRemote, Memory, NeedsAck};

struct AmigaUaeBackend {
    capstone: Capstone,
    conn: gdb::GdbRemote,
    exception_location: u32,
}

impl AmigaUaeBackend {
    fn from_hex(ch: u8) -> u8 {
        if (ch >= b'a') && (ch <= b'f') {
            return ch - b'a' + 10;
        }

        if (ch >= b'0') && (ch <= b'9') {
            return ch - b'0';
        }

        if (ch >= b'A') && (ch <= b'F') {
            return ch - b'A' + 10;
        }

        return 0;
    }

    fn get_u32(data: &[u8]) -> u32 {
        let t0 = ((Self::from_hex(data[0]) << 4) | Self::from_hex(data[1])) as u32;
        let t1 = ((Self::from_hex(data[2]) << 4) | Self::from_hex(data[3])) as u32;
        let t2 = ((Self::from_hex(data[4]) << 4) | Self::from_hex(data[5])) as u32;
        let t3 = ((Self::from_hex(data[6]) << 4) | Self::from_hex(data[7])) as u32;
        (t0 << 24) | (t1 << 16) | (t2 << 8) | t3
    }

    fn write_register(writer: &mut Writer, name: &str, data: u32, read_only: bool) {
        writer.array_entry_begin();
        writer.write_string("name", name);
        writer.write_u8("size", 4);

        if read_only {
            writer.write_u8("read_only", 1);
        }

        writer.write_u32("register", data);

        writer.array_entry_end();
    }

    fn write_registers(&mut self, writer: &mut Writer, data: &Vec<u8>) {
        let mut index = 1;  // 1 to skip starting $

        writer.event_begin(EventType::SetRegisters as u16);
        writer.array_begin("registers");

        // d registers

        for i in 0..8 {
            let name = format!("d{}", i);
            let reg = Self::get_u32(&data[index..]);
            Self::write_register(writer, &name, reg, false);
            index += 8;
        }

        // a registers

        for i in 0..8 {
            let name = format!("a{}", i);
            let reg = Self::get_u32(&data[index..]);
            Self::write_register(writer, &name, reg, false);
            index += 8;
        }

        // Status registers & pc

        let sr = Self::get_u32(&data[index..]);
        let pc = Self::get_u32(&data[index + 8..]);

        self.exception_location = pc;

        Self::write_register(writer, "sr", sr, true);
        Self::write_register(writer, "pc", pc, true);

        writer.array_end();
        writer.event_end();
    }

    fn write_disassembly(&mut self, writer: &mut Writer, mem: &Memory) {
        match self.capstone.open(Arch::M68K, CS_MODE_M68K_000) {
            Err(e) => {
                println!("Unable to open Capstone {}", e as i32);
                return;
            }
            _ => (),
        }

        if let Ok(insns) = self.capstone.disasm(&mem.data, mem.address, 0) {
            writer.event_begin(EventType::SetDisassembly as u16);
            writer.array_begin("disassembly");

            for i in insns.iter() {
                let text = format!("{0: <10} {1: <10}", i.mnemonic().unwrap(), i.op_str().unwrap_or(""));
                writer.array_entry_begin();
                writer.write_u32("address", i.address as u32);
                writer.write_string("line", &text);

                writer.array_entry_end();
            }

            writer.array_end();
            writer.event_end();
        } else {
            println!("No instructions :(");
        }
    }

    fn write_exception_location(&mut self, writer: &mut Writer) {
        writer.event_begin(EventType::SetExceptionLocation as u16);
        writer.write_u64("address", self.exception_location as u64);
        writer.write_u8("size", 4);
        writer.event_end();
    }
}

impl Backend for AmigaUaeBackend {
    fn new(service: &Service) -> Self {
        AmigaUaeBackend {
            capstone: service.get_capstone(),
            conn: GdbRemote::new(NeedsAck::No),
            exception_location: 0,
        }
    }

    fn update(&mut self, action: i32, reader: &mut Reader, writer: &mut Writer) {
        for event in reader.get_event() {
            match event {
                 35 => {
                    if self.conn.connect("127.0.0.1:6860").is_ok() {
                        println!("Connected!");
                    }
                }
                _ => (),
            }
        }

        match action {
            ACTION_BREAK => {
                println!("Break");
            }

            ACTION_STEP => {
                self.conn.step_sync();

                if let Some(data) = self.conn.get_registers_sync() {
                    self.write_registers(writer, &data.clone());
                }

                if let Some(memory) = self.conn.get_memory_sync(self.exception_location - 128, 256) {
                    self.write_disassembly(writer, &memory);
                }

                self.write_exception_location(writer);
            }
            _ => (),
        }
    }

    fn register_menu(&mut self, menu_funcs: &mut MenuFuncs) -> *mut c_void {
        let menu = menu_funcs.create_menu("Amiga UAE Debugger");
        menu_funcs.add_menu_item(menu, "Connect to UAE...", 0, 0, 0);
        menu
    }
}

#[no_mangle]
pub fn init_plugin(plugin_handler: &mut PluginHandler) {
    define_backend_plugin!(PLUGIN, b"Amiga UAE Debugger\0", AmigaUaeBackend);
    plugin_handler.register_backend(&PLUGIN);
}

<|endoftext|>


<commit_before>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use packet::Packet;
use packet::HasPseudoheader;
use packet::checksum::rfc1071_checksum;
use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset_and_reserved: u8,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOptions>,
    #[length_fn = "tcp_padding_length"]
    padding: Vec<TcpPadding>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    let size = tcp.get_data_offset_and_reserved() as usize;
    return (size / 4) - 5 // XXX the "reserved" 4-bit word is zeros and is ignored when we divide by 4
}

/// Represents the TCP Option fields
#[packet]
pub struct TcpOptions {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

fn tcp_padding_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The TCP header padding is used to ensure that the entire header
       ends on a 32 bit boundary.
     */
    return tcp.get_data_offset_and_reserved() as usize % 4;
}

/// Represents the TCP header padding
#[packet]
pub struct TcpPadding {
    #[payload]
    data: Vec<u8>
}

/// Calculates the checksum of a TCP packet
pub fn checksum<'a, T: HasPseudoheader>(packet: &mut MutableTcpPacket<'a>, encapsulating_packet: T) -> u16be {
    let mut sum = encapsulating_packet.pseudoheader_checksum();
    let length = packet.packet().len() as u32;
    sum = sum + length & 0xffff;
    sum = sum + length >> 16;
    packet.set_checksum(0);
    return rfc1071_checksum(packet.packet(), sum);
}

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

    const TCP_MIN_HEADER_LEN: usize = 20;
    const TCP_OPTIONS_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 5;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::MutableIpv4Packet;
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(127, 0, 0, 1);
        let ipv4_destination = Ipv4Addr::new(127, 0, 0, 1);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;
        {
            let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_level_protocol(next_level_protocol);
            ip_header.set_source(ipv4_source);
            ip_header.set_destination(ipv4_destination);
        }

        {
            generate_simple_tcp_header(&mut packet[IPV4_HEADER_LEN..]);
        }

        // Set payload data
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 0] = 'm' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 1] = 'e' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 2] = 'o' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 3] = 'w' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 4] = '\n' as u8;

        let ref_tcp_packet = [0xe0, 0x0f, // source port
                              0x25, 0xc2, // dest port
                              0xdf, 0x06, // sequence
                              0xe6, 0xe6,
                              0xc9, 0x2d, // acknowledgement
                              0x98, 0x71,
                              0x80,       // header length + reserved
                              0x18,       // control bits
                              0x02, 0xab, // window
                              0xfe, 0x2d, // checksum
                              0x00, 0x00, // urgent pointer
                              0x01, 0x01, // tcp option no-op
                              0x08, 0x0a, // tcp option timestamp, options length == 10 bytes
                              0x1d, 0xfc, // 4-byte send timestamp
                              0xcb, 0x76,
                              0x1d, 0xfc, // 4-byte latest replied timestamp
                              0xbe, 0x62,
                              0x6d, 0x65, // payload
                              0x6f, 0x77, 0x0a];
        assert_eq!(&ref_tcp_packet[..], &packet[IPV4_HEADER_LEN..]);

        //tcp/ipv4 == "45, 00 00 39 58 89 40 00 40 06 e4 33 7f 00 00 01 7f 00 00 01 e0 0f 25 c2 df 06 e6 e6 c9 2d 98 71 80 18 02 ab fe 2d 00 00 01 01 08 0a 1d fc cb 76 1d fc be 62 6d 65 6f 77 0a";

    }

    fn generate_simple_tcp_header<'p>(packet: &'p mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(57359);
        assert_eq!(tcp_header.get_source(), 57359);

        tcp_header.set_destination(9666);
        assert_eq!(tcp_header.get_destination(), 9666);

        tcp_header.set_sequence(3741771494);
        assert_eq!(tcp_header.get_sequence(), 3741771494);

        tcp_header.set_acknowledgement(3375208561);
        assert_eq!(tcp_header.get_acknowledgement(), 3375208561);

        tcp_header.set_data_offset_and_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_and_reserved(), 0x80);

        tcp_header.set_control_bits(0x18);
        assert_eq!(tcp_header.get_control_bits(), 0x18);

        tcp_header.set_window(0x02ab);
        assert_eq!(tcp_header.get_window(), 0x02ab);

        tcp_header.set_checksum(0xfe2d);
        assert_eq!(tcp_header.get_checksum(), 0xfe2d);

        tcp_header.set_urgent_pointer(0x0000);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x0000);

        let mut opts: Vec<TcpOptions> = Vec::new();
        let tcp_option = TcpOptions{
            kind: 0x1,
            data: vec![0x01,0x08,0x0a,0x1d,0xfc,0xcb,0x76,0x1d,0xfc,0xbe,0x62],
        };
        opts.push(tcp_option);
        tcp_header.set_options(opts);
    }
}
<commit_msg>broken work in progress<commit_after>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use packet::Packet;
use packet::HasPseudoheader;
use packet::checksum::rfc1071_checksum;
use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset_and_reserved: u8,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOptions>,
    #[length_fn = "tcp_padding_length"]
    padding: Vec<TcpPadding>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    let size = tcp.get_data_offset_and_reserved() as usize;
    return (size / 4) - 5 // XXX the "reserved" 4-bit word is zeros and is ignored when we divide by 4
}

/// Represents the TCP Option fields
#[packet]
pub struct TcpOptions {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

fn tcp_padding_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The TCP header padding is used to ensure that the entire header
       ends on a 32 bit boundary.
     */
    return tcp.get_data_offset_and_reserved() as usize % 4;
}

/// Represents the TCP header padding
#[packet]
pub struct TcpPadding {
    #[payload]
    data: Vec<u8>
}

/// Calculates the checksum of a TCP packet
/// The passed in TcpPacket must have it's initial checksum value set to zero.
pub fn checksum<'a, T: HasPseudoheader>(packet: &TcpPacket<'a>, encapsulating_packet: T) -> u16be {
    let mut sum = encapsulating_packet.pseudoheader_checksum();
    let length = packet.packet().len() as u32;
    sum = sum + length & 0xffff;
    sum = sum + length >> 16;
    return rfc1071_checksum(packet.packet(), sum);
}

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

    const TCP_MIN_HEADER_LEN: usize = 20;
    const TCP_OPTIONS_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 5;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::{Ipv4Packet,MutableIpv4Packet};
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(127, 0, 0, 1);
        let ipv4_destination = Ipv4Addr::new(127, 0, 0, 1);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;

        {
            let mut mut_ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            mut_ip_header.set_next_level_protocol(next_level_protocol);
            mut_ip_header.set_source(ipv4_source);
            mut_ip_header.set_destination(ipv4_destination);
        }

        {
            let ip_header = Ipv4Packet::new(&packet[..]).unwrap();
            let tcp_header = TcpPacket::new(&packet[IPV4_HEADER_LEN..]).unwrap();
            let csum = checksum(tcp_header, ip_header);
        }

        {
            generate_simple_tcp_header(&mut packet[IPV4_HEADER_LEN..]);
        }

        // Set payload data
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 0] = 'm' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 1] = 'e' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 2] = 'o' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 3] = 'w' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 4] = '\n' as u8;

        let ref_tcp_packet = [0xe0, 0x0f, // source port
                              0x25, 0xc2, // dest port
                              0xdf, 0x06, // sequence
                              0xe6, 0xe6,
                              0xc9, 0x2d, // acknowledgement
                              0x98, 0x71,
                              0x80,       // header length + reserved
                              0x18,       // control bits
                              0x02, 0xab, // window
                              0xfe, 0x2d, // checksum
                              0x00, 0x00, // urgent pointer
                              0x01, 0x01, // tcp option no-op
                              0x08, 0x0a, // tcp option timestamp, options length == 10 bytes
                              0x1d, 0xfc, // 4-byte send timestamp
                              0xcb, 0x76,
                              0x1d, 0xfc, // 4-byte latest replied timestamp
                              0xbe, 0x62,
                              0x6d, 0x65, // payload
                              0x6f, 0x77, 0x0a];
        assert_eq!(&ref_tcp_packet[..], &packet[IPV4_HEADER_LEN..]);

        //tcp/ipv4 == "45, 00 00 39 58 89 40 00 40 06 e4 33 7f 00 00 01 7f 00 00 01 e0 0f 25 c2 df 06 e6 e6 c9 2d 98 71 80 18 02 ab fe 2d 00 00 01 01 08 0a 1d fc cb 76 1d fc be 62 6d 65 6f 77 0a";

    }

    fn generate_simple_tcp_header<'p>(packet: &'p mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(57359);
        assert_eq!(tcp_header.get_source(), 57359);

        tcp_header.set_destination(9666);
        assert_eq!(tcp_header.get_destination(), 9666);

        tcp_header.set_sequence(3741771494);
        assert_eq!(tcp_header.get_sequence(), 3741771494);

        tcp_header.set_acknowledgement(3375208561);
        assert_eq!(tcp_header.get_acknowledgement(), 3375208561);

        tcp_header.set_data_offset_and_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_and_reserved(), 0x80);

        tcp_header.set_control_bits(0x18);
        assert_eq!(tcp_header.get_control_bits(), 0x18);

        tcp_header.set_window(0x02ab);
        assert_eq!(tcp_header.get_window(), 0x02ab);

        tcp_header.set_checksum(0xfe2d);
        assert_eq!(tcp_header.get_checksum(), 0xfe2d);

        tcp_header.set_urgent_pointer(0x0000);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x0000);

        let mut opts: Vec<TcpOptions> = Vec::new();
        let tcp_option = TcpOptions{
            kind: 0x1,
            data: vec![0x01,0x08,0x0a,0x1d,0xfc,0xcb,0x76,0x1d,0xfc,0xbe,0x62],
        };
        opts.push(tcp_option);
        tcp_header.set_options(opts);
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::marker::PhantomData;
use super::Alphabet;
use expression::{Expression, Condition, ExpressionError};

#[derive(Debug, Eq, PartialEq)]
pub enum RuleError {
    SymbolMismatch,
    RuleArityMismatch,
    ArityMismatch,
    ConditionFalse,
    ConditionFailed,
    ExprFailed(ExpressionError),
}

pub trait ParametricSymbol: Clone + PartialEq + Debug
{
    type Sym: Alphabet;
    type Param: Clone + Debug + PartialEq;

    fn symbol(&self) -> &Self::Sym;
    fn symbol_mut(&mut self) -> &mut Self::Sym;

    fn params(&self) -> &[Self::Param];
    fn params_mut(&mut self) -> &mut [Self::Param];

    /// Construct a new ParametricSymbol. If the iterator contains a wrong
    /// number of parameters, return None.
    fn new_from_result_iter<I, E>(symbol: Self::Sym, iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>;

    fn new_from_iter<I>(symbol: Self::Sym, iter: I) -> Option<Self>
        where I: Iterator<Item = Self::Param>
    {
        match Self::new_from_result_iter::<_, ()>(symbol, iter.map(|i| Ok(i))) {
            Some(Ok(res)) => Some(res),
            Some(Err(())) => panic!(),
            None => None,
        }
    }

    fn new_from_vec(symbol: Self::Sym, vec: Vec<Self::Param>) -> Option<Self> {
        Self::new_from_iter(symbol, vec.into_iter())
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct PSym<Sym: Alphabet, Param: Clone + Debug + PartialEq> {
    symbol: Sym,
    params: Vec<Param>,
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> ParametricSymbol for PSym<Sym, Param> {
    type Sym = Sym;
    type Param = Param;

    fn symbol(&self) -> &Self::Sym {
        &self.symbol
    }
    fn symbol_mut(&mut self) -> &mut Self::Sym {
        &mut self.symbol
    }
    fn params(&self) -> &[Self::Param] {
        &self.params
    }
    fn params_mut(&mut self) -> &mut [Self::Param] {
        &mut self.params
    }

    fn new_from_result_iter<I, E>(symbol: Self::Sym, iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>
    {
        let mut params = Vec::with_capacity(iter.size_hint().0);
        for p in iter {
            match p {
                Ok(p) => params.push(p),
                Err(e) => return Some(Err(e)),
            }
        }
        Some(Ok(PSym {
            symbol: symbol,
            params: params,
        }))
    }
}

#[derive(Debug, PartialEq)]
pub struct PSym1<Sym: Alphabet, Param: Clone + Debug + PartialEq> {
    symbol: Sym,
    params: [Param; 1],
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> Clone for PSym1<Sym, Param> {
    fn clone(&self) -> Self {
        PSym1 {
            symbol: self.symbol.clone(),
            params: [self.params[0].clone()],
        }
    }
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> ParametricSymbol for PSym1<Sym, Param> {
    type Sym = Sym;
    type Param = Param;

    fn symbol(&self) -> &Self::Sym {
        &self.symbol
    }
    fn symbol_mut(&mut self) -> &mut Self::Sym {
        &mut self.symbol
    }
    fn params(&self) -> &[Self::Param] {
        &self.params
    }
    fn params_mut(&mut self) -> &mut [Self::Param] {
        &mut self.params
    }

    fn new_from_result_iter<I, E>(symbol: Self::Sym, mut iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>
    {
        let p1 = match iter.next() {
            Some(Ok(p)) => p,
            Some(Err(e)) => return Some(Err(e)),
            None => return None,
        };
        if let Some(_) = iter.next() {
            return None;
        }

        Some(Ok(PSym1 {
            symbol: symbol,
            params: [p1],
        }))
    }
}

#[derive(Debug, PartialEq)]
pub struct PSym2<Sym: Alphabet, Param: Clone + Debug + PartialEq> {
    symbol: Sym,
    params: [Param; 2],
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> Clone for PSym2<Sym, Param> {
    fn clone(&self) -> Self {
        PSym2 {
            symbol: self.symbol.clone(),
            params: [self.params[0].clone(), self.params[1].clone()],
        }
    }
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> ParametricSymbol for PSym2<Sym, Param> {
    type Sym = Sym;
    type Param = Param;

    fn symbol(&self) -> &Self::Sym {
        &self.symbol
    }
    fn symbol_mut(&mut self) -> &mut Self::Sym {
        &mut self.symbol
    }
    fn params(&self) -> &[Self::Param] {
        &self.params
    }
    fn params_mut(&mut self) -> &mut [Self::Param] {
        &mut self.params
    }

    fn new_from_result_iter<I, E>(symbol: Self::Sym, mut iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>
    {
        let p1 = match iter.next() {
            Some(Ok(p)) => p,
            Some(Err(e)) => return Some(Err(e)),
            None => return None,
        };
        let p2 = match iter.next() {
            Some(Ok(p)) => p,
            Some(Err(e)) => return Some(Err(e)),
            None => return None,
        };
        if let Some(_) = iter.next() {
            return None;
        }

        Some(Ok(PSym2 {
            symbol: symbol,
            params: [p1, p2],
        }))
    }
}

pub trait ParametricRule: Clone + Debug
{
    type InSym: ParametricSymbol;
    type OutSym: ParametricSymbol;

    fn apply(&self, psym: &Self::OutSym) -> Result<Vec<Self::OutSym>, RuleError>;

    fn symbol(&self) -> &<Self::InSym as ParametricSymbol>::Sym;
}

#[derive(Debug, Clone)]
pub struct PRule<Sym, PS, PS2, C>
    where Sym: Alphabet,
          PS: ParametricSymbol<Sym = Sym, Param = C::Expr>,
          PS2: ParametricSymbol<Sym = Sym, Param = <C::Expr as Expression>::Element>,
          C: Condition
{
    pub symbol: Sym,
    pub condition: C,
    pub production: Vec<PS>,
    pub arity: usize,
    _marker: PhantomData<PS2>,
}

impl<Sym, PS, PS2, C> PRule<Sym, PS, PS2, C>
    where Sym: Alphabet,
          PS: ParametricSymbol<Sym = Sym, Param = C::Expr>,
          PS2: ParametricSymbol<Sym = Sym, Param = <C::Expr as Expression>::Element>,
          C: Condition
{
    pub fn new(sym: Sym, cond: C, prod: Vec<PS>, arity: usize) -> PRule<Sym, PS, PS2, C> {
        PRule {
            symbol: sym,
            condition: cond,
            production: prod,
            arity: arity,
            _marker: PhantomData,
        }
    }
}

impl<Sym, PS, PS2, C> ParametricRule for PRule<Sym, PS, PS2, C>
    where Sym: Alphabet,
          PS: ParametricSymbol<Sym = Sym, Param = C::Expr>,
          PS2: ParametricSymbol<Sym = Sym, Param = <C::Expr as Expression>::Element>,
          C: Condition
{
    type InSym = PS;
    type OutSym = PS2;

    /// Tries to apply the rule and if applicable, produces a successor.
    fn apply(&self, psym: &PS2) -> Result<Vec<PS2>, RuleError> {
        if self.arity != psym.params().len() {
            Err(RuleError::RuleArityMismatch)
        } else if self.symbol.eq(psym.symbol()) {
            match self.condition.evaluate(psym.params()) {
                Ok(true) => {
                    let mut new_symbol_string = Vec::with_capacity(self.production.len());

                    // evaluate all parameters of all symbols in the production
                    for prod_sym in self.production.iter() {
                        match PS2::new_from_result_iter(prod_sym.symbol().clone(),
                                                        prod_sym.params().iter().map(|expr| {
                                                            expr.evaluate(psym.params())
                                                        })) {
                            Some(Ok(new_sym)) => {
                                new_symbol_string.push(new_sym);
                            }
                            Some(Err(e)) => {
                                return Err(RuleError::ExprFailed(e));
                            }
                            None => {
                                return Err(RuleError::ArityMismatch);
                            }
                        }
                    }

                    Ok(new_symbol_string)
                }
                Ok(false) => Err(RuleError::ConditionFalse),
                _ => Err(RuleError::ConditionFailed),
            }
        } else {
            Err(RuleError::SymbolMismatch)
        }
    }

    fn symbol(&self) -> &<Self::InSym as ParametricSymbol>::Sym {
        &self.symbol
    }
}

#[test]
fn test_rule_apply() {
    use expression_num::NumExpr;
    use expression::cond::Cond;
    let expr_s = PSym::new_from_vec('P', vec![NumExpr::Const(123u32)]).unwrap();

    let rule = PRule::<_, PSym<_, NumExpr<u32>>, PSym<_, u32>, _>::new('A',
                                                                       Cond::True,
                                                                       vec![expr_s.clone()],
                                                                       1);

    let param_s = PSym::new_from_vec('P', vec![123u32]).unwrap();
    assert_eq!(Err(RuleError::SymbolMismatch), rule.apply(&param_s));

    let param_s = PSym::new_from_vec('A', vec![123u32]).unwrap();
    let result_s = PSym::new_from_vec('P', vec![123u32]).unwrap();
    assert_eq!(Ok(vec![result_s]), rule.apply(&param_s));

    let rule = PRule::<_, PSym<_, NumExpr<u32>>, PSym<_, u32>, _>::new('A',
                                                                       Cond::False,
                                                                       vec![expr_s.clone()],
                                                                       1);
    assert_eq!(Err(RuleError::ConditionFalse), rule.apply(&param_s));
}

pub trait ParametricSystem {
    type Rule: ParametricRule;

    fn apply_first_rule(&self, sym: &<Self::Rule as ParametricRule>::OutSym) -> Option<Vec<<Self::Rule as ParametricRule>::OutSym>>;

    /// Apply in parallel the first matching rule to each symbol in the string.
    /// Returns the total number of rule applications.
    fn develop_next(&self, axiom: &Vec<<Self::Rule as ParametricRule>::OutSym>) -> (Vec<<Self::Rule as ParametricRule>::OutSym>, usize) {
        let mut expanded = Vec::new();
        let mut rule_applications = 0;

        for sym in axiom.iter() {
            match self.apply_first_rule(sym) {
                Some(successor) => {
                    expanded.extend(successor);
                    rule_applications += 1;
                    // XXX: Count rule applications of the matching rule.
                }

                None => {
                    expanded.push(sym.clone());
                }
            }
        }

        (expanded, rule_applications)
    }

    /// Develop the system starting with `axiom` up to `max_iterations`. Return iteration count.
    fn develop(&self,
               axiom: Vec<<Self::Rule as ParametricRule>::OutSym>,
               max_iterations: usize)
               -> (Vec<<Self::Rule as ParametricRule>::OutSym>, usize) {
        let mut current = axiom;

        for iter in 0..max_iterations {
            let (next, rule_applications) = self.develop_next(&current);
            if rule_applications == 0 {
                return (current, iter);
            }
            current = next;
        }
        return (current, max_iterations);
    }
}

/// Apply first matching rule and return expanded successor.
pub fn apply_first_rule<R>(rules: &[R],
                           sym: &<R as ParametricRule>::OutSym)
                           -> Option<Vec<<R as ParametricRule>::OutSym>>
    where R: ParametricRule
{
    for rule in rules {
        if let Ok(successor) = rule.apply(sym) {
            return Some(successor);
        }
    }
    return None;
}

#[derive(Debug, Clone)]
pub struct PSystem<R>
    where R: ParametricRule
{
    rules: Vec<R>,
}

impl<R> PSystem<R> where R: ParametricRule
{
    pub fn new() -> PSystem<R> {
        PSystem { rules: vec![] }
    }

    pub fn add_rule(&mut self, rule: R) {
        self.rules.push(rule);
    }
}

impl<R> ParametricSystem for PSystem<R> where R: ParametricRule
{
    type Rule = R;

    /// Apply first matching rule and return expanded successor.
    fn apply_first_rule(&self, sym: &<Self::Rule as ParametricRule>::OutSym) -> Option<Vec<<Self::Rule as ParametricRule>::OutSym>> {
        apply_first_rule(&self.rules, sym)
    }
}
<commit_msg>Implement PDualMapSystem<commit_after>use std::fmt::Debug;
use std::marker::PhantomData;
use super::{Alphabet, DualAlphabet};
use expression::{Expression, Condition, ExpressionError};
use std::collections::BTreeMap;

#[derive(Debug, Eq, PartialEq)]
pub enum RuleError {
    SymbolMismatch,
    RuleArityMismatch,
    ArityMismatch,
    ConditionFalse,
    ConditionFailed,
    ExprFailed(ExpressionError),
}

pub trait ParametricSymbol: Clone + PartialEq + Debug
{
    type Sym: Alphabet;
    type Param: Clone + Debug + PartialEq;

    fn symbol(&self) -> &Self::Sym;
    fn symbol_mut(&mut self) -> &mut Self::Sym;

    fn params(&self) -> &[Self::Param];
    fn params_mut(&mut self) -> &mut [Self::Param];

    /// Construct a new ParametricSymbol. If the iterator contains a wrong
    /// number of parameters, return None.
    fn new_from_result_iter<I, E>(symbol: Self::Sym, iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>;

    fn new_from_iter<I>(symbol: Self::Sym, iter: I) -> Option<Self>
        where I: Iterator<Item = Self::Param>
    {
        match Self::new_from_result_iter::<_, ()>(symbol, iter.map(|i| Ok(i))) {
            Some(Ok(res)) => Some(res),
            Some(Err(())) => panic!(),
            None => None,
        }
    }

    fn new_from_vec(symbol: Self::Sym, vec: Vec<Self::Param>) -> Option<Self> {
        Self::new_from_iter(symbol, vec.into_iter())
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct PSym<Sym: Alphabet, Param: Clone + Debug + PartialEq> {
    symbol: Sym,
    params: Vec<Param>,
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> ParametricSymbol for PSym<Sym, Param> {
    type Sym = Sym;
    type Param = Param;

    fn symbol(&self) -> &Self::Sym {
        &self.symbol
    }
    fn symbol_mut(&mut self) -> &mut Self::Sym {
        &mut self.symbol
    }
    fn params(&self) -> &[Self::Param] {
        &self.params
    }
    fn params_mut(&mut self) -> &mut [Self::Param] {
        &mut self.params
    }

    fn new_from_result_iter<I, E>(symbol: Self::Sym, iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>
    {
        let mut params = Vec::with_capacity(iter.size_hint().0);
        for p in iter {
            match p {
                Ok(p) => params.push(p),
                Err(e) => return Some(Err(e)),
            }
        }
        Some(Ok(PSym {
            symbol: symbol,
            params: params,
        }))
    }
}

#[derive(Debug, PartialEq)]
pub struct PSym1<Sym: Alphabet, Param: Clone + Debug + PartialEq> {
    symbol: Sym,
    params: [Param; 1],
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> Clone for PSym1<Sym, Param> {
    fn clone(&self) -> Self {
        PSym1 {
            symbol: self.symbol.clone(),
            params: [self.params[0].clone()],
        }
    }
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> ParametricSymbol for PSym1<Sym, Param> {
    type Sym = Sym;
    type Param = Param;

    fn symbol(&self) -> &Self::Sym {
        &self.symbol
    }
    fn symbol_mut(&mut self) -> &mut Self::Sym {
        &mut self.symbol
    }
    fn params(&self) -> &[Self::Param] {
        &self.params
    }
    fn params_mut(&mut self) -> &mut [Self::Param] {
        &mut self.params
    }

    fn new_from_result_iter<I, E>(symbol: Self::Sym, mut iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>
    {
        let p1 = match iter.next() {
            Some(Ok(p)) => p,
            Some(Err(e)) => return Some(Err(e)),
            None => return None,
        };
        if let Some(_) = iter.next() {
            return None;
        }

        Some(Ok(PSym1 {
            symbol: symbol,
            params: [p1],
        }))
    }
}

#[derive(Debug, PartialEq)]
pub struct PSym2<Sym: Alphabet, Param: Clone + Debug + PartialEq> {
    symbol: Sym,
    params: [Param; 2],
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> Clone for PSym2<Sym, Param> {
    fn clone(&self) -> Self {
        PSym2 {
            symbol: self.symbol.clone(),
            params: [self.params[0].clone(), self.params[1].clone()],
        }
    }
}

impl<Sym: Alphabet, Param: Clone + Debug + PartialEq> ParametricSymbol for PSym2<Sym, Param> {
    type Sym = Sym;
    type Param = Param;

    fn symbol(&self) -> &Self::Sym {
        &self.symbol
    }
    fn symbol_mut(&mut self) -> &mut Self::Sym {
        &mut self.symbol
    }
    fn params(&self) -> &[Self::Param] {
        &self.params
    }
    fn params_mut(&mut self) -> &mut [Self::Param] {
        &mut self.params
    }

    fn new_from_result_iter<I, E>(symbol: Self::Sym, mut iter: I) -> Option<Result<Self, E>>
        where I: Iterator<Item = Result<Self::Param, E>>
    {
        let p1 = match iter.next() {
            Some(Ok(p)) => p,
            Some(Err(e)) => return Some(Err(e)),
            None => return None,
        };
        let p2 = match iter.next() {
            Some(Ok(p)) => p,
            Some(Err(e)) => return Some(Err(e)),
            None => return None,
        };
        if let Some(_) = iter.next() {
            return None;
        }

        Some(Ok(PSym2 {
            symbol: symbol,
            params: [p1, p2],
        }))
    }
}

pub trait ParametricRule: Clone + Debug
{
    type InSym: ParametricSymbol;
    type OutSym: ParametricSymbol;

    fn apply(&self, psym: &Self::OutSym) -> Result<Vec<Self::OutSym>, RuleError>;

    fn symbol(&self) -> &<Self::InSym as ParametricSymbol>::Sym;
}

#[derive(Debug, Clone)]
pub struct PRule<Sym, PS, PS2, C>
    where Sym: Alphabet,
          PS: ParametricSymbol<Sym = Sym, Param = C::Expr>,
          PS2: ParametricSymbol<Sym = Sym, Param = <C::Expr as Expression>::Element>,
          C: Condition
{
    pub symbol: Sym,
    pub condition: C,
    pub production: Vec<PS>,
    pub arity: usize,
    _marker: PhantomData<PS2>,
}

impl<Sym, PS, PS2, C> PRule<Sym, PS, PS2, C>
    where Sym: Alphabet,
          PS: ParametricSymbol<Sym = Sym, Param = C::Expr>,
          PS2: ParametricSymbol<Sym = Sym, Param = <C::Expr as Expression>::Element>,
          C: Condition
{
    pub fn new(sym: Sym, cond: C, prod: Vec<PS>, arity: usize) -> PRule<Sym, PS, PS2, C> {
        PRule {
            symbol: sym,
            condition: cond,
            production: prod,
            arity: arity,
            _marker: PhantomData,
        }
    }
}

impl<Sym, PS, PS2, C> ParametricRule for PRule<Sym, PS, PS2, C>
    where Sym: Alphabet,
          PS: ParametricSymbol<Sym = Sym, Param = C::Expr>,
          PS2: ParametricSymbol<Sym = Sym, Param = <C::Expr as Expression>::Element>,
          C: Condition
{
    type InSym = PS;
    type OutSym = PS2;

    /// Tries to apply the rule and if applicable, produces a successor.
    fn apply(&self, psym: &PS2) -> Result<Vec<PS2>, RuleError> {
        if self.arity != psym.params().len() {
            Err(RuleError::RuleArityMismatch)
        } else if self.symbol.eq(psym.symbol()) {
            match self.condition.evaluate(psym.params()) {
                Ok(true) => {
                    let mut new_symbol_string = Vec::with_capacity(self.production.len());

                    // evaluate all parameters of all symbols in the production
                    for prod_sym in self.production.iter() {
                        match PS2::new_from_result_iter(prod_sym.symbol().clone(),
                                                        prod_sym.params().iter().map(|expr| {
                                                            expr.evaluate(psym.params())
                                                        })) {
                            Some(Ok(new_sym)) => {
                                new_symbol_string.push(new_sym);
                            }
                            Some(Err(e)) => {
                                return Err(RuleError::ExprFailed(e));
                            }
                            None => {
                                return Err(RuleError::ArityMismatch);
                            }
                        }
                    }

                    Ok(new_symbol_string)
                }
                Ok(false) => Err(RuleError::ConditionFalse),
                _ => Err(RuleError::ConditionFailed),
            }
        } else {
            Err(RuleError::SymbolMismatch)
        }
    }

    fn symbol(&self) -> &<Self::InSym as ParametricSymbol>::Sym {
        &self.symbol
    }
}

#[test]
fn test_rule_apply() {
    use expression_num::NumExpr;
    use expression::cond::Cond;
    let expr_s = PSym::new_from_vec('P', vec![NumExpr::Const(123u32)]).unwrap();

    let rule = PRule::<_, PSym<_, NumExpr<u32>>, PSym<_, u32>, _>::new('A',
                                                                       Cond::True,
                                                                       vec![expr_s.clone()],
                                                                       1);

    let param_s = PSym::new_from_vec('P', vec![123u32]).unwrap();
    assert_eq!(Err(RuleError::SymbolMismatch), rule.apply(&param_s));

    let param_s = PSym::new_from_vec('A', vec![123u32]).unwrap();
    let result_s = PSym::new_from_vec('P', vec![123u32]).unwrap();
    assert_eq!(Ok(vec![result_s]), rule.apply(&param_s));

    let rule = PRule::<_, PSym<_, NumExpr<u32>>, PSym<_, u32>, _>::new('A',
                                                                       Cond::False,
                                                                       vec![expr_s.clone()],
                                                                       1);
    assert_eq!(Err(RuleError::ConditionFalse), rule.apply(&param_s));
}

pub trait ParametricSystem {
    type Rule: ParametricRule;

    fn apply_first_rule(&self, sym: &<Self::Rule as ParametricRule>::OutSym) -> Option<Vec<<Self::Rule as ParametricRule>::OutSym>>;

    /// Apply in parallel the first matching rule to each symbol in the string.
    /// Returns the total number of rule applications.
    fn develop_next(&self, axiom: &Vec<<Self::Rule as ParametricRule>::OutSym>) -> (Vec<<Self::Rule as ParametricRule>::OutSym>, usize) {
        let mut expanded = Vec::new();
        let mut rule_applications = 0;

        for sym in axiom.iter() {
            match self.apply_first_rule(sym) {
                Some(successor) => {
                    expanded.extend(successor);
                    rule_applications += 1;
                    // XXX: Count rule applications of the matching rule.
                }

                None => {
                    expanded.push(sym.clone());
                }
            }
        }

        (expanded, rule_applications)
    }

    /// Develop the system starting with `axiom` up to `max_iterations`. Return iteration count.
    fn develop(&self,
               axiom: Vec<<Self::Rule as ParametricRule>::OutSym>,
               max_iterations: usize)
               -> (Vec<<Self::Rule as ParametricRule>::OutSym>, usize) {
        let mut current = axiom;

        for iter in 0..max_iterations {
            let (next, rule_applications) = self.develop_next(&current);
            if rule_applications == 0 {
                return (current, iter);
            }
            current = next;
        }
        return (current, max_iterations);
    }
}

/// Apply first matching rule and return expanded successor.
pub fn apply_first_rule<R>(rules: &[R],
                           sym: &<R as ParametricRule>::OutSym)
                           -> Option<Vec<<R as ParametricRule>::OutSym>>
    where R: ParametricRule
{
    for rule in rules {
        if let Ok(successor) = rule.apply(sym) {
            return Some(successor);
        }
    }
    return None;
}

#[derive(Debug, Clone)]
pub struct PSystem<R>
    where R: ParametricRule
{
    rules: Vec<R>,
}

impl<R> PSystem<R> where R: ParametricRule
{
    pub fn new() -> PSystem<R> {
        PSystem { rules: vec![] }
    }

    pub fn add_rule(&mut self, rule: R) {
        self.rules.push(rule);
    }
}

impl<R> ParametricSystem for PSystem<R> where R: ParametricRule
{
    type Rule = R;

    /// Apply first matching rule and return expanded successor.
    fn apply_first_rule(&self, sym: &<Self::Rule as ParametricRule>::OutSym) -> Option<Vec<<Self::Rule as ParametricRule>::OutSym>> {
        apply_first_rule(&self.rules, sym)
    }
}

/// Distinguishes between terminal symbols and non-terminals.  Rules are only allowed on
/// non-terminals.
#[derive(Debug, Clone)]
pub struct PDualMapSystem<A, R>
    where
          A: DualAlphabet,
          R: ParametricRule,
          <R as ParametricRule>::InSym: ParametricSymbol<Sym=A>,
          <R as ParametricRule>::OutSym: ParametricSymbol<Sym=A>,
{
    rules: BTreeMap<A::NonTerminal, Vec<R>>,
}

impl<A, R>  PDualMapSystem<A, R>
    where
          A: DualAlphabet,
          R: ParametricRule,
          <R as ParametricRule>::InSym: ParametricSymbol<Sym=A>,
          <R as ParametricRule>::OutSym: ParametricSymbol<Sym=A>,
{
    pub fn new() -> PDualMapSystem<A,R> {
        PDualMapSystem {
            rules: BTreeMap::new()
        }
    }

    pub fn add_rule(&mut self, rule: R) {
        assert!(rule.symbol().nonterminal().is_some());
    }
}

impl<A, R> ParametricSystem for PDualMapSystem<A, R>
    where
          A: DualAlphabet,
          R: ParametricRule,
          <R as ParametricRule>::InSym: ParametricSymbol<Sym=A>,
          <R as ParametricRule>::OutSym: ParametricSymbol<Sym=A>,
{
    type Rule = R;

    fn apply_first_rule(&self, sym: &<Self::Rule as ParametricRule>::OutSym) -> Option<Vec<<Self::Rule as ParametricRule>::OutSym>> {
        match sym.symbol().nonterminal()
        {
            // We don't store rules for terminal symbols.
            None => None,

            // Only apply rules for non-terminals
            Some(id) => {
                self.rules.get(&id).and_then(|rules| apply_first_rule(&rules[..], sym))
            }
        }
    }
}
<|endoftext|>