<commit_before>//! CLI tool to use the functions provided by the [cretonne-wasm](../cton_wasm/index.html) crate.
//!
//! Reads Wasm binary files (one Wasm module per file), translates the functions' code to Cretonne
//! IL. Can also executes the `start` function of the module by laying out the memories, globals
//! and tables, then emitting the translated code with hardcoded addresses to memory.

use cton_wasm::{translate_module, DummyRuntime, WasmRuntime};
use cton_reader::{parse_options, Location};
use std::path::PathBuf;
use cretonne::Context;
use cretonne::settings::{self, FlagsOrIsa};
use cretonne::isa::{self, TargetIsa};
use std::fs::File;
use std::error::Error;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
use std::process::Command;
use tempdir::TempDir;
use term;
use utils::{pretty_verifier_error, pretty_error};

macro_rules! vprintln {
    ($x: expr, $($tts:tt)*) => {
        if $x {
            println!($($tts)*);
        }
    }
}

macro_rules! vprint {
    ($x: expr, $($tts:tt)*) => {
        if $x {
            print!($($tts)*);
        }
    }
}

fn read_wasm_file(path: PathBuf) -> Result<Vec<u8>, io::Error> {
    let mut buf: Vec<u8> = Vec::new();
    let file = File::open(path)?;
    let mut buf_reader = BufReader::new(file);
    buf_reader.read_to_end(&mut buf)?;
    Ok(buf)
}

enum OwnedFlagsOrIsa {
    Flags(settings::Flags),
    Isa(Box<TargetIsa>),
}

pub fn run(
    files: Vec<String>,
    flag_verbose: bool,
    flag_just_decode: bool,
    flag_check_translation: bool,
    flag_print: bool,
    flag_set: Vec<String>,
    flag_isa: String,
) -> Result<(), String> {
    let mut flag_builder = settings::builder();
    parse_options(
        flag_set.iter().map(|x| x.as_str()),
        &mut flag_builder,
        &Location { line_number: 0 },
    ).map_err(|err| err.to_string())?;

    let mut words = flag_isa.trim().split_whitespace();
    // Look for `isa foo`.
    let owned_fisa = if let Some(isa_name) = words.next() {
        let isa_builder = isa::lookup(isa_name).map_err(|err| match err {
            isa::LookupError::Unknown => format!("unknown ISA '{}'", isa_name),
            isa::LookupError::Unsupported => format!("support for ISA '{}' not enabled", isa_name),
        })?;
        OwnedFlagsOrIsa::Isa(isa_builder.finish(settings::Flags::new(&flag_builder)))
    } else {
        OwnedFlagsOrIsa::Flags(settings::Flags::new(&flag_builder))
    };
    let fisa = match owned_fisa {
        OwnedFlagsOrIsa::Flags(ref flags) => FlagsOrIsa::from(flags),
        OwnedFlagsOrIsa::Isa(ref isa) => FlagsOrIsa::from(&**isa),
    };

    for filename in files {
        let path = Path::new(&filename);
        let name = String::from(path.as_os_str().to_string_lossy());
        handle_module(
            flag_verbose,
            flag_just_decode,
            flag_check_translation,
            flag_print,
            path.to_path_buf(),
            name,
            &fisa,
        )?;
    }
    Ok(())
}

fn handle_module(
    flag_verbose: bool,
    flag_just_decode: bool,
    flag_check_translation: bool,
    flag_print: bool,
    path: PathBuf,
    name: String,
    fisa: &FlagsOrIsa,
) -> Result<(), String> {
    let mut terminal = term::stdout().unwrap();
    terminal.fg(term::color::YELLOW).unwrap();
    vprint!(flag_verbose, "Handling: ");
    terminal.reset().unwrap();
    vprintln!(flag_verbose, "\"{}\"", name);
    terminal.fg(term::color::MAGENTA).unwrap();
    vprint!(flag_verbose, "Translating... ");
    terminal.reset().unwrap();
    let data = match path.extension() {
        None => {
            return Err(String::from("the file extension is not wasm or wat"));
        }
        Some(ext) => {
            match ext.to_str() {
                Some("wasm") => {
                    read_wasm_file(path.clone()).map_err(|err| {
                        String::from(err.description())
                    })?
                }
                Some("wat") => {
                    let tmp_dir = TempDir::new("cretonne-wasm").unwrap();
                    let file_path = tmp_dir.path().join("module.wasm");
                    File::create(file_path.clone()).unwrap();
                    Command::new("wat2wasm")
                        .arg(path.clone())
                        .arg("-o")
                        .arg(file_path.to_str().unwrap())
                        .output()
                        .or_else(|e| if let io::ErrorKind::NotFound = e.kind() {
                            return Err(String::from("wat2wasm not found"));
                        } else {
                            return Err(String::from(e.description()));
                        })
                        .unwrap();
                    read_wasm_file(file_path).map_err(|err| {
                        String::from(err.description())
                    })?
                }
                None | Some(&_) => {
                    return Err(String::from("the file extension is not wasm or wat"));
                }
            }
        }
    };
    let mut dummy_runtime = DummyRuntime::with_flags(fisa.flags.clone());
    let translation = {
        let runtime: &mut WasmRuntime = &mut dummy_runtime;
        translate_module(&data, runtime)?
    };
    terminal.fg(term::color::GREEN).unwrap();
    vprintln!(flag_verbose, "ok");
    terminal.reset().unwrap();
    if flag_just_decode {
        return Ok(());
    }
    terminal.fg(term::color::MAGENTA).unwrap();
    if flag_check_translation {
        vprint!(flag_verbose, "Checking... ");
    } else {
        vprint!(flag_verbose, "Compiling... ");
    }
    terminal.reset().unwrap();
    for func in &translation.functions {
        let mut context = Context::new();
        context.func = func.clone();
        if flag_check_translation {
            context.verify(*fisa).map_err(|err| {
                pretty_verifier_error(&context.func, fisa.isa, err)
            })?;
            continue;
        }
        if let Some(isa) = fisa.isa {
            context.compile(isa).map_err(|err| {
                pretty_error(&context.func, fisa.isa, err)
            })?;
        } else {
            return Err(String::from("compilation requires a target isa"));
        }
        if flag_print {
            vprintln!(flag_verbose, "");
            println!("{}", context.func.display(fisa.isa));
            vprintln!(flag_verbose, "");
        }
    }
    terminal.fg(term::color::GREEN).unwrap();
    vprintln!(flag_verbose, "ok");
    terminal.reset().unwrap();
    Ok(())
}
<commit_msg>Make the "wat2wasm" error message not panic.<commit_after>//! CLI tool to use the functions provided by the [cretonne-wasm](../cton_wasm/index.html) crate.
//!
//! Reads Wasm binary files (one Wasm module per file), translates the functions' code to Cretonne
//! IL. Can also executes the `start` function of the module by laying out the memories, globals
//! and tables, then emitting the translated code with hardcoded addresses to memory.

use cton_wasm::{translate_module, DummyRuntime, WasmRuntime};
use cton_reader::{parse_options, Location};
use std::path::PathBuf;
use cretonne::Context;
use cretonne::settings::{self, FlagsOrIsa};
use cretonne::isa::{self, TargetIsa};
use std::fs::File;
use std::error::Error;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
use std::process::Command;
use tempdir::TempDir;
use term;
use utils::{pretty_verifier_error, pretty_error};

macro_rules! vprintln {
    ($x: expr, $($tts:tt)*) => {
        if $x {
            println!($($tts)*);
        }
    }
}

macro_rules! vprint {
    ($x: expr, $($tts:tt)*) => {
        if $x {
            print!($($tts)*);
        }
    }
}

fn read_wasm_file(path: PathBuf) -> Result<Vec<u8>, io::Error> {
    let mut buf: Vec<u8> = Vec::new();
    let file = File::open(path)?;
    let mut buf_reader = BufReader::new(file);
    buf_reader.read_to_end(&mut buf)?;
    Ok(buf)
}

enum OwnedFlagsOrIsa {
    Flags(settings::Flags),
    Isa(Box<TargetIsa>),
}

pub fn run(
    files: Vec<String>,
    flag_verbose: bool,
    flag_just_decode: bool,
    flag_check_translation: bool,
    flag_print: bool,
    flag_set: Vec<String>,
    flag_isa: String,
) -> Result<(), String> {
    let mut flag_builder = settings::builder();
    parse_options(
        flag_set.iter().map(|x| x.as_str()),
        &mut flag_builder,
        &Location { line_number: 0 },
    ).map_err(|err| err.to_string())?;

    let mut words = flag_isa.trim().split_whitespace();
    // Look for `isa foo`.
    let owned_fisa = if let Some(isa_name) = words.next() {
        let isa_builder = isa::lookup(isa_name).map_err(|err| match err {
            isa::LookupError::Unknown => format!("unknown ISA '{}'", isa_name),
            isa::LookupError::Unsupported => format!("support for ISA '{}' not enabled", isa_name),
        })?;
        OwnedFlagsOrIsa::Isa(isa_builder.finish(settings::Flags::new(&flag_builder)))
    } else {
        OwnedFlagsOrIsa::Flags(settings::Flags::new(&flag_builder))
    };
    let fisa = match owned_fisa {
        OwnedFlagsOrIsa::Flags(ref flags) => FlagsOrIsa::from(flags),
        OwnedFlagsOrIsa::Isa(ref isa) => FlagsOrIsa::from(&**isa),
    };

    for filename in files {
        let path = Path::new(&filename);
        let name = String::from(path.as_os_str().to_string_lossy());
        handle_module(
            flag_verbose,
            flag_just_decode,
            flag_check_translation,
            flag_print,
            path.to_path_buf(),
            name,
            &fisa,
        )?;
    }
    Ok(())
}

fn handle_module(
    flag_verbose: bool,
    flag_just_decode: bool,
    flag_check_translation: bool,
    flag_print: bool,
    path: PathBuf,
    name: String,
    fisa: &FlagsOrIsa,
) -> Result<(), String> {
    let mut terminal = term::stdout().unwrap();
    terminal.fg(term::color::YELLOW).unwrap();
    vprint!(flag_verbose, "Handling: ");
    terminal.reset().unwrap();
    vprintln!(flag_verbose, "\"{}\"", name);
    terminal.fg(term::color::MAGENTA).unwrap();
    vprint!(flag_verbose, "Translating... ");
    terminal.reset().unwrap();
    let data = match path.extension() {
        None => {
            return Err(String::from("the file extension is not wasm or wat"));
        }
        Some(ext) => {
            match ext.to_str() {
                Some("wasm") => {
                    read_wasm_file(path.clone()).map_err(|err| {
                        String::from(err.description())
                    })?
                }
                Some("wat") => {
                    let tmp_dir = TempDir::new("cretonne-wasm").unwrap();
                    let file_path = tmp_dir.path().join("module.wasm");
                    File::create(file_path.clone()).unwrap();
                    Command::new("wat2wasm")
                        .arg(path.clone())
                        .arg("-o")
                        .arg(file_path.to_str().unwrap())
                        .output()
                        .or_else(|e| if let io::ErrorKind::NotFound = e.kind() {
                            return Err(String::from("wat2wasm not found"));
                        } else {
                            return Err(String::from(e.description()));
                        })?;
                    read_wasm_file(file_path).map_err(|err| {
                        String::from(err.description())
                    })?
                }
                None | Some(&_) => {
                    return Err(String::from("the file extension is not wasm or wat"));
                }
            }
        }
    };
    let mut dummy_runtime = DummyRuntime::with_flags(fisa.flags.clone());
    let translation = {
        let runtime: &mut WasmRuntime = &mut dummy_runtime;
        translate_module(&data, runtime)?
    };
    terminal.fg(term::color::GREEN).unwrap();
    vprintln!(flag_verbose, "ok");
    terminal.reset().unwrap();
    if flag_just_decode {
        return Ok(());
    }
    terminal.fg(term::color::MAGENTA).unwrap();
    if flag_check_translation {
        vprint!(flag_verbose, "Checking... ");
    } else {
        vprint!(flag_verbose, "Compiling... ");
    }
    terminal.reset().unwrap();
    for func in &translation.functions {
        let mut context = Context::new();
        context.func = func.clone();
        if flag_check_translation {
            context.verify(*fisa).map_err(|err| {
                pretty_verifier_error(&context.func, fisa.isa, err)
            })?;
            continue;
        }
        if let Some(isa) = fisa.isa {
            context.compile(isa).map_err(|err| {
                pretty_error(&context.func, fisa.isa, err)
            })?;
        } else {
            return Err(String::from("compilation requires a target isa"));
        }
        if flag_print {
            vprintln!(flag_verbose, "");
            println!("{}", context.func.display(fisa.isa));
            vprintln!(flag_verbose, "");
        }
    }
    terminal.fg(term::color::GREEN).unwrap();
    vprintln!(flag_verbose, "ok");
    terminal.reset().unwrap();
    Ok(())
}
<|endoftext|>


<commit_before>use glm;
use moho::errors::*;
use moho::input_manager::*;
use moho::resource_manager::*;
use moho::MohoEngine;
use sdl2::keyboard::Keycode;
use sdl2::mouse::MouseButton;

use meteor::{Meteor, MeteorState};
use planet::{Planet, PlanetKind};

pub struct MasterSmasher<E: MohoEngine> {
    meteor: Meteor<E::Renderer>,
    planets: Vec<Planet<E::Renderer>>,
    background: TextureData<<E::Renderer as Renderer>::Texture>,
    input_manager: InputManager<E::EventPump>,
    renderer: ResourceManager<E::Renderer>,
}

impl<E: MohoEngine> MasterSmasher<E> {
    pub fn new(mut renderer: ResourceManager<E::Renderer>,
               input_manager: InputManager<E::EventPump>)
               -> Result<Self> {
        let background = renderer.load_texture("resources/background_game.png")?;
        let blue_center = glm::ivec2(840, 478);
        let white_center = glm::ivec2(346, 298);
        let meteor_center = glm::ivec2(130, 402);
        let blue_planet = Planet::new(blue_center, 700., 215., PlanetKind::BLUE, &mut renderer)?;
        let white_planet = Planet::new(white_center, 400., 175., PlanetKind::WHITE, &mut renderer)?;
        let meteor = Meteor::new(meteor_center, &mut renderer)?;

        Ok(MasterSmasher {
            meteor: meteor,
            planets: vec![white_planet, blue_planet],
            background: background,
            input_manager: input_manager,
            renderer: renderer,
        })
    }

    pub fn run(&mut self) -> Result<()> {
        while !self.game_quit() {
            self.update();
            self.draw()?;
        }
        Ok(())
    }

    fn update(&mut self) {
        self.input_manager.update();
        if self.game_quit() {
            return;
        }

        match self.meteor.state() {
            &MeteorState::UNLAUNCHED => {
                self.meteor.update_target(self.input_manager.mouse_coords());
                if self.input_manager.did_click_mouse(MouseButton::Left) {
                    self.meteor.launch();
                }
            }
            &MeteorState::LAUNCHED => {
                if self.input_manager.did_press_key(Keycode::R) {
                    self.meteor.explode();
                }
            }
            &MeteorState::EXPLODED => {}
        }

        self.meteor.update(&self.planets)
    }

    fn game_quit(&self) -> bool {
        self.input_manager.game_quit() || self.input_manager.is_key_down(Keycode::Escape)
    }

    fn draw(&mut self) -> Result<()> {
        self.renderer.clear();
        self.renderer.draw(&*self.background.texture, None, None, None)?;
        for planet in &self.planets {
            planet.draw(&mut self.renderer)?;
        }
        self.meteor.draw(&mut self.renderer)?;
        self.renderer.present();
        Ok(())
    }
}
<commit_msg>adding stars WIP; no collision yet<commit_after>use glm;
use moho::errors::*;
use moho::input_manager::*;
use moho::resource_manager::*;
use moho::MohoEngine;
use sdl2::keyboard::Keycode;
use sdl2::mouse::MouseButton;

use meteor::{Meteor, MeteorState};
use planet::{Planet, PlanetKind};
use self::star::Star;

mod star {
    use glm;
    use moho::errors::*;
    use moho::resource_manager::{Renderer, ResourceManager, TextureData};

    use circle::Circle;
    use animation::Animation;

    use std::cmp;
    use std::time::Duration;
    use std::rc::Rc;

    pub struct Star<R: Renderer> {
        drawable: Drawable<R>,
        object: Object,
    }

    impl<R: Renderer> Star<R> {
        pub fn new(center: glm::IVec2, resource_manager: &ResourceManager<R>) -> Result<Self> {
            let drawable = Drawable::new(center, resource_manager)?;
            let dims = drawable.dims();
            let radius = cmp::min(dims.x, dims.y) as f64 / 2.;
            let object = Object::new(glm::to_dvec2(center), radius);
            let star = Star {
                drawable: drawable,
                object: object,
            };

            Ok(star)
        }

        pub fn update(&mut self) {
            self.drawable.animate();
        }

        pub fn draw(&self, renderer: &mut ResourceManager<R>) -> Result<()> {
            self.drawable.draw(renderer)
        }
    }

    struct Drawable<R: Renderer> {
        star: Rc<R::Texture>,
        explosion: Rc<R::Texture>,
        animation: Animation,
        explosion_animation: Animation,
        center: glm::IVec2,
        star_dims: glm::UVec2,
    }

    impl<R: Renderer> Drawable<R> {
        fn new(center: glm::IVec2, resource_manager: &ResourceManager<R>) -> Result<Self> {
            let star = resource_manager.load_texture("resources/star.png")?;
            let explosion = resource_manager.load_texture("resources/explosion_small.png")?;
            let star_duration = Duration::from_millis(150);
            let explosion_duration = Duration::from_millis(100);
            let star_dims = glm::uvec2(star.dims.x / 2, star.dims.y);
            let explosion_dims = glm::uvec2(explosion.dims.x / 10, explosion.dims.y);
            let animation = Animation::new(2, star_duration, star.dims, true);
            let explosion_animation = Animation::new(10, explosion_duration, explosion_dims, false);
            let drawable = Drawable {
                star: star.texture,
                explosion: explosion.texture,
                animation: animation,
                explosion_animation: explosion_animation,
                center: center,
                star_dims: star_dims,
            };

            Ok(drawable)
        }

        fn dims(&self) -> glm::UVec2 {
            self.star_dims
        }

        fn animate(&mut self) {
            self.animation.update();
        }

        fn animate_explosion(&mut self) {
            self.explosion_animation.update();
        }

        fn draw(&self, renderer: &mut ResourceManager<R>) -> Result<()> {
            let src = Some(self.animation.src_rect());
            renderer.draw_from_center(&*self.star, src, self.center, self.star_dims, None)
        }

        fn is_exploding(&self) -> bool {
            self.explosion_animation.is_active()
        }
    }

    struct Object {
        body: Circle,
    }

    impl Object {
        fn new(center: glm::DVec2, radius: f64) -> Self {
            let body = Circle {
                center: center,
                radius: radius,
            };

            Object { body: body }
        }
    }
}

pub struct MasterSmasher<E: MohoEngine> {
    meteor: Meteor<E::Renderer>,
    planets: Vec<Planet<E::Renderer>>,
    stars: Vec<Star<E::Renderer>>,
    background: TextureData<<E::Renderer as Renderer>::Texture>,
    input_manager: InputManager<E::EventPump>,
    renderer: ResourceManager<E::Renderer>,
}

impl<E: MohoEngine> MasterSmasher<E> {
    pub fn new(mut renderer: ResourceManager<E::Renderer>,
               input_manager: InputManager<E::EventPump>)
               -> Result<Self> {
        let background = renderer.load_texture("resources/background_game.png")?;
        let blue_center = glm::ivec2(840, 478);
        let white_center = glm::ivec2(346, 298);
        let meteor_center = glm::ivec2(130, 402);
        let star_center = glm::ivec2(500, 130);
        let blue_planet = Planet::new(blue_center, 700., 215., PlanetKind::BLUE, &mut renderer)?;
        let white_planet = Planet::new(white_center, 400., 175., PlanetKind::WHITE, &mut renderer)?;
        let meteor = Meteor::new(meteor_center, &mut renderer)?;
        let star = Star::new(star_center, &mut renderer)?;

        Ok(MasterSmasher {
            meteor: meteor,
            planets: vec![white_planet, blue_planet],
            stars: vec![star],
            background: background,
            input_manager: input_manager,
            renderer: renderer,
        })
    }

    pub fn run(&mut self) -> Result<()> {
        while !self.game_quit() {
            self.update();
            self.draw()?;
        }
        Ok(())
    }

    fn update(&mut self) {
        self.input_manager.update();
        if self.game_quit() {
            return;
        }

        match *self.meteor.state() {
            MeteorState::UNLAUNCHED => {
                self.meteor.update_target(self.input_manager.mouse_coords());
                if self.input_manager.did_click_mouse(MouseButton::Left) {
                    self.meteor.launch();
                }
            }
            MeteorState::LAUNCHED => {
                if self.input_manager.did_press_key(Keycode::R) {
                    self.meteor.explode();
                }
            }
            MeteorState::EXPLODED => {}
        }

        self.meteor.update(&self.planets);
        for star in &mut self.stars {
            star.update();
        }
    }

    fn game_quit(&self) -> bool {
        self.input_manager.game_quit() || self.input_manager.is_key_down(Keycode::Escape)
    }

    fn draw(&mut self) -> Result<()> {
        self.renderer.clear();
        self.renderer.draw(&*self.background.texture, None, None, None)?;
        for star in &self.stars {
            star.draw(&mut self.renderer)?;
        }
        for planet in &self.planets {
            planet.draw(&mut self.renderer)?;
        }
        self.meteor.draw(&mut self.renderer)?;
        self.renderer.present();
        Ok(())
    }
}
<|endoftext|>


<commit_before>use arrayvec::ArrayVec;
use std::collections::VecDeque;
use std::iter::IntoIterator;

use math::{self, FScalar};
use super::primitive::{Polygon, Polygonal, Primitive, Triangle, Quad};

// A type `F` constrained to `Fn(P, D) -> R` could be used here, but it would
// not be possible to name that type for anything but functions (not closures).
// Instead of a limited and somewhat redundant type `F`, just use `fn(P, D) ->
// R` for the member `f`.
pub struct Decompose
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    input: I,
    output: VecDeque<Q>,
    parameter: D,
    f: fn(P, D) -> R,
}

impl Decompose
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    pub(super) fn new(input: I, parameter: D, f: fn(P, D) -> R) -> Self {
        Decompose {
            input: input,
            output: VecDeque::new(),
            parameter: parameter,
            f: f,
        }
    }
}

impl Iterator for Decompose
where
    I: Iterator<Item = P>,
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(polygon) = self.output.pop_front() {
                return Some(polygon);
            }
            if let Some(polygon) = self.input.next() {
                self.output.extend((self.f)(polygon, self.parameter));
            }
            else {
                return None;
            }
        }
    }
}

pub trait Interpolate: math::Interpolate<FScalar> {}

impl<T> Interpolate for T
where
    T: math::Interpolate<FScalar>,
{
}

pub trait IntoSubdivisions: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self>;
}

pub trait IntoTetrahedrons: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]>;
}

impl<T> IntoSubdivisions for Triangle<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        n_map_polygon(n, self, |triangle| {
            let Triangle { a, b, c } = triangle;
            let ac = a.midpoint(&c);
            vec![
                Triangle::new(b.clone(), ac.clone(), a),
                Triangle::new(c, ac, b),
            ]
        })
    }
}

impl<T> IntoSubdivisions for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        n_map_polygon(n, self, |quad| {
            let Quad { a, b, c, d } = quad;
            let ab = a.midpoint(&b);
            let bc = b.midpoint(&c);
            let cd = c.midpoint(&d);
            let da = d.midpoint(&a);
            let ac = a.midpoint(&c); // Diagonal.
            vec![
                Quad::new(a, ab.clone(), ac.clone(), da.clone()),
                Quad::new(ab, b, bc.clone(), ac.clone()),
                Quad::new(ac.clone(), bc, c, cd.clone()),
                Quad::new(da, ac, cd, d),
            ]
        })
    }
}

impl<T> IntoTetrahedrons for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]> {
        let Quad { a, b, c, d } = self;
        let ac = a.midpoint(&c); // Diagonal.
        ArrayVec::from(
            [
                Triangle::new(a.clone(), b.clone(), ac.clone()),
                Triangle::new(b, c.clone(), ac.clone()),
                Triangle::new(c, d.clone(), ac.clone()),
                Triangle::new(d, a, ac),
            ],
        )
    }
}

impl<T> IntoSubdivisions for Polygon<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        match self {
            Polygon::Triangle(triangle) => {
                triangle
                    .into_subdivisions(n)
                    .into_iter()
                    .map(|triangle| triangle.into())
                    .collect()
            }
            Polygon::Quad(quad) => {
                quad.into_subdivisions(n)
                    .into_iter()
                    .map(|quad| quad.into())
                    .collect()
            }
        }
    }
}

pub trait Points
: Sized
where
    P: Primitive,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
>;
}

impl Points
 for I
where
    I: Iterator<Item = P>,
    P: Primitive<Point = T>,
    T: Clone,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
> {
        Decompose::new(self, (), into_points)
    }
}

pub trait Triangulate
: Sized
where
    P: Polygonal,
{
    #[allow(type_complexity)]
    fn triangulate(self) -> Decompose<Self, P, Triangle
, (), Vec<Triangle
>>;
}

impl Triangulate
 for I
where
    I: Iterator<Item = P>,
    P: Polygonal<Point = T>,
    T: Clone,
{
    #[allow(type_complexity)]
    fn triangulate(self) -> Decompose<Self, P, Triangle
, (), Vec<Triangle
>> {
        Decompose::new(self, (), into_triangles)
    }
}

pub trait Subdivide
: Sized
where
    P: Polygonal,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
>;
}

impl Subdivide
 for I
where
    I: Iterator<Item = P>,
    P: IntoSubdivisions<Point = T>,
    T: Clone + Interpolate,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
> {
        Decompose::new(self, n, P::into_subdivisions)
    }
}

pub trait Tetrahedrons<T>: Sized {
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), ArrayVec<[Triangle<T>; 4]>>;
}

impl Tetrahedrons<T> for I
where
    I: Iterator<Item = Quad<T>>,
    T: Clone + Interpolate,
{
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), ArrayVec<[Triangle<T>; 4]>> {
        Decompose::new(self, (), into_tetrahedrons)
    }
}

fn into_points
(primitive: P, _: ()) -> Vec<T>
where
    P: Primitive<Point = T>,
    T: Clone,
{
    primitive.into_points()
}

fn into_triangles
(polygon: P, _: ()) -> Vec<Triangle<T>>
where
    P: Polygonal<Point = T>,
    T: Clone,
{
    polygon.into_triangles()
}

fn into_tetrahedrons<T>(quad: Quad<T>, _: ()) -> ArrayVec<[Triangle<T>; 4]>
where
    T: Clone + Interpolate,
{
    quad.into_tetrahedrons()
}

fn n_map_polygon<T, P, F>(n: usize, polygon: P, f: F) -> Vec

where
    P: Polygonal<Point = T>,
    T: Clone,
    F: Fn(P) -> Vec
,
{
    let mut polygons = vec![polygon];
    for _ in 0..n {
        polygons = polygons.into_iter().flat_map(&f).collect();
    }
    polygons
}
<commit_msg>Use `ArrayVec` in `n_map_polygon` mapping function.<commit_after>use arrayvec::{Array, ArrayVec};
use std::collections::VecDeque;
use std::iter::IntoIterator;

use math::{self, FScalar};
use super::primitive::{Polygon, Polygonal, Primitive, Triangle, Quad};

// A type `F` constrained to `Fn(P, D) -> R` could be used here, but it would
// not be possible to name that type for anything but functions (not closures).
// Instead of a limited and somewhat redundant type `F`, just use `fn(P, D) ->
// R` for the member `f`.
pub struct Decompose
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    input: I,
    output: VecDeque<Q>,
    parameter: D,
    f: fn(P, D) -> R,
}

impl Decompose
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    pub(super) fn new(input: I, parameter: D, f: fn(P, D) -> R) -> Self {
        Decompose {
            input: input,
            output: VecDeque::new(),
            parameter: parameter,
            f: f,
        }
    }
}

impl Iterator for Decompose
where
    I: Iterator<Item = P>,
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(polygon) = self.output.pop_front() {
                return Some(polygon);
            }
            if let Some(polygon) = self.input.next() {
                self.output.extend((self.f)(polygon, self.parameter));
            }
            else {
                return None;
            }
        }
    }
}

pub trait Interpolate: math::Interpolate<FScalar> {}

impl<T> Interpolate for T
where
    T: math::Interpolate<FScalar>,
{
}

pub trait IntoSubdivisions: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self>;
}

pub trait IntoTetrahedrons: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]>;
}

impl<T> IntoSubdivisions for Triangle<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        n_map_polygon(n, self, |triangle| {
            let Triangle { a, b, c } = triangle;
            let ac = a.midpoint(&c);
            ArrayVec::from(
                [
                    Triangle::new(b.clone(), ac.clone(), a),
                    Triangle::new(c, ac, b),
                ],
            )
        })
    }
}

impl<T> IntoSubdivisions for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        n_map_polygon(n, self, |quad| {
            let Quad { a, b, c, d } = quad;
            let ab = a.midpoint(&b);
            let bc = b.midpoint(&c);
            let cd = c.midpoint(&d);
            let da = d.midpoint(&a);
            let ac = a.midpoint(&c); // Diagonal.
            ArrayVec::from(
                [
                    Quad::new(a, ab.clone(), ac.clone(), da.clone()),
                    Quad::new(ab, b, bc.clone(), ac.clone()),
                    Quad::new(ac.clone(), bc, c, cd.clone()),
                    Quad::new(da, ac, cd, d),
                ],
            )
        })
    }
}

impl<T> IntoTetrahedrons for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_tetrahedrons(self) -> ArrayVec<[Triangle<Self::Point>; 4]> {
        let Quad { a, b, c, d } = self;
        let ac = a.midpoint(&c); // Diagonal.
        ArrayVec::from(
            [
                Triangle::new(a.clone(), b.clone(), ac.clone()),
                Triangle::new(b, c.clone(), ac.clone()),
                Triangle::new(c, d.clone(), ac.clone()),
                Triangle::new(d, a, ac),
            ],
        )
    }
}

impl<T> IntoSubdivisions for Polygon<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions(self, n: usize) -> Vec<Self> {
        match self {
            Polygon::Triangle(triangle) => {
                triangle
                    .into_subdivisions(n)
                    .into_iter()
                    .map(|triangle| triangle.into())
                    .collect()
            }
            Polygon::Quad(quad) => {
                quad.into_subdivisions(n)
                    .into_iter()
                    .map(|quad| quad.into())
                    .collect()
            }
        }
    }
}

pub trait Points
: Sized
where
    P: Primitive,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
>;
}

impl Points
 for I
where
    I: Iterator<Item = P>,
    P: Primitive<Point = T>,
    T: Clone,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
> {
        Decompose::new(self, (), into_points)
    }
}

pub trait Triangulate
: Sized
where
    P: Polygonal,
{
    #[allow(type_complexity)]
    fn triangulate(self) -> Decompose<Self, P, Triangle
, (), Vec<Triangle
>>;
}

impl Triangulate
 for I
where
    I: Iterator<Item = P>,
    P: Polygonal<Point = T>,
    T: Clone,
{
    #[allow(type_complexity)]
    fn triangulate(self) -> Decompose<Self, P, Triangle
, (), Vec<Triangle
>> {
        Decompose::new(self, (), into_triangles)
    }
}

pub trait Subdivide
: Sized
where
    P: Polygonal,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
>;
}

impl Subdivide
 for I
where
    I: Iterator<Item = P>,
    P: IntoSubdivisions<Point = T>,
    T: Clone + Interpolate,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
> {
        Decompose::new(self, n, P::into_subdivisions)
    }
}

pub trait Tetrahedrons<T>: Sized {
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), ArrayVec<[Triangle<T>; 4]>>;
}

impl Tetrahedrons<T> for I
where
    I: Iterator<Item = Quad<T>>,
    T: Clone + Interpolate,
{
    #[allow(type_complexity)]
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), ArrayVec<[Triangle<T>; 4]>> {
        Decompose::new(self, (), into_tetrahedrons)
    }
}

fn into_points
(primitive: P, _: ()) -> Vec<T>
where
    P: Primitive<Point = T>,
    T: Clone,
{
    primitive.into_points()
}

fn into_triangles
(polygon: P, _: ()) -> Vec<Triangle<T>>
where
    P: Polygonal<Point = T>,
    T: Clone,
{
    polygon.into_triangles()
}

fn into_tetrahedrons<T>(quad: Quad<T>, _: ()) -> ArrayVec<[Triangle<T>; 4]>
where
    T: Clone + Interpolate,
{
    quad.into_tetrahedrons()
}

fn n_map_polygon<T, P, A, F>(n: usize, polygon: P, f: F) -> Vec

where
    P: Polygonal<Point = T>,
    T: Clone,
    A: Array<Item = P>,
    F: Fn(P) -> ArrayVec,
{
    let mut polygons = vec![polygon];
    for _ in 0..n {
        polygons = polygons.into_iter().flat_map(&f).collect();
    }
    polygons
}
<|endoftext|>


<commit_before>use io;
use std::fs::File;

pub struct MultiFile {
    files_iterator: Box<Iterator<Item = String>>,
    current_file: Option<File>,
}

impl MultiFile {
    pub fn new(filenames: Vec<String>) -> MultiFile {
        MultiFile {
            files_iterator: Box::new(filenames.into_iter()),
            current_file: None,
        }
    }
}

impl io::Read for MultiFile {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        let read_size;
        {
            let mut file = match self.current_file {
                Some(ref file) => file,
                None => {
                    self.current_file = match &self.files_iterator.next() {
                        Some(file) => Some(File::open(file)?),
                        None => {
                            return Ok(0);
                        }
                    };
                    return self.read(&mut buf);
                }
            };
            read_size = file.read(buf);
        }

        match read_size {
            Ok(0) => {
                // EOF, proceed with next file
                self.current_file = None;
                self.read(&mut buf)
            }
            Ok(read_size) => Ok(read_size),
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use std::io::BufRead;

    use super::*;

    #[test]
    fn test_read_all() {
        let filenames = vec![
            String::from("src/test/simple-1.log"),
            String::from("src/test/simple-2.log"),
        ];
        let input = MultiFile::new(filenames);

        let reader = io::BufReader::new(input);

        let result = reader.lines().count();
        assert_eq!(result, 8);
    }

    #[test]
    fn test_read_non_existent() {
        let filenames = vec![String::from("src/test/non-existent.log")];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_second_non_existent() {
        let filenames = vec![
            String::from("src/test/empty.log"),
            String::from("src/test/non-existent.log"),
        ];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_no_files_means_eof() {
        let filenames = vec![];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 0);
    }
}
<commit_msg>Simplify read code, avoid intermediate variable<commit_after>use io;
use std::fs::File;

pub struct MultiFile {
    files_iterator: Box<Iterator<Item = String>>,
    current_file: Option<File>,
}

impl MultiFile {
    pub fn new(filenames: Vec<String>) -> MultiFile {
        MultiFile {
            files_iterator: Box::new(filenames.into_iter()),
            current_file: None,
        }
    }
}

impl io::Read for MultiFile {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        let read_size = match self.current_file {
            Some(ref mut file) => file.read(buf),
            None => {
                self.current_file = match &self.files_iterator.next() {
                    Some(file) => Some(File::open(file)?),
                    None => {
                        return Ok(0);
                    }
                };
                return self.read(&mut buf);
            }
        };

        match read_size {
            Ok(0) => {
                // EOF, proceed with next file
                self.current_file = None;
                self.read(&mut buf)
            }
            Ok(read_size) => Ok(read_size),
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use std::io::BufRead;

    use super::*;

    #[test]
    fn test_read_all() {
        let filenames = vec![
            String::from("src/test/simple-1.log"),
            String::from("src/test/simple-2.log"),
        ];
        let input = MultiFile::new(filenames);

        let reader = io::BufReader::new(input);

        let result = reader.lines().count();
        assert_eq!(result, 8);
    }

    #[test]
    fn test_read_non_existent() {
        let filenames = vec![String::from("src/test/non-existent.log")];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_second_non_existent() {
        let filenames = vec![
            String::from("src/test/empty.log"),
            String::from("src/test/non-existent.log"),
        ];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_no_files_means_eof() {
        let filenames = vec![];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 0);
    }
}
<|endoftext|>


<commit_before>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
extern crate winapi;
extern crate kernel32;

use util::{CheckedCStr, CStringAsRef};

use std::ffi::{CStr, OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let mut wide_filename: Vec<u16> = filename.as_ref().encode_wide().collect();
        wide_filename.push(0);
        wide_filename.shrink_to_fit();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work. Symbol may or may not be terminated with a null byte (see “Premature
    /// optimisation”).
    ///
    /// # Unsafety
    ///
    /// The pointer to a symbol of arbitrary type or kind is returned. Requesting for function
    /// pointer while the symbol is not one and vice versa is not memory safe.
    ///
    /// The return value does not ensure the symbol does not outlive the library.
    ///
    /// # Premature optimisation
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CheckedCStr::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            &*(&self.pointer as *const _ as *const T)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<String>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            // TODO: Possibly use FormatMessage (lots of work here)
            Some(format!("Error {}", error))
        }
    })
}

#[test]
fn works_GetLastError() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(&::std::ffi::CString::new("GetLastError").unwrap()).unwrap();
    }
}

#[test]
fn works_GetLastError0() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(&::std::ffi::CString::new("GetLastError\0").unwrap()).unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<commit_msg>Fix windows tests<commit_after>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
extern crate winapi;
extern crate kernel32;

use util::{CheckedCStr, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let mut wide_filename: Vec<u16> = filename.as_ref().encode_wide().collect();
        wide_filename.push(0);
        wide_filename.shrink_to_fit();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work. Symbol may or may not be terminated with a null byte (see “Premature
    /// optimisation”).
    ///
    /// # Unsafety
    ///
    /// The pointer to a symbol of arbitrary type or kind is returned. Requesting for function
    /// pointer while the symbol is not one and vice versa is not memory safe.
    ///
    /// The return value does not ensure the symbol does not outlive the library.
    ///
    /// # Premature optimisation
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CheckedCStr::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            &*(&self.pointer as *const _ as *const T)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<String>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            // TODO: Possibly use FormatMessage (lots of work here)
            Some(format!("Error {}", error))
        }
    })
}

#[test]
fn works_GetLastError() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError").unwrap();
    }
}

#[test]
fn works_GetLastError0() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError\0").unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<|endoftext|>


<commit_before>fn csv_to_xml(input: &str, delim: char, root_name: &str, row_name: &str, col_name: &str) -> String {
	let mut output = String::new();

	output.open_elem(root_name);

	for line in input.lines_any() {
		output.open_elem(row_name);
		for value in line.split(delim) { output.full_elem(col_name, value);	}
		output.close_elem(row_name);
	}

	output.close_elem(root_name);

	output
}

trait XmlStr {
	fn open_elem(&mut self, elem_name: &str);
	fn close_elem(&mut self, elem_name: &str);
	fn full_elem(&mut self, elem_name: &str, elem_content: &str);
}

impl XmlStr for String {
	fn open_elem(&mut self, elem_name: &str) {
		self.push('<');
		self.push_str(elem_name);
		self.push('>');
	}

	fn close_elem(&mut self, elem_name: &str) {
		self.push_str("</");
		self.push_str(elem_name);
		self.push('>');
	}

	fn full_elem(&mut self, elem_name: &str, elem_content: &str) {
		self.open_elem(elem_name);
		self.push_str(elem_content);
		self.close_elem(elem_name);
	}
}

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

    #[test]
    fn csv_to_xml_test() {
		let test_str = "herp;derp\nhurr;durr";
		let target = "<root><row><col>herp</col><col>derp</col></row>\
			<row><col>hurr</col><col>durr</col></row></root>";

		assert_eq!(csv_to_xml(test_str, ';', "root", "row", "col"), target);
	}
}<commit_msg>add csv vectorization to the csv lib<commit_after>#![allow(dead_code)]

fn vectorize_csv(csv: &str, delim: char) -> Vec<Vec<String>> {
	let csv_lines: Vec<&str> = csv.lines_any().collect();
	let mut csv_vec = Vec::with_capacity(csv_lines.len());

	for line in csv_lines {
		csv_vec.push(line.split(|c| c == delim).map(|s| s.to_owned()).collect());
	}

	csv_vec
}

fn csv_to_xml(input: &str, delim: char, root_name: &str, row_name: &str, col_name: &str) -> String {
	let mut output = String::new();

	output.open_elem(root_name);

	for line in input.lines_any() {
		output.open_elem(row_name);
		for value in line.split(delim) { output.full_elem(col_name, value);	}
		output.close_elem(row_name);
	}

	output.close_elem(root_name);

	output
}

trait XmlStr {
	fn open_elem(&mut self, elem_name: &str);
	fn close_elem(&mut self, elem_name: &str);
	fn full_elem(&mut self, elem_name: &str, elem_content: &str);
}

impl XmlStr for String {
	fn open_elem(&mut self, elem_name: &str) {
		self.push('<');
		self.push_str(elem_name);
		self.push('>');
	}

	fn close_elem(&mut self, elem_name: &str) {
		self.push_str("</");
		self.push_str(elem_name);
		self.push('>');
	}

	fn full_elem(&mut self, elem_name: &str, elem_content: &str) {
		self.open_elem(elem_name);
		self.push_str(elem_content);
		self.close_elem(elem_name);
	}
}

#[cfg(test)]
mod tests {
    use super::{vectorize_csv, csv_to_xml};

	#[test]
	fn csv_vectorization_test() {
		let vec1 = vec![vec!["herp", "derp", "durr"], vec!["1", "2", ""], vec!["", "b", "c"]];
		let vec2 = vectorize_csv("herp;derp;durr\n1;2;\r\n;b;c", ';');

		assert_eq!(vec1, vec2);
	}

    #[test]
    fn csv_to_xml_test() {
		let test_str = "herp;derp\nhurr;durr";
		let target = "<root><row><col>herp</col><col>derp</col></row>\
			<row><col>hurr</col><col>durr</col></row></root>";

		assert_eq!(csv_to_xml(test_str, ';', "root", "row", "col"), target);
	}
}<|endoftext|>


<commit_before>// Copyright 2018 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! This library provides type-safe and fully-featured `Mutex` and `RwLock`
//! types which wrap a simple raw mutex or rwlock type. This has several
//! benefits: not only does it eliminate a large portion of the work in
//! implementing custom lock types, it also allows users to write code which is
//! generic with regards to different lock implementations.
//!
//! Basic usage of this crate is very straightforward:
//!
//! 1. Create a raw lock type. This should only contain the lock state, not any
//!    data protected by the lock.
//! 2. Implement the `RawMutex` trait for your custom lock type.
//! 3. Export your mutex as a type alias for `lock_api::Mutex`, and
//!    your mutex guard as a type alias for `lock_api::MutexGuard`.
//!    See the [example](#example) below for details.
//!
//! This process is similar for RwLocks, except that two guards need to be
//! exported instead of one. (Or 3 guards if your type supports upgradable read
//! locks, see [extension traits](#extension-traits) below for details)
//!
//! # Example
//!
//! ```
//! use lock_api::{RawMutex, Mutex, GuardSend};
//! use std::sync::atomic::{AtomicBool, Ordering};
//!
//! // 1. Define our raw lock type
//! pub struct RawSpinlock(AtomicBool);
//!
//! // 2. Implement RawMutex for this type
//! unsafe impl RawMutex for RawSpinlock {
//!     const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
//!
//!     // A spinlock guard can be sent to another thread and unlocked there
//!     type GuardMarker = GuardSend;
//!
//!     fn lock(&self) {
//!         // Note: This isn't the best way of implementing a spinlock, but it
//!         // suffices for the sake of this example.
//!         while !self.try_lock() {}
//!     }
//!
//!     fn try_lock(&self) -> bool {
//!         self.0.swap(true, Ordering::Acquire)
//!     }
//!
//!     fn unlock(&self) {
//!         self.0.store(false, Ordering::Release);
//!     }
//! }
//!
//! // 3. Export the wrappers. This are the types that your users will actually use.
//! pub type Spinlock<T> = lock_api::Mutex<RawSpinlock, T>;
//! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>;
//! ```
//!
//! # Extension traits
//!
//! In addition to basic locking & unlocking functionality, you have the option
//! of exposing additional functionality in your lock types by implementing
//! additional traits for it. Examples of extension features include:
//!
//! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`)
//! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`)
//! - Downgradable write locks (`RawRwLockDowngradable`)
//! - Recursive read locks (`RawRwLockRecursive`)
//! - Upgradable read locks (`RawRwLockUpgrade`)
//!
//! The `Mutex` and `RwLock` wrappers will automatically expose this additional
//! functionality if the raw lock type implements these extension traits.
//!
//! # Cargo features
//!
//! This crate supports two cargo features:
//!
//! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate.
//! - `nightly`: Enables nightly-only features. At the moment the only such
//!   feature is `const fn` constructors for lock types.

#![no_std]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![cfg_attr(feature = "nightly", feature(const_fn))]

#[macro_use]
extern crate scopeguard;

/// Marker type which indicates that the Guard type for a lock is `Send`.
pub struct GuardSend(());

/// Marker type which indicates that the Guard type for a lock is not `Send`.
pub struct GuardNoSend(*mut ());

mod mutex;
pub use crate::mutex::*;

mod remutex;
pub use crate::remutex::*;

mod rwlock;
pub use crate::rwlock::*;
<commit_msg>Fix `try_lock` implementation in `lock_api` example<commit_after>// Copyright 2018 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! This library provides type-safe and fully-featured `Mutex` and `RwLock`
//! types which wrap a simple raw mutex or rwlock type. This has several
//! benefits: not only does it eliminate a large portion of the work in
//! implementing custom lock types, it also allows users to write code which is
//! generic with regards to different lock implementations.
//!
//! Basic usage of this crate is very straightforward:
//!
//! 1. Create a raw lock type. This should only contain the lock state, not any
//!    data protected by the lock.
//! 2. Implement the `RawMutex` trait for your custom lock type.
//! 3. Export your mutex as a type alias for `lock_api::Mutex`, and
//!    your mutex guard as a type alias for `lock_api::MutexGuard`.
//!    See the [example](#example) below for details.
//!
//! This process is similar for RwLocks, except that two guards need to be
//! exported instead of one. (Or 3 guards if your type supports upgradable read
//! locks, see [extension traits](#extension-traits) below for details)
//!
//! # Example
//!
//! ```
//! use lock_api::{RawMutex, Mutex, GuardSend};
//! use std::sync::atomic::{AtomicBool, Ordering};
//!
//! // 1. Define our raw lock type
//! pub struct RawSpinlock(AtomicBool);
//!
//! // 2. Implement RawMutex for this type
//! unsafe impl RawMutex for RawSpinlock {
//!     const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
//!
//!     // A spinlock guard can be sent to another thread and unlocked there
//!     type GuardMarker = GuardSend;
//!
//!     fn lock(&self) {
//!         // Note: This isn't the best way of implementing a spinlock, but it
//!         // suffices for the sake of this example.
//!         while !self.try_lock() {}
//!     }
//!
//!     fn try_lock(&self) -> bool {
//!         self.0
//!             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
//!             .is_ok()
//!     }
//!
//!     fn unlock(&self) {
//!         self.0.store(false, Ordering::Release);
//!     }
//! }
//!
//! // 3. Export the wrappers. This are the types that your users will actually use.
//! pub type Spinlock<T> = lock_api::Mutex<RawSpinlock, T>;
//! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>;
//! ```
//!
//! # Extension traits
//!
//! In addition to basic locking & unlocking functionality, you have the option
//! of exposing additional functionality in your lock types by implementing
//! additional traits for it. Examples of extension features include:
//!
//! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`)
//! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`)
//! - Downgradable write locks (`RawRwLockDowngradable`)
//! - Recursive read locks (`RawRwLockRecursive`)
//! - Upgradable read locks (`RawRwLockUpgrade`)
//!
//! The `Mutex` and `RwLock` wrappers will automatically expose this additional
//! functionality if the raw lock type implements these extension traits.
//!
//! # Cargo features
//!
//! This crate supports two cargo features:
//!
//! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate.
//! - `nightly`: Enables nightly-only features. At the moment the only such
//!   feature is `const fn` constructors for lock types.

#![no_std]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![cfg_attr(feature = "nightly", feature(const_fn))]

#[macro_use]
extern crate scopeguard;

/// Marker type which indicates that the Guard type for a lock is `Send`.
pub struct GuardSend(());

/// Marker type which indicates that the Guard type for a lock is not `Send`.
pub struct GuardNoSend(*mut ());

mod mutex;
pub use crate::mutex::*;

mod remutex;
pub use crate::remutex::*;

mod rwlock;
pub use crate::rwlock::*;
<|endoftext|>


<commit_before>extern crate clap;
extern crate kiss3d;
extern crate nalgebra as na;

use clap::Parser;
use kiss3d::light::Light;
use kiss3d::window::Window;
use na::vector;
use na::{Translation, UnitQuaternion, Vector3};

/// Program to display a 3x3 cube solution.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
   /// Solve the minotaur problem.
   #[arg(short, long)]
   minotaur: bool,

   /// Solve the planes problem.
   #[arg(short, long)]
   planes: bool,
}

fn main() {
    env_logger::init();
    let args = Args::parse();

    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    //let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    for i in 0..27 {
        let c = window.add_cube(0.08, 0.08, 0.08);
        cubes.push(c);

        //cubes[i].append_rotation(&rot1);

        let r = (i % 3) as f32 * 0.1;
        let c = (i / 9) as f32 * 0.1;
        let d = (i % 9) as f32 * 0.05;
        cubes[i].append_translation(&Translation { vector: vector!(r, c, d) });
    }

    if args.minotaur {
        cubes[0].set_color(1.0, 0.0, 0.0);
        cubes[1].set_color(1.0, 0.0, 0.0);
        cubes[2].set_color(1.0, 0.0, 0.0);

        cubes[3].set_color(1.0, 0.0, 0.0);
        cubes[4].set_color(0.0, 1.0, 0.0);
        cubes[5].set_color(0.0, 0.0, 1.0);

        cubes[6].set_color(0.0, 1.0, 0.0);
        cubes[7].set_color(0.0, 1.0, 0.0);
        cubes[8].set_color(0.0, 0.0, 1.0);

        cubes[9].set_color(1.0, 1.0, 0.0);
        cubes[10].set_color(1.0, 0.0, 0.0);
        cubes[11].set_color(0.0, 1.0, 1.0);

        cubes[12].set_color(1.0, 1.0, 0.0);
        cubes[13].set_color(1.0, 1.0, 0.0);
        cubes[14].set_color(0.0, 1.0, 1.0);

        cubes[15].set_color(0.0, 1.0, 0.0);
        cubes[16].set_color(0.0, 0.0, 1.0);
        cubes[17].set_color(0.0, 0.0, 1.0);

        cubes[18].set_color(1.0, 0.0, 1.0);
        cubes[19].set_color(1.0, 0.0, 1.0);
        cubes[20].set_color(1.0, 0.0, 1.0);

        cubes[21].set_color(1.0, 1.0, 0.0);
        cubes[22].set_color(1.0, 0.0, 1.0);
        cubes[23].set_color(0.0, 1.0, 1.0);

        cubes[24].set_color(1.0, 1.0, 0.0);
        cubes[25].set_color(0.0, 1.0, 1.0);
        cubes[26].set_color(0.0, 1.0, 1.0);
    }

    if args.planes {
        for i in 0..9 {
            cubes[i].set_color(1., 0., 0.);
        }
        for i in 9..27 {
            cubes[i].set_color(0., 1., 0.);
        }
        for i in 18..27 {
            cubes[i].set_color(0., 0., 1.);
        }
    }

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    while window.render() {
        for i in 0..27 {
            cubes[i].append_rotation(&rot);
        }
    }
}<commit_msg>Make it more pretty.<commit_after>extern crate clap;
extern crate kiss3d;
extern crate nalgebra as na;

use clap::Parser;
use kiss3d::light::Light;
use kiss3d::window::Window;
use na::vector;
use na::{Translation, UnitQuaternion, Vector3};

/// Program to display a 3x3 cube solution.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
   /// Solve the minotaur problem.
   #[arg(short, long)]
   minotaur: bool,

   /// Solve the planes problem.
   #[arg(short, long)]
   planes: bool,
}

fn main() {
    env_logger::init();
    let args = Args::parse();

    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    for i in 0..27 {
        let c = window.add_cube(0.09, 0.09, 0.09);
        cubes.push(c);

        let r = (i % 3) as f32 * 0.1 - 0.1;
        let c = (i / 9) as f32 * 0.1 - 0.1;
        let d = (i % 9) as f32 * 0.05 - 0.1;
        cubes[i].append_translation(&Translation { vector: vector!(r, c, d) });
    }

    if args.minotaur {
        cubes[0].set_color(1.0, 0.0, 0.0);
        cubes[1].set_color(1.0, 0.0, 0.0);
        cubes[2].set_color(1.0, 0.0, 0.0);

        cubes[3].set_color(1.0, 0.0, 0.0);
        cubes[4].set_color(0.0, 1.0, 0.0);
        cubes[5].set_color(0.0, 0.0, 1.0);

        cubes[6].set_color(0.0, 1.0, 0.0);
        cubes[7].set_color(0.0, 1.0, 0.0);
        cubes[8].set_color(0.0, 0.0, 1.0);

        cubes[9].set_color(1.0, 1.0, 0.0);
        cubes[10].set_color(1.0, 0.0, 0.0);
        cubes[11].set_color(0.0, 1.0, 1.0);

        cubes[12].set_color(1.0, 1.0, 0.0);
        cubes[13].set_color(1.0, 1.0, 0.0);
        cubes[14].set_color(0.0, 1.0, 1.0);

        cubes[15].set_color(0.0, 1.0, 0.0);
        cubes[16].set_color(0.0, 0.0, 1.0);
        cubes[17].set_color(0.0, 0.0, 1.0);

        cubes[18].set_color(1.0, 0.0, 1.0);
        cubes[19].set_color(1.0, 0.0, 1.0);
        cubes[20].set_color(1.0, 0.0, 1.0);

        cubes[21].set_color(1.0, 1.0, 0.0);
        cubes[22].set_color(1.0, 0.0, 1.0);
        cubes[23].set_color(0.0, 1.0, 1.0);

        cubes[24].set_color(1.0, 1.0, 0.0);
        cubes[25].set_color(0.0, 1.0, 1.0);
        cubes[26].set_color(0.0, 1.0, 1.0);
    }

    if args.planes {
        for i in 0..9 {
            cubes[i].set_color(1., 0., 0.);
        }
        for i in 9..27 {
            cubes[i].set_color(0., 1., 0.);
        }
        for i in 18..27 {
            cubes[i].set_color(0., 0., 1.);
        }
    }

    let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), 0.01);
    let rot2 = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.01);

    for _ in 0..1600 {
        if window.render() {
            for i in 0..27 {
                cubes[i].append_rotation(&rot1);
            }
        }
    }
    for _ in 0..1600 {
        if window.render() {
            for i in 0..27 {
                cubes[i].append_rotation(&rot2)
            }
        }
    }
}<|endoftext|>


<commit_before>use std::ops::Add;

#[derive(Default, Copy, Clone, Debug)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}

#[derive(Default, Debug, Copy, Clone)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: u32,
    pub h: u32,
}

impl Rect {
    pub fn intersects(&self, other: &Rect) -> bool {
        self.x < other.x + other.w as i32
            && self.x + other.w as i32 > other.x
            && self.y < other.y + other.h as i32
            && self.h as i32 + self.y > other.y
    }

    pub fn contains_point(self, point: Point) -> bool {
        point.x > self.x
            && point.x < self.x + self.w as i32
            && point.y > self.y
            && point.y < self.y + self.h as i32
    }
}

impl Add<Point> for Rect {
    type Output = Rect;

    fn add(self, other: Point) -> Rect {
        Rect {
            x: self.x + other.x,
            y: self.y + other.y,
            w: self.w,
            h: self.h,
        }
    }
}

impl Add<(i32, i32)> for Rect {
    type Output = Rect;

    fn add(self, other: (i32, i32)) -> Rect {
        Rect {
            x: self.x + other.0,
            y: self.y + other.1,
            w: self.w,
            h: self.h,
        }
    }
}

#[derive(Default, Copy, Clone, Debug)]
pub struct Interval {
    pub a: i32,
    pub b: i32,
}

impl Interval {
    pub fn contains_point(self, other: i32) -> bool {
        self.a <= other && self.b >= other
    }
}
<commit_msg>fix rect intersection bug<commit_after>use std::ops::Add;

#[derive(Default, Copy, Clone, Debug)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}

#[derive(Default, Debug, Copy, Clone)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: u32,
    pub h: u32,
}

impl Rect {
    pub fn intersects(&self, other: &Rect) -> bool {
        self.x < other.x + other.w as i32
            && self.x + self.w as i32 > other.x
            && self.y < other.y + other.h as i32
            && self.h as i32 + self.y > other.y
    }

    pub fn contains_point(self, point: Point) -> bool {
        point.x > self.x
            && point.x < self.x + self.w as i32
            && point.y > self.y
            && point.y < self.y + self.h as i32
    }
}

impl Add<Point> for Rect {
    type Output = Rect;

    fn add(self, other: Point) -> Rect {
        Rect {
            x: self.x + other.x,
            y: self.y + other.y,
            w: self.w,
            h: self.h,
        }
    }
}

impl Add<(i32, i32)> for Rect {
    type Output = Rect;

    fn add(self, other: (i32, i32)) -> Rect {
        Rect {
            x: self.x + other.0,
            y: self.y + other.1,
            w: self.w,
            h: self.h,
        }
    }
}

#[derive(Default, Copy, Clone, Debug)]
pub struct Interval {
    pub a: i32,
    pub b: i32,
}

impl Interval {
    pub fn contains_point(self, other: i32) -> bool {
        self.a <= other && self.b >= other
    }
}
<|endoftext|>


<commit_before>extern crate regex;

use std::env;
use std::fs::File;
use std::error::Error;
use std::path::PathBuf;
use std::io::prelude::*;
use std::collections::HashMap;
use std::collections::HashSet;
use regex::Regex;

use request::*;
use response::*;

#[derive(PartialEq, Eq, Hash, Debug)]
pub enum ParamType {
    Integer,
    String,
    Float,
    Path,
}

pub struct Route {
    matcher:     Regex,
    methods:     HashSet<Method>,
    params:      HashMap<String, ParamType>,
    pub handler: fn(&Request) -> Response,
}

impl Route {
    pub fn new(path: &str, mlist: Vec<Method>, handler: fn(&Request) -> Response) -> Route {
        let re = Regex::new(r"^<(?:(int|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$").unwrap();
        let parts: Vec<&str> = path.split('/').filter(|&s| s != "").collect();
        let mut matcher: String = String::from(r"^");
        let mut params: HashMap<String, ParamType> = HashMap::new();
        let mut methods: HashSet<Method> = HashSet::new();

        for m in mlist {
            methods.insert(m);
        }

        for part in parts {
            let chunk: String = match re.is_match(part) {
                true  => {
                    let mut rc = String::new();
                    let caps = re.captures(part).unwrap();
                    let param = caps.at(2).unwrap().clone();
                    let ptype: ParamType = match caps.at(1) {
                        Some(x)     => {
                            match x.as_ref() {
                                "int"   => ParamType::Integer,
                                "float" => ParamType::Float,
                                "path"  => ParamType::Path,
                                _       => ParamType::String,

                            }
                        }
                        None        => ParamType::String,
                    };

                    let mstr: String = match ptype {
                        ParamType::String  => String::from(r"(?:[^/])+"),
                        ParamType::Integer => String::from(r"-*[0-9]+"),
                        ParamType::Float   => String::from(r"-*[0-9]*[.]?[0-9]+"),
                        ParamType::Path    => String::from(r".+"),
                    };

                    rc.push_str("/(?P<");
                    rc.push_str(&param);
                    rc.push_str(">");
                    rc.push_str(&mstr);
                    rc.push_str(")");
                    params.insert(String::from(param), ptype);

                    rc
                },
                false => String::from("/") + part,
            };

            matcher.push_str(&chunk);
        }

        /* end the regex with an optional final slash and a string terminator */
        matcher.push_str("/?$");

        Route {
            matcher: Regex::new(&matcher).unwrap(),
            params:  params,
            methods: methods,
            handler: handler,
        }
    }

    pub fn is_match(&self, req: &Request) -> bool {
        self.matcher.is_match(&req.path) && self.methods.contains(&req.method)
    }

    pub fn parse(&self, path: &str) -> Option<HashMap<String, String>> {
        let mut params: HashMap<String, String> = HashMap::new();

        return match self.matcher.is_match(&path) {
            true  => {
                let caps = self.matcher.captures(path).unwrap();
                for (param, _) in &self.params {
                    params.insert(param.clone(), String::from(caps.name(&param).unwrap()));
                }

                Some(params)
            },
            false => None,
        }
    }

    pub fn err_403(req: &Request) -> Response {
        Response::err_403(&req.path)
    }

    pub fn err_404(req: &Request) -> Response {
        Response::err_404(&req.path)
    }

    pub fn static_file(req: &Request) -> Response {
        let mut res = Response::new();

        let cwd = env::current_dir().unwrap();
        let clean = Route::replace_escape(&req.path);
        let mut fpath = PathBuf::from(&cwd);
        let mut fbuf: Vec<u8> = Vec::new();

        for chunk in clean.split('/') {
            if chunk == "" || chunk == "." || chunk == ".." {
                /* bzzzzt */
                continue;
            }

            fpath.push(&chunk);
        }

        let file = File::open(&fpath);

        match file {
            Ok(mut f)   => {
                match f.read_to_end(&mut fbuf) {
                    Ok(_)   => {
                        res.set_code(200);
                        res.set_content_type("text/plain");
                        res.append(fbuf);
                    },
                    Err(e)  => {
                        return Response::err_500(e.description());
                    },
                }
            },
            Err(_)      => {
                return Response::err_404(&req.path);
            }
        }

        res
    }
}
<commit_msg>string escape fixer upper<commit_after>extern crate regex;

use std::env;
use std::fs::File;
use std::error::Error;
use std::path::PathBuf;
use std::io::prelude::*;
use std::collections::HashMap;
use std::collections::HashSet;
use regex::Regex;

use request::*;
use response::*;

#[derive(PartialEq, Eq, Hash, Debug)]
pub enum ParamType {
    Integer,
    String,
    Float,
    Path,
}

pub struct Route {
    matcher:     Regex,
    methods:     HashSet<Method>,
    params:      HashMap<String, ParamType>,
    pub handler: fn(&Request) -> Response,
}

impl Route {
    pub fn new(path: &str, mlist: Vec<Method>, handler: fn(&Request) -> Response) -> Route {
        let re = Regex::new(r"^<(?:(int|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$").unwrap();
        let parts: Vec<&str> = path.split('/').filter(|&s| s != "").collect();
        let mut matcher: String = String::from(r"^");
        let mut params: HashMap<String, ParamType> = HashMap::new();
        let mut methods: HashSet<Method> = HashSet::new();

        for m in mlist {
            methods.insert(m);
        }

        for part in parts {
            let chunk: String = match re.is_match(part) {
                true  => {
                    let mut rc = String::new();
                    let caps = re.captures(part).unwrap();
                    let param = caps.at(2).unwrap().clone();
                    let ptype: ParamType = match caps.at(1) {
                        Some(x)     => {
                            match x.as_ref() {
                                "int"   => ParamType::Integer,
                                "float" => ParamType::Float,
                                "path"  => ParamType::Path,
                                _       => ParamType::String,

                            }
                        }
                        None        => ParamType::String,
                    };

                    let mstr: String = match ptype {
                        ParamType::String  => String::from(r"(?:[^/])+"),
                        ParamType::Integer => String::from(r"-*[0-9]+"),
                        ParamType::Float   => String::from(r"-*[0-9]*[.]?[0-9]+"),
                        ParamType::Path    => String::from(r".+"),
                    };

                    rc.push_str("/(?P<");
                    rc.push_str(&param);
                    rc.push_str(">");
                    rc.push_str(&mstr);
                    rc.push_str(")");
                    params.insert(String::from(param), ptype);

                    rc
                },
                false => String::from("/") + part,
            };

            matcher.push_str(&chunk);
        }

        /* end the regex with an optional final slash and a string terminator */
        matcher.push_str("/?$");

        Route {
            matcher: Regex::new(&matcher).unwrap(),
            params:  params,
            methods: methods,
            handler: handler,
        }
    }

    pub fn is_match(&self, req: &Request) -> bool {
        self.matcher.is_match(&req.path) && self.methods.contains(&req.method)
    }

    pub fn parse(&self, path: &str) -> Option<HashMap<String, String>> {
        let mut params: HashMap<String, String> = HashMap::new();

        return match self.matcher.is_match(&path) {
            true  => {
                let caps = self.matcher.captures(path).unwrap();
                for (param, _) in &self.params {
                    params.insert(param.clone(), String::from(caps.name(&param).unwrap()));
                }

                Some(params)
            },
            false => None,
        }
    }

    pub fn replace_escape(path: &str) -> String {
        let mut fixed = String::from(path);
        let replaces: [(&str, &str); 22] = [
                ("%20", " "),
                ("%3C", "<"),
                ("%3E", ">"),
                ("%23", "#"),
                ("%25", "%"),
                ("%7B", "["),
                ("%7D", ")"),
                ("%7C", "|"),
                ("%5C", "\\"),
                ("%5E", "^"),
                ("%7E", "~"),
                ("%5B", "["),
                ("%5D", ")"),
                ("%60", "`"),
                ("%3B", ";"),
                ("%2F", "/"),
                ("%3F", "?"),
                ("%3A", ":"),
                ("%40", "@"),
                ("%3D", "="),
                ("%26", "&"),
                ("%24", "$"),
        ];

        for &(from, to) in replaces.iter() {
            fixed = fixed.replace(from, to);
        }

        fixed
    }

    pub fn err_403(req: &Request) -> Response {
        Response::err_403(&req.path)
    }

    pub fn err_404(req: &Request) -> Response {
        Response::err_404(&req.path)
    }

    pub fn static_file(req: &Request) -> Response {
        let mut res = Response::new();

        let cwd = env::current_dir().unwrap();
        let clean = Route::replace_escape(&req.path);
        let mut fpath = PathBuf::from(&cwd);
        let mut fbuf: Vec<u8> = Vec::new();

        for chunk in clean.split('/') {
            if chunk == "" || chunk == "." || chunk == ".." {
                /* bzzzzt */
                continue;
            }

            fpath.push(&chunk);
        }

        let file = File::open(&fpath);

        match file {
            Ok(mut f)   => {
                match f.read_to_end(&mut fbuf) {
                    Ok(_)   => {
                        res.set_code(200);
                        res.set_content_type("text/plain");
                        res.append(fbuf);
                    },
                    Err(e)  => {
                        return Response::err_500(e.description());
                    },
                }
            },
            Err(_)      => {
                return Response::err_404(&req.path);
            }
        }

        res
    }
}
<|endoftext|>