<commit_before>use error::*;
use ops;

use std::collections::HashMap;
use std::fmt;
// use std::iter;
use std::slice;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Symbol {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Symbol::*;
        write!(f, "{}", match *self {
            Add => "+",
            Sub => "-",
            Mul => "*",
            Div => "/",
            Mod => "%",
        })
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
    Nullary,
    Unary,
    Binary,
    Ternary,
    Multiary, // 2+ arguments
}

impl fmt::Display for Arity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Arity::*;
        let text = match *self {
            Nullary => "0",
            Unary => "1",
            Binary => "2",
            Ternary => "3",
            Multiary => "at least 2",
        };

        write!(f, "{} args", text)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Atom {
    Sym(Symbol),
    // Bool(bool),
    Int(i64),
    // Float(f64),
    //Str(String),
}

impl Atom {
    fn kind(&self) -> &str {
        use self::Atom::*;
        match *self {
            Sym(_) => "sym",
            Int(_) => "int",
        }
    }

    pub fn add(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a + b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Add, self.kind(), x.kind()).into()),
        }
    }

    pub fn sub(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a - b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Sub, self.kind(), x.kind()).into()),
        }
    }

    pub fn mul(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a * b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mul, self.kind(), x.kind()).into()),
        }
    }

    pub fn div(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("division by zero".into())
                } else {
                    Ok(Int(a / b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Div, self.kind(), x.kind()).into()),
        }
    }

    pub fn modulus(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("modulus by zero".into())
                } else {
                    Ok(Int(a % b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mod, self.kind(), x.kind()).into()),
        }
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Sym(ref t) => write!(f, "{}", t),
            // Bool(ref t) => write!(f, "{}", t),
            Int(ref t) => write!(f, "{}", t),
            // Float(ref t) => write!(f, "{}", t),
            // Str(ref t) => write!(f, "{}", t),
        }
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Sym(x)
    }
}

impl From<i64> for Atom {
    fn from(x: i64) -> Self {
        Atom::Int(x)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Atom(Atom),
    List(List),
}

impl Value {
    fn kind(&self) -> &str {
        use self::Value::*;
        match *self {
            Atom(_) => "atom",
            List(_) => "list",
        }
    }

    fn binary<F>(&self, x: &Self, symbol: Symbol, f: F) -> Result<Value>
        where F: Fn(&Atom, &Atom) -> Result<Atom>
    {
        use self::Value::Atom;
        match (self, x) {
            (&Atom(ref a), &Atom(ref b)) => f(a, b).map(Value::from),
            _ => Err(format!("incompatible types for {}: {}, {}",
                symbol, self.kind(), x.kind()).into()),
        }
    }

    pub fn add(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Add, Atom::add)
    }

    pub fn sub(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Sub, Atom::sub)
    }

    pub fn mul(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mul, Atom::mul)
    }

    pub fn div(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Div, Atom::div)
    }

    pub fn modulus(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mod, Atom::modulus)
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;
        match *self {
            Atom(ref t) => write!(f, "{}", t),
            List(ref t) => write!(f, "{}", t),
        }
    }
}

impl<T> From<T> for Value
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Value::Atom(v.into())
    }
}

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Sum<Value> for Value {
//     fn sum<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(0.into(), |acc, x| acc + x)
//     }
// }

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Mul<Value> for Value {
//     fn mul<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(1.into(), |acc, x| acc * x)
//     }
// }

#[derive(Clone, Debug, PartialEq)]
pub enum Node {
    Atom(Atom),
    List(List),
    Expr(Expr),
}

impl Node {
    pub fn eval(&self) -> Result<Value> {
        use self::Node::*;
        match *self {
            Atom(a) => Ok(Value::Atom(a)),
            List(ref l) => Ok(Value::List(l.clone())),
            Expr(ref e) => e.eval(),
        }
    }
}

impl<T> From<T> for Node
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Node::Atom(v.into())
    }
}

// impl<T> From<T> for Node where T: Into<List> {
//     fn from(l: T) -> Self {
//         Node::List(l.into())
//     }
// }
//
// impl<T> From<T> for Node where T: Into<Expr> {
//     fn from(e: T) -> Self {
//         Node::Expr(e.into())
//     }
// }

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Node::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "{}", l),
            Expr(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct List {
    inner: Vec<Node>,
}

impl List {
    pub fn new() -> Self {
        List { inner: Vec::new() }
    }
}

impl From<Vec<Node>> for List {
    fn from(v: Vec<Node>) -> Self {
        List { inner: v }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.inner
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "[ {} ]", elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
    sym: Symbol,
    args: Vec<Node>,
}

impl Expr {
    pub fn new(sym: Symbol, args: Vec<Node>) -> Self {
        Expr {
            sym: sym,
            args: args,
        }
    }

    pub fn sym(&self) -> Symbol {
        self.sym
    }

    pub fn args(&self) -> slice::Iter<Node> {
        self.args.iter()
    }

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

    fn check_arity(&self, arity: Arity) -> bool {
        use self::Arity::*;
        let num_args = self.num_args();
        match arity {
            Nullary => num_args == 0,
            Unary => num_args == 1,
            Binary => num_args == 2,
            Ternary => num_args == 3,
            Multiary => num_args >= 2,
        }
    }

    pub fn eval(&self) -> Result<Value> {
        use self::Symbol::*;
        use self::Arity::*;

        // Arity = number of arguments accepted
        let mut arity = HashMap::new();

        arity.insert(Add, Multiary);
        arity.insert(Sub, Binary);
        arity.insert(Mul, Multiary);
        arity.insert(Div, Binary);
        arity.insert(Mod, Binary);

        let sym = self.sym();

        let expected_arity = match arity.get(&sym) {
            Some(e) => e,
            None => return Err(format!("symbol {} has unknown number of arguments", sym).into()),
        };

        // Check if number of arguments match expected number
        if !self.check_arity(*expected_arity) {
            return Err(format!("{} symbol expected {} arguments, but received {}",
                               sym,
                               expected_arity,
                               self.num_args())
                .into());
        }

        let evaled_args: Result<Vec<_>> = self.args().map(Node::eval).collect();

        // Return the first expr that cannot eval correctly
        match evaled_args {
            Err(e) => Err(e),
            Ok(v) => {
                match sym {
                    Add => ops::add(&v),
                    Sub => ops::sub(&v),
                    Mul => ops::mul(&v),
                    Div => ops::div(&v),
                    Mod => ops::modulus(&v),
                }
            }
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.args
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} {} )", self.sym, elements)
    }
}
<commit_msg>Fix invalid number of arguments error message<commit_after>use error::*;
use ops;

use std::collections::HashMap;
use std::fmt;
// use std::iter;
use std::slice;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Symbol {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Symbol::*;
        write!(f, "{}", match *self {
            Add => "+",
            Sub => "-",
            Mul => "*",
            Div => "/",
            Mod => "%",
        })
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
    Nullary,
    Unary,
    Binary,
    Ternary,
    Multiary, // 2+ arguments
}

impl fmt::Display for Arity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Arity::*;
        let text = match *self {
            Nullary => "0",
            Unary => "1",
            Binary => "2",
            Ternary => "3",
            Multiary => "at least 2",
        };

        write!(f, "{}", text)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Atom {
    Sym(Symbol),
    // Bool(bool),
    Int(i64),
    // Float(f64),
    //Str(String),
}

impl Atom {
    fn kind(&self) -> &str {
        use self::Atom::*;
        match *self {
            Sym(_) => "sym",
            Int(_) => "int",
        }
    }

    pub fn add(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a + b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Add, self.kind(), x.kind()).into()),
        }
    }

    pub fn sub(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a - b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Sub, self.kind(), x.kind()).into()),
        }
    }

    pub fn mul(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a * b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mul, self.kind(), x.kind()).into()),
        }
    }

    pub fn div(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("division by zero".into())
                } else {
                    Ok(Int(a / b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Div, self.kind(), x.kind()).into()),
        }
    }

    pub fn modulus(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("modulus by zero".into())
                } else {
                    Ok(Int(a % b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mod, self.kind(), x.kind()).into()),
        }
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Sym(ref t) => write!(f, "{}", t),
            // Bool(ref t) => write!(f, "{}", t),
            Int(ref t) => write!(f, "{}", t),
            // Float(ref t) => write!(f, "{}", t),
            // Str(ref t) => write!(f, "{}", t),
        }
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Sym(x)
    }
}

impl From<i64> for Atom {
    fn from(x: i64) -> Self {
        Atom::Int(x)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Atom(Atom),
    List(List),
}

impl Value {
    fn kind(&self) -> &str {
        use self::Value::*;
        match *self {
            Atom(_) => "atom",
            List(_) => "list",
        }
    }

    fn binary<F>(&self, x: &Self, symbol: Symbol, f: F) -> Result<Value>
        where F: Fn(&Atom, &Atom) -> Result<Atom>
    {
        use self::Value::Atom;
        match (self, x) {
            (&Atom(ref a), &Atom(ref b)) => f(a, b).map(Value::from),
            _ => Err(format!("incompatible types for {}: {}, {}",
                symbol, self.kind(), x.kind()).into()),
        }
    }

    pub fn add(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Add, Atom::add)
    }

    pub fn sub(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Sub, Atom::sub)
    }

    pub fn mul(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mul, Atom::mul)
    }

    pub fn div(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Div, Atom::div)
    }

    pub fn modulus(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mod, Atom::modulus)
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;
        match *self {
            Atom(ref t) => write!(f, "{}", t),
            List(ref t) => write!(f, "{}", t),
        }
    }
}

impl<T> From<T> for Value
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Value::Atom(v.into())
    }
}

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Sum<Value> for Value {
//     fn sum<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(0.into(), |acc, x| acc + x)
//     }
// }

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Mul<Value> for Value {
//     fn mul<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(1.into(), |acc, x| acc * x)
//     }
// }

#[derive(Clone, Debug, PartialEq)]
pub enum Node {
    Atom(Atom),
    List(List),
    Expr(Expr),
}

impl Node {
    pub fn eval(&self) -> Result<Value> {
        use self::Node::*;
        match *self {
            Atom(a) => Ok(Value::Atom(a)),
            List(ref l) => Ok(Value::List(l.clone())),
            Expr(ref e) => e.eval(),
        }
    }
}

impl<T> From<T> for Node
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Node::Atom(v.into())
    }
}

// impl<T> From<T> for Node where T: Into<List> {
//     fn from(l: T) -> Self {
//         Node::List(l.into())
//     }
// }
//
// impl<T> From<T> for Node where T: Into<Expr> {
//     fn from(e: T) -> Self {
//         Node::Expr(e.into())
//     }
// }

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Node::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "{}", l),
            Expr(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct List {
    inner: Vec<Node>,
}

impl List {
    pub fn new() -> Self {
        List { inner: Vec::new() }
    }
}

impl From<Vec<Node>> for List {
    fn from(v: Vec<Node>) -> Self {
        List { inner: v }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.inner
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "[ {} ]", elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
    sym: Symbol,
    args: Vec<Node>,
}

impl Expr {
    pub fn new(sym: Symbol, args: Vec<Node>) -> Self {
        Expr {
            sym: sym,
            args: args,
        }
    }

    pub fn sym(&self) -> Symbol {
        self.sym
    }

    pub fn args(&self) -> slice::Iter<Node> {
        self.args.iter()
    }

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

    fn check_arity(&self, arity: Arity) -> bool {
        use self::Arity::*;
        let num_args = self.num_args();
        match arity {
            Nullary => num_args == 0,
            Unary => num_args == 1,
            Binary => num_args == 2,
            Ternary => num_args == 3,
            Multiary => num_args >= 2,
        }
    }

    pub fn eval(&self) -> Result<Value> {
        use self::Symbol::*;
        use self::Arity::*;

        // Arity = number of arguments accepted
        let mut arity = HashMap::new();

        arity.insert(Add, Multiary);
        arity.insert(Sub, Binary);
        arity.insert(Mul, Multiary);
        arity.insert(Div, Binary);
        arity.insert(Mod, Binary);

        let sym = self.sym();

        let expected_arity = match arity.get(&sym) {
            Some(e) => e,
            None => return Err(format!("symbol {} has unknown number of arguments", sym).into()),
        };

        // Check if number of arguments match expected number
        if !self.check_arity(*expected_arity) {
            return Err(format!("{} symbol expected {} arguments, but received {}",
                               sym,
                               expected_arity,
                               self.num_args())
                .into());
        }

        let evaled_args: Result<Vec<_>> = self.args().map(Node::eval).collect();

        // Return the first expr that cannot eval correctly
        match evaled_args {
            Err(e) => Err(e),
            Ok(v) => {
                match sym {
                    Add => ops::add(&v),
                    Sub => ops::sub(&v),
                    Mul => ops::mul(&v),
                    Div => ops::div(&v),
                    Mod => ops::modulus(&v),
                }
            }
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.args
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} {} )", self.sym, elements)
    }
}
<|endoftext|>


<commit_before>use crate::extractors::ActixError;
use crate::prometheus_middleware;
use crate::routes::{
    autocomplete, entry_point, features, metrics, post_autocomplete, reverse, status,
};
use crate::{Args, Context};
use actix_web::{http, middleware, server, App, HttpRequest, Json};
use structopt::StructOpt;

fn default_404(req: &HttpRequest<Context>) -> Result<Json<()>, ActixError> {
    Err(ActixError::RouteNotFound(req.path().to_string()))
}

pub fn create_server(ctx: Context) -> App<Context> {
    App::with_state(ctx)
        .middleware(
            middleware::cors::Cors::build()
                .allowed_methods(vec!["GET"])
                .finish(),
        )
        .middleware(middleware::Logger::default())
        .middleware(prometheus_middleware::PrometheusMiddleware::default())
        .resource("/", |r| r.f(entry_point))
        .resource("/autocomplete", |r| {
            r.method(http::Method::GET).with(autocomplete);

            r.method(http::Method::POST)
                .with_config(post_autocomplete, |(_, _, json_cfg)| {
                    json_cfg.error_handler(|err, _req| {
                        ActixError::InvalidJson(format!("{}", err)).into()
                    });
                });
        })
        .resource("/status", |r| r.with(status))
        .resource("/features/{id}", |r| r.with(features))
        .resource("/reverse", |r| r.with(reverse))
        .resource("/metrics", |r| r.f(metrics))
        .default_resource(|r| {
            // custom error for 404
            r.f(default_404)
        })
}

pub fn runserver() {
    let args = Args::from_args();
    let ctx: Context = (&args).into();
    server::new(move || create_server(ctx.clone()))
        .bind(&args.bind)
        .unwrap()
        .run();
}
<commit_msg>change nb_threads<commit_after>use crate::extractors::ActixError;
use crate::prometheus_middleware;
use crate::routes::{
    autocomplete, entry_point, features, metrics, post_autocomplete, reverse, status,
};
use crate::{Args, Context};
use actix_web::{http, middleware, server, App, HttpRequest, Json};
use structopt::StructOpt;

fn default_404(req: &HttpRequest<Context>) -> Result<Json<()>, ActixError> {
    Err(ActixError::RouteNotFound(req.path().to_string()))
}

pub fn create_server(ctx: Context) -> App<Context> {
    App::with_state(ctx)
        .middleware(
            middleware::cors::Cors::build()
                .allowed_methods(vec!["GET"])
                .finish(),
        )
        .middleware(middleware::Logger::default())
        .middleware(prometheus_middleware::PrometheusMiddleware::default())
        .resource("/", |r| r.f(entry_point))
        .resource("/autocomplete", |r| {
            r.method(http::Method::GET).with(autocomplete);

            r.method(http::Method::POST)
                .with_config(post_autocomplete, |(_, _, json_cfg)| {
                    json_cfg.error_handler(|err, _req| {
                        ActixError::InvalidJson(format!("{}", err)).into()
                    });
                });
        })
        .resource("/status", |r| r.with(status))
        .resource("/features/{id}", |r| r.with(features))
        .resource("/reverse", |r| r.with(reverse))
        .resource("/metrics", |r| r.f(metrics))
        .default_resource(|r| {
            // custom error for 404
            r.f(default_404)
        })
}

pub fn runserver() {
    let args = Args::from_args();
    let ctx: Context = (&args).into();
    server::new(move || create_server(ctx.clone()))
        .bind(&args.bind)
        .unwrap()
        .workers(args.nb_threads)
        .run();
}
<|endoftext|>


<commit_before>use std;
use std::borrow::Cow;
use std::fs::File;
use std::io::{Error as IOError, Read};
use toml;

// That's the default seed used by the Haskell plugin
const DEFAULT_HERBIE_SEED: &'static str = "#(1461197085 2376054483 1553562171 1611329376 \
                                           2497620867 2308122621)";
const DEFAULT_DB_PATH: &'static str = "Herbie.db";
const DEFAULT_TIMEOUT: u32 = 120;

#[derive(Debug, RustcDecodable)]
pub struct UxConf {
    /// Path to the database.
    pub db_path: Option<String>,
    /// Maximum time in seconds that Herbie is allowed to play with an expression. If null, allow
    /// The seed use by Herbie. If not provided, a fixed seed will be used. Fixing the seed ensures
    /// deterministic builds.
    pub herbie_seed: Option<String>,
    /// Herbie to run indefinitely. Default is two minutes.
    pub timeout: Option<u32>,
    /// Allow the plugin to call Herbie on unknown expressions. Positive results from Herbie will
    /// be cached in the database.
    /// If ‘true’, the plugin will fail if it cannot find the executable.
    /// If ‘false’, the plugin will not try to run Herbie.
    /// By default, the plugin will call the executable only if it's found, but won't complain
    /// otherwise.
    pub use_herbie: Option<bool>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum UseHerbieConf {
    Default,
    No,
    Yes,
}

#[derive(Debug)]
pub struct Conf {
    pub db_path: Cow<'static, str>,
    pub herbie_seed: Cow<'static, str>,
    pub timeout: Option<u32>,
    pub use_herbie: UseHerbieConf,
}

impl Default for Conf {
    fn default() -> Conf {
        Conf {
            db_path: DEFAULT_DB_PATH.into(),
            herbie_seed: DEFAULT_HERBIE_SEED.into(),
            timeout: Some(DEFAULT_TIMEOUT),
            use_herbie: UseHerbieConf::Default,
        }
    }
}

impl From<UxConf> for Conf {
    fn from(ux: UxConf) -> Conf {
        Conf {
            db_path: ux.db_path.map_or(DEFAULT_DB_PATH.into(), Into::into),
            herbie_seed: ux.herbie_seed.map_or(DEFAULT_HERBIE_SEED.into(), Into::into),
            timeout: ux.timeout.map_or(Some(DEFAULT_TIMEOUT), |t| {
                if t == 0 {
                    None
                }
                else {
                    Some(t)
                }
            }),
            use_herbie: ux.use_herbie.map_or(UseHerbieConf::Default, |u| {
                if u {
                    UseHerbieConf::Yes
                }
                else {
                    UseHerbieConf::No
                }
            }),
        }
    }
}

#[derive(Debug)]
pub enum ConfError {
    IOError {
        error: IOError,
    },
    ParseError,
}

impl std::fmt::Display for ConfError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            ConfError::IOError{ ref error } => write!(f, "Error reading Herbie.toml: {}", error),
            ConfError::ParseError => write!(f, "Syntax error in Herbie.toml"),
        }
    }
}

impl From<IOError> for ConfError {
    fn from(err: IOError) -> ConfError {
        ConfError::IOError { error: err }
    }
}

pub fn read_conf() -> Result<Conf, ConfError> {
    if let Ok(mut conf) = File::open("Herbie.toml") {
        let mut buffer = String::new();
        try!(conf.read_to_string(&mut buffer));

        if let Some(conf) = toml::decode_str::<UxConf>(&buffer) {
            Ok(conf.into())
        }
        else {
            Err(ConfError::ParseError)
        }
    }
    else {
        Ok(Conf::default())
    }
}
<commit_msg>Fix comment<commit_after>use std;
use std::borrow::Cow;
use std::fs::File;
use std::io::{Error as IOError, Read};
use toml;

// That's the default seed used by the Haskell plugin
const DEFAULT_HERBIE_SEED: &'static str = "#(1461197085 2376054483 1553562171 1611329376 \
                                           2497620867 2308122621)";
const DEFAULT_DB_PATH: &'static str = "Herbie.db";
const DEFAULT_TIMEOUT: u32 = 120;

#[derive(Debug, RustcDecodable)]
pub struct UxConf {
    /// Path to the database. Defaults to "Herbie.db".
    pub db_path: Option<String>,
    /// The seed use by Herbie. If not provided, a fixed seed will be used. Fixing the seed ensures
    /// deterministic builds.
    pub herbie_seed: Option<String>,
    /// Maximum time in seconds that Herbie is allowed to play with an expression. If null, allow
    /// Herbie to run indefinitely. Default is two minutes.
    pub timeout: Option<u32>,
    /// Allow the plugin to call Herbie on unknown expressions. Positive results from Herbie will
    /// be cached in the database.
    /// If ‘true’, the plugin will fail if it cannot find the executable.
    /// If ‘false’, the plugin will not try to run Herbie.
    /// By default, the plugin will call the executable only if it's found, but won't complain
    /// otherwise.
    pub use_herbie: Option<bool>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum UseHerbieConf {
    Default,
    No,
    Yes,
}

#[derive(Debug)]
pub struct Conf {
    pub db_path: Cow<'static, str>,
    pub herbie_seed: Cow<'static, str>,
    pub timeout: Option<u32>,
    pub use_herbie: UseHerbieConf,
}

impl Default for Conf {
    fn default() -> Conf {
        Conf {
            db_path: DEFAULT_DB_PATH.into(),
            herbie_seed: DEFAULT_HERBIE_SEED.into(),
            timeout: Some(DEFAULT_TIMEOUT),
            use_herbie: UseHerbieConf::Default,
        }
    }
}

impl From<UxConf> for Conf {
    fn from(ux: UxConf) -> Conf {
        Conf {
            db_path: ux.db_path.map_or(DEFAULT_DB_PATH.into(), Into::into),
            herbie_seed: ux.herbie_seed.map_or(DEFAULT_HERBIE_SEED.into(), Into::into),
            timeout: ux.timeout.map_or(Some(DEFAULT_TIMEOUT), |t| {
                if t == 0 {
                    None
                }
                else {
                    Some(t)
                }
            }),
            use_herbie: ux.use_herbie.map_or(UseHerbieConf::Default, |u| {
                if u {
                    UseHerbieConf::Yes
                }
                else {
                    UseHerbieConf::No
                }
            }),
        }
    }
}

#[derive(Debug)]
pub enum ConfError {
    IOError {
        error: IOError,
    },
    ParseError,
}

impl std::fmt::Display for ConfError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            ConfError::IOError{ ref error } => write!(f, "Error reading Herbie.toml: {}", error),
            ConfError::ParseError => write!(f, "Syntax error in Herbie.toml"),
        }
    }
}

impl From<IOError> for ConfError {
    fn from(err: IOError) -> ConfError {
        ConfError::IOError { error: err }
    }
}

pub fn read_conf() -> Result<Conf, ConfError> {
    if let Ok(mut conf) = File::open("Herbie.toml") {
        let mut buffer = String::new();
        try!(conf.read_to_string(&mut buffer));

        if let Some(conf) = toml::decode_str::<UxConf>(&buffer) {
            Ok(conf.into())
        }
        else {
            Err(ConfError::ParseError)
        }
    }
    else {
        Ok(Conf::default())
    }
}
<|endoftext|>


<commit_before>//! This module provides an oct-tree of cubes. Each leaf cube describes a
//! spatial partition, its properties, and a deformable geometry.

extern crate nalgebra;
extern crate num;

use ::nalgebra::Origin;
use ::num::{One, Zero}; // TODO: `use ::std::num::{One, Zero};`.
use ::std::error;
use ::std::error::Error;
use ::std::fmt;
use ::std::mem;
use ::std::ops;

use math::{Clamp, Mask};
use resource::ResourceId;

pub const MAX_WIDTH: RootWidth = 32;
pub const MIN_WIDTH: RootWidth = 4;

pub type Domain = u32;
pub type Point3 = nalgebra::Point3<Domain>;
pub type Vector3 = nalgebra::Vector3<Domain>;
pub type RootWidth = u8; // TODO: https://github.com/rust-lang/rfcs/issues/671

impl Clamp<RootWidth> for RootWidth {
    fn clamp(&self, min: RootWidth, max: RootWidth) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

#[derive(Clone)]
pub struct Partition {
    origin: Point3,
    width: RootWidth,
}

impl Partition {
    fn at_point(point: &Point3, width: RootWidth) -> Self {
        Partition {
            origin: point.mask(!Domain::zero() << width),
            width: width,
        }
    }

    fn at_index(&self, index: usize) -> Option<Self> {
        if self.width > MIN_WIDTH {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        } else {
            None
        }
    }

    pub fn origin(&self) -> &Point3 {
        &self.origin
    }

    pub fn width(&self) -> RootWidth {
        self.width
    }

    pub fn midpoint(&self) -> Point3 {
        let m = exp(self.width - 1);
        Point3::new(m, m, m)
    }
}

pub trait Traversal: ops::Deref<Target = Cube> {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;
}

pub trait TraversalMut: Traversal + ops::DerefMut {}

#[derive(Clone)]
pub struct Cursor<'a> {
    cube: &'a Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> Cursor<'a> {
    fn new(cube: &'a Cube, root: &'a Partition, partition: Partition) -> Self {
        Cursor {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn iter(&self) -> CursorIter {
        CursorIter::new(self.clone())
    }

    pub fn at_point(&self, point: &Point3, width: RootWidth) -> Self {
        let mut cube = self.cube;
        let mut depth = self.partition.width();

        // Clamp the inputs.
        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            match *cube {
                Cube::Branch(ref branch) => {
                    depth = depth - 1;
                    cube = &branch.cubes[index_at_point(&point, depth)]
                }
                _ => break,
            }
        }

        Cursor::new(cube, self.root, Partition::at_point(&point, depth))
    }
}

impl<'a> Traversal for Cursor<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ops::Deref for Cursor<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

pub struct CursorIter<'a> {
    cursors: Vec<Cursor<'a>>,
}

impl<'a> CursorIter<'a> {
    fn new(cursor: Cursor<'a>) -> Self {
        CursorIter { cursors: vec![cursor] }
    }
}

impl<'a> Iterator for CursorIter<'a> {
    type Item = Cursor<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(cursor) = self.cursors.pop() {
            match *cursor.cube {
                Cube::Branch(ref branch) => {
                    for (index, cube) in branch.iter().enumerate() {
                        self.cursors.push(Cursor::new(cube,
                                                      cursor.root,
                                                      cursor.partition().at_index(index).unwrap()));
                    }
                }
                _ => {}
            }
            Some(cursor)
        } else {
            None
        }
    }
}

#[derive(Debug)]
pub enum JoinError {
    LeafJoined,
}

impl fmt::Display for JoinError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for JoinError {
    fn description(&self) -> &str {
        match *self {
            JoinError::LeafJoined => "attempted to join leaf",
        }
    }
}

#[derive(Debug)]
pub enum SubdivideError {
    LimitExceeded,
    BranchSubdivided,
}

impl fmt::Display for SubdivideError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for SubdivideError {
    fn description(&self) -> &str {
        match *self {
            SubdivideError::LimitExceeded => "minimum width limit exceeded",
            SubdivideError::BranchSubdivided => "attempted to subdivide branch",
        }
    }
}

pub struct CursorMut<'a> {
    cube: &'a mut Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> CursorMut<'a> {
    fn new(cube: &'a mut Cube, root: &'a Partition, partition: Partition) -> Self {
        CursorMut {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn at_point(&'a mut self, point: &Point3, width: RootWidth) -> Self {
        let mut cube: Option<&mut Cube> = Some(self.cube);
        let mut depth = self.partition.width();

        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            let inner = cube.take().unwrap();
            match *inner {
                Cube::Branch(ref mut branch) => {
                    depth = depth - 1;
                    cube = Some(&mut branch.cubes[index_at_point(&point, depth)]);
                }
                _ => {
                    cube = Some(inner);
                    break;
                }
            }
        }

        CursorMut::new(cube.take().unwrap(),
                       self.root,
                       Partition::at_point(&point, depth))
    }

    pub fn join(&mut self) -> Result<&mut Self, JoinError> {
        try!(self.cube.join().ok_or(JoinError::LeafJoined));
        Ok(self)
    }

    pub fn subdivide(&mut self) -> Result<&mut Self, SubdivideError> {
        if self.partition.width() > MIN_WIDTH {
            try!(self.cube.subdivide().ok_or(SubdivideError::BranchSubdivided));
            Ok(self)
        } else {
            Err(SubdivideError::LimitExceeded)
        }
    }
}

impl<'a> Traversal for CursorMut<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> TraversalMut for CursorMut<'a> {}

impl<'a> ops::Deref for CursorMut<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

impl<'a> ops::DerefMut for CursorMut<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.cube
    }
}

pub struct Tree {
    cube: Cube,
    partition: Partition,
}

impl Tree {
    pub fn new(width: RootWidth) -> Self {
        Tree {
            cube: Cube::new(),
            partition: Partition::at_point(&Point3::origin(),
                                           width.clamp(MIN_WIDTH, MAX_WIDTH)),
        }
    }

    pub fn cursor(&self) -> Cursor {
        Cursor::new(&self.cube, &self.partition, self.partition.clone())
    }

    pub fn cursor_mut(&mut self) -> CursorMut {
        CursorMut::new(&mut self.cube, &self.partition, self.partition.clone())
    }
}

impl Traversal for Tree {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        0
    }
}

impl TraversalMut for Tree {}

impl ops::Deref for Tree {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        &self.cube
    }
}

impl ops::DerefMut for Tree {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.cube
    }
}

#[derive(Clone)]
pub enum Cube {
    Leaf(LeafNode),
    Branch(BranchNode),
}

impl Cube {
    fn new() -> Self {
        Cube::Leaf(LeafNode::new())
    }

    fn join(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Branch(branch) => {
                *self = branch.join().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    fn subdivide(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Leaf(leaf) => {
                *self = leaf.subdivide().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    pub fn is_leaf(&self) -> bool {
        match *self {
            Cube::Leaf(_) => true,
            _ => false,
        }
    }
}

impl Default for Cube {
    fn default() -> Self {
        Cube::new()
    }
}

impl From<LeafNode> for Cube {
    fn from(leaf: LeafNode) -> Self {
        Cube::Leaf(leaf)
    }
}

impl From<BranchNode> for Cube {
    fn from(branch: BranchNode) -> Self {
        Cube::Branch(branch)
    }
}

#[derive(Clone, Copy)]
pub struct LeafNode {
    pub geometry: [u32; 3],
    pub material: ResourceId,
}

impl LeafNode {
    fn new() -> Self {
        LeafNode {
            geometry: Geometry::full(),
            material: 0,
        }
    }

    fn subdivide(self) -> BranchNode {
        // TODO: Transform the geometry of the parent into the children.
        let cube: Cube = self.into();
        BranchNode {
            cubes: Box::new([cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube]),
        }
    }
}

pub struct BranchNode {
    cubes: Box<[Cube; 8]>,
}

impl BranchNode {
    fn join(self) -> LeafNode {
        // TODO: Copy data from one of the original leaves.
        LeafNode::new()
    }
}

impl Clone for BranchNode {
    fn clone(&self) -> Self {
        BranchNode {
            cubes: Box::new([self.cubes[0].clone(),
                             self.cubes[1].clone(),
                             self.cubes[2].clone(),
                             self.cubes[3].clone(),
                             self.cubes[4].clone(),
                             self.cubes[5].clone(),
                             self.cubes[6].clone(),
                             self.cubes[7].clone()]),
        }
    }
}

impl ops::Deref for BranchNode {
    type Target = [Cube];

    fn deref(&self) -> &Self::Target {
        &*self.cubes
    }
}

trait Geometry {
    fn full() -> Self;
    fn empty() -> Self;
}

impl Geometry for [u32; 3] {
    fn full() -> Self {
        [0x0F0F0F0F; 3]
    }

    fn empty() -> Self {
        [0x00000000; 3]
    }
}

trait Subdivision {}

impl Subdivision for [Cube; 8] {}

trait Storage {}

impl Storage for Box<[Cube; 8]> {}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn index_at_point(point: &Point3, width: RootWidth) -> usize {
    ((((point.x >> width) & Domain::one()) << 0) |
     (((point.y >> width) & Domain::one()) << 1) |
     (((point.z >> width) & Domain::one()) << 2)) as usize
}

fn vector_at_index(index: usize, width: RootWidth) -> Vector3 {
    assert!(index < 8);
    let index = index as Domain;
    let width = exp(width);
    Vector3::new(((index >> 0) & Domain::one()) * width,
                 ((index >> 1) & Domain::one()) * width,
                 ((index >> 2) & Domain::one()) * width)
}

pub fn exp(width: RootWidth) -> Domain {
    if width > 0 {
        Domain::one() << (width - 1)
    } else {
        0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Store axis-aligned edges and geometry in leaf nodes.<commit_after>//! This module provides an oct-tree of cubes. Each leaf cube describes a
//! spatial partition, its properties, and a deformable geometry.

extern crate nalgebra;
extern crate num;

use ::nalgebra::Origin;
use ::num::{One, Zero}; // TODO: `use ::std::num::{One, Zero};`.
use ::std::error;
use ::std::error::Error;
use ::std::fmt;
use ::std::mem;
use ::std::ops;

use math::{Clamp, Mask};
use resource::ResourceId;

pub const MAX_WIDTH: RootWidth = 32;
pub const MIN_WIDTH: RootWidth = 4;

pub type Domain = u32;
pub type Point3 = nalgebra::Point3<Domain>;
pub type Vector3 = nalgebra::Vector3<Domain>;
pub type RootWidth = u8; // TODO: https://github.com/rust-lang/rfcs/issues/671

impl Clamp<RootWidth> for RootWidth {
    fn clamp(&self, min: RootWidth, max: RootWidth) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

#[derive(Clone)]
pub struct Partition {
    origin: Point3,
    width: RootWidth,
}

impl Partition {
    fn at_point(point: &Point3, width: RootWidth) -> Self {
        Partition {
            origin: point.mask(!Domain::zero() << width),
            width: width,
        }
    }

    fn at_index(&self, index: usize) -> Option<Self> {
        if self.width > MIN_WIDTH {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        } else {
            None
        }
    }

    pub fn origin(&self) -> &Point3 {
        &self.origin
    }

    pub fn width(&self) -> RootWidth {
        self.width
    }

    pub fn midpoint(&self) -> Point3 {
        let m = exp(self.width - 1);
        Point3::new(m, m, m)
    }
}

pub trait Traversal: ops::Deref<Target = Cube> {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;
}

pub trait TraversalMut: Traversal + ops::DerefMut {}

#[derive(Clone)]
pub struct Cursor<'a> {
    cube: &'a Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> Cursor<'a> {
    fn new(cube: &'a Cube, root: &'a Partition, partition: Partition) -> Self {
        Cursor {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn iter(&self) -> CursorIter {
        CursorIter::new(self.clone())
    }

    pub fn at_point(&self, point: &Point3, width: RootWidth) -> Self {
        let mut cube = self.cube;
        let mut depth = self.partition.width();

        // Clamp the inputs.
        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            match *cube {
                Cube::Branch(ref branch) => {
                    depth = depth - 1;
                    cube = &branch.cubes[index_at_point(&point, depth)]
                }
                _ => break,
            }
        }

        Cursor::new(cube, self.root, Partition::at_point(&point, depth))
    }
}

impl<'a> Traversal for Cursor<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ops::Deref for Cursor<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

pub struct CursorIter<'a> {
    cursors: Vec<Cursor<'a>>,
}

impl<'a> CursorIter<'a> {
    fn new(cursor: Cursor<'a>) -> Self {
        CursorIter { cursors: vec![cursor] }
    }
}

impl<'a> Iterator for CursorIter<'a> {
    type Item = Cursor<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(cursor) = self.cursors.pop() {
            match *cursor.cube {
                Cube::Branch(ref branch) => {
                    for (index, cube) in branch.iter().enumerate() {
                        self.cursors.push(Cursor::new(cube,
                                                      cursor.root,
                                                      cursor.partition().at_index(index).unwrap()));
                    }
                }
                _ => {}
            }
            Some(cursor)
        } else {
            None
        }
    }
}

#[derive(Debug)]
pub enum JoinError {
    LeafJoined,
}

impl fmt::Display for JoinError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for JoinError {
    fn description(&self) -> &str {
        match *self {
            JoinError::LeafJoined => "attempted to join leaf",
        }
    }
}

#[derive(Debug)]
pub enum SubdivideError {
    LimitExceeded,
    BranchSubdivided,
}

impl fmt::Display for SubdivideError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for SubdivideError {
    fn description(&self) -> &str {
        match *self {
            SubdivideError::LimitExceeded => "minimum width limit exceeded",
            SubdivideError::BranchSubdivided => "attempted to subdivide branch",
        }
    }
}

pub struct CursorMut<'a> {
    cube: &'a mut Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> CursorMut<'a> {
    fn new(cube: &'a mut Cube, root: &'a Partition, partition: Partition) -> Self {
        CursorMut {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn at_point(&'a mut self, point: &Point3, width: RootWidth) -> Self {
        let mut cube: Option<&mut Cube> = Some(self.cube);
        let mut depth = self.partition.width();

        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            let inner = cube.take().unwrap();
            match *inner {
                Cube::Branch(ref mut branch) => {
                    depth = depth - 1;
                    cube = Some(&mut branch.cubes[index_at_point(&point, depth)]);
                }
                _ => {
                    cube = Some(inner);
                    break;
                }
            }
        }

        CursorMut::new(cube.take().unwrap(),
                       self.root,
                       Partition::at_point(&point, depth))
    }

    pub fn join(&mut self) -> Result<&mut Self, JoinError> {
        try!(self.cube.join().ok_or(JoinError::LeafJoined));
        Ok(self)
    }

    pub fn subdivide(&mut self) -> Result<&mut Self, SubdivideError> {
        if self.partition.width() > MIN_WIDTH {
            try!(self.cube.subdivide().ok_or(SubdivideError::BranchSubdivided));
            Ok(self)
        } else {
            Err(SubdivideError::LimitExceeded)
        }
    }
}

impl<'a> Traversal for CursorMut<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> TraversalMut for CursorMut<'a> {}

impl<'a> ops::Deref for CursorMut<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

impl<'a> ops::DerefMut for CursorMut<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.cube
    }
}

pub struct Tree {
    cube: Cube,
    partition: Partition,
}

impl Tree {
    pub fn new(width: RootWidth) -> Self {
        Tree {
            cube: Cube::new(),
            partition: Partition::at_point(&Point3::origin(),
                                           width.clamp(MIN_WIDTH, MAX_WIDTH)),
        }
    }

    pub fn cursor(&self) -> Cursor {
        Cursor::new(&self.cube, &self.partition, self.partition.clone())
    }

    pub fn cursor_mut(&mut self) -> CursorMut {
        CursorMut::new(&mut self.cube, &self.partition, self.partition.clone())
    }
}

impl Traversal for Tree {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        0
    }
}

impl TraversalMut for Tree {}

impl ops::Deref for Tree {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        &self.cube
    }
}

impl ops::DerefMut for Tree {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.cube
    }
}

#[derive(Clone)]
pub enum Cube {
    Leaf(LeafNode),
    Branch(BranchNode),
}

impl Cube {
    fn new() -> Self {
        Cube::Leaf(LeafNode::new())
    }

    fn join(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Branch(branch) => {
                *self = branch.join().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    fn subdivide(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Leaf(leaf) => {
                *self = leaf.subdivide().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    pub fn is_leaf(&self) -> bool {
        match *self {
            Cube::Leaf(_) => true,
            _ => false,
        }
    }
}

impl Default for Cube {
    fn default() -> Self {
        Cube::new()
    }
}

impl From<LeafNode> for Cube {
    fn from(leaf: LeafNode) -> Self {
        Cube::Leaf(leaf)
    }
}

impl From<BranchNode> for Cube {
    fn from(branch: BranchNode) -> Self {
        Cube::Branch(branch)
    }
}

#[derive(Clone, Copy)]
pub struct LeafNode {
    pub geometry: Geometry,
    pub material: ResourceId,
}

impl LeafNode {
    fn new() -> Self {
        LeafNode {
            geometry: Geometry::full(),
            material: 0,
        }
    }

    fn subdivide(self) -> BranchNode {
        // TODO: Transform the geometry of the parent into the children.
        let cube: Cube = self.into();
        BranchNode {
            cubes: Box::new([cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube]),
        }
    }
}

pub struct BranchNode {
    cubes: Box<[Cube; 8]>,
}

impl BranchNode {
    fn join(self) -> LeafNode {
        // TODO: Copy data from one of the original leaves.
        LeafNode::new()
    }
}

impl Clone for BranchNode {
    fn clone(&self) -> Self {
        BranchNode {
            cubes: Box::new([self.cubes[0].clone(),
                             self.cubes[1].clone(),
                             self.cubes[2].clone(),
                             self.cubes[3].clone(),
                             self.cubes[4].clone(),
                             self.cubes[5].clone(),
                             self.cubes[6].clone(),
                             self.cubes[7].clone()]),
        }
    }
}

impl ops::Deref for BranchNode {
    type Target = [Cube];

    fn deref(&self) -> &Self::Target {
        &*self.cubes
    }
}

#[derive(Copy, Clone)]
pub struct Geometry([[Edge; 4]; 3]);

impl Geometry {
    fn full() -> Self {
        Geometry([[Edge::full(); 4]; 3])
    }

    fn empty() -> Self {
        Geometry([[Edge::converged(0); 4]; 3])
    }

    pub fn as_edges_x(&self) -> &[Edge; 4] {
        &self.0[0]
    }
    pub fn as_edges_y(&self) -> &[Edge; 4] {
        &self.0[1]
    }
    pub fn as_edges_z(&self) -> &[Edge; 4] {
        &self.0[2]
    }

    pub fn as_edges_x_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[0]
    }
    pub fn as_edges_y_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[1]
    }
    pub fn as_edges_z_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[2]
    }
}

#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Edge(u8);

const MAX_EDGE: u8 = 0x0F;

impl Edge {
    fn full() -> Self {
        Edge(MAX_EDGE)
    }

    fn converged(value: u8) -> Self {
        let value = nalgebra::clamp(value, 0, MAX_EDGE);
        Edge((value << 4) | value)
    }

    pub fn set_front(&mut self, value: u8) {
        let value = nalgebra::clamp(value, 0, self.back());
        self.0 = (value << 4) | self.back();
    }

    pub fn set_back(&mut self, value: u8) {
        let value = nalgebra::clamp(value, self.front(), MAX_EDGE);
        self.0 = (self.front() << 4) | value;
    }

    pub fn front(&self) -> u8 {
        (self.0 & 0xF0) >> 4
    }

    pub fn back(&self) -> u8 {
        self.0 & 0x0F
    }

    pub fn front_transform(&self) -> f32 {
        (self.front() as f32) / (MAX_EDGE as f32)
    }

    pub fn back_transform(&self) -> f32 {
        -((MAX_EDGE - self.back()) as f32) / (MAX_EDGE as f32)
    }
}

trait Subdivision {}

impl Subdivision for [Cube; 8] {}

trait Storage {}

impl Storage for Box<[Cube; 8]> {}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn index_at_point(point: &Point3, width: RootWidth) -> usize {
    ((((point.x >> width) & Domain::one()) << 0) |
     (((point.y >> width) & Domain::one()) << 1) |
     (((point.z >> width) & Domain::one()) << 2)) as usize
}

fn vector_at_index(index: usize, width: RootWidth) -> Vector3 {
    assert!(index < 8);
    let index = index as Domain;
    let width = exp(width);
    Vector3::new(((index >> 0) & Domain::one()) * width,
                 ((index >> 1) & Domain::one()) * width,
                 ((index >> 2) & Domain::one()) * width)
}

pub fn exp(width: RootWidth) -> Domain {
    if width > 0 {
        Domain::one() << (width - 1)
    } else {
        0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>extern crate hyper;

use hyper::Url;
use hyper::client::Request;

fn main() {
    println!("24 days of Rust - hyper (day 5)");
    let url = match Url::parse("http://httpbin.org/status/200") {
        Ok(url) => url,
        Err(_) => panic!("Uh oh."),
    };
    println!("> get: {}", url);
    let fresh_request = match Request::get(url) {
        Ok(request) => request,
        Err(_) => panic!("Whoops."),
    };
    let streaming_request = match fresh_request.start() {
        Ok(request) => request,
        Err(_) => panic!("Noooo."),
    };
    let mut response = match streaming_request.send() {
        Ok(response) => response,
        Err(_) => panic!("So close..."),
    };
    println!("< status code: {}", response.status);
    let content = match response.read_to_string() {
        Ok(content) => content,
        Err(_) => panic!("I give up."),
    };
    println!("{}", content);
}
<commit_msg>Refactored get request.<commit_after>extern crate hyper;

use hyper::{HttpError, HttpResult, Url};
use hyper::client::Request;

fn get_content(url: &str) -> HttpResult<String> {
    let url = match Url::parse(url) {
        Ok(url) => url,
        Err(_) => return Err(HttpError::HttpUriError),
    };
    let fresh_request = try!(Request::get(url));
    let streaming_request = try!(fresh_request.start());
    let mut response = try!(streaming_request.send());
    Ok(try!(response.read_to_string()))
}

fn main() {
    println!("24 days of Rust - hyper (day 5)");
    println!("{}", get_content("http://httpbin.org/status/200"));
}
<|endoftext|>


<commit_before>#![feature(phase)]

#[phase(plugin, link)]
extern crate itertools;

fn main() {
    println!("24 days of Rust - itertools (day 7)");
}
<commit_msg>apply example<commit_after>#![feature(phase)]

#[phase(plugin, link)]
extern crate itertools;

use itertools::Itertools;

fn main() {
    println!("24 days of Rust - itertools (day 7)");
    let mut words = "hello supercalifragilisticexpialidocious programmer".words();
    words.apply(|word| println!("{} is {} characters long", word, word.len()));
}
<|endoftext|>


<commit_before>use std::sync::{mpsc, Arc, atomic};
use std::{fs, fmt, thread, path};
use std::io::{self, Seek, SeekFrom, Write, Read};
use std::path::PathBuf;
use slog::Logger;
use util::torrent_name;
use {CONTROL, CONFIG, TC};

pub struct Disk {
    queue: mpsc::Receiver<Request>,
    l: Logger
}

pub struct Handle {
    pub tx: mpsc::Sender<Request>,
}

impl Handle {
    pub fn init(&self) { }

    pub fn get(&self) -> mpsc::Sender<Request> {
        self.tx.clone()
    }
}

unsafe impl Sync for Handle {}

pub enum Request {
    Write { tid: usize, data: Box<[u8; 16384]>, locations: Vec<Location> },
    Read { data: Box<[u8; 16384]>, locations: Vec<Location>, context: Ctx },
    Serialize { tid: usize, data: Vec<u8>, hash: [u8; 20] },
    Delete { tid: usize, hash: [u8; 20] },
    Shutdown,
}

pub struct Ctx {
    pub pid: usize,
    pub tid: usize,
    pub idx: u32,
    pub begin: u32,
    pub length: u32,
}

impl Ctx {
    pub fn new(pid: usize, tid: usize, idx: u32, begin: u32, length: u32) -> Ctx {
        Ctx { pid, tid, idx, begin, length }
    }
}

impl Request {
    pub fn write(tid: usize, data: Box<[u8; 16384]>, locations: Vec<Location>) -> Request {
        Request::Write { tid, data, locations }
    }

    pub fn read(context: Ctx, data: Box<[u8; 16384]>, locations: Vec<Location>) -> Request {
        Request::Read { context, data, locations }
    }

    pub fn serialize(tid: usize, data: Vec<u8>, hash: [u8; 20]) -> Request {
        Request::Serialize { tid, data, hash }
    }

    pub fn delete(tid: usize, hash: [u8; 20]) -> Request {
        Request::Delete { tid, hash }
    }

    pub fn shutdown() -> Request {
        Request::Shutdown
    }
}

pub struct Location {
    pub file: PathBuf,
    pub offset: u64,
    pub start: usize,
    pub end: usize,
}

impl Location {
    pub fn new(file: PathBuf, offset: u64, start: usize, end: usize) -> Location {
        Location { file, offset, start, end }
    }
}

pub enum Response {
    Read { context: Ctx, data: Arc<Box<[u8; 16384]>> },
    Error { tid: usize, err: io::Error, }
}

impl Response {
    pub fn read(context: Ctx, data: Arc<Box<[u8; 16384]>>) -> Response {
        Response::Read { context, data }
    }

    pub fn error(tid: usize, err: io::Error) -> Response {
        Response::Error { tid, err }
    }

    pub fn tid(&self) -> usize {
        match *self {
            Response::Read { ref context, .. } => context.tid,
            Response::Error { tid, .. } => tid
        }
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "disk::Response")
    }
}

impl Disk {
    pub fn new(queue: mpsc::Receiver<Request>, l: Logger) -> Disk {
        Disk {
            queue, l
        }
    }

    pub fn run(&mut self) {
        let sd = &CONFIG.session;
        fs::create_dir_all(sd).unwrap();
        debug!(self.l, "Initialized!");
        loop {
            match self.queue.recv() {
                Ok(Request::Write { tid, data, locations }) => {
                    trace!(self.l, "Writing data!");
                    for loc in locations {
                        let res = fs::OpenOptions::new().write(true).open(&loc.file).and_then(|mut f| {
                            f.seek(SeekFrom::Start(loc.offset)).map(|_| f)
                        }).and_then(|mut f| {
                            f.write(&data[loc.start..loc.end])
                        });
                        if let Err(e) = res {
                            CONTROL.disk_tx.lock().unwrap().send(Response::error(tid, e)).unwrap();
                            return;
                        }
                    }
                }
                Ok(Request::Read { context, mut data, locations }) =>  {
                    trace!(self.l, "Reading data!");
                    for loc in locations {
                        let res = fs::OpenOptions::new().read(true).open(&loc.file).and_then(|mut f| {
                            f.seek(SeekFrom::Start(loc.offset)).unwrap();
                            f.seek(SeekFrom::Start(loc.offset)).map(|_| f)
                        }).and_then(|mut f| {
                            f.read(&mut data[loc.start..loc.end])
                        });
                        if let Err(e) = res {
                            CONTROL.disk_tx.lock().unwrap().send(Response::error(context.tid, e)).unwrap();
                            return;
                        }
                    }
                    let data = Arc::new(data);
                    CONTROL.disk_tx.lock().unwrap().send(Response::read(context, data)).unwrap();
                }
                Ok(Request::Serialize { tid, data, hash }) => {
                    trace!(self.l, "Serializing torrent!");
                    let mut pb = path::PathBuf::from(sd);
                    pb.push(torrent_name(&hash));
                    let res = fs::OpenOptions::new().write(true).create(true).open(&pb).and_then(|mut f| {
                        f.write(&data)
                    });
                    if let Err(e) = res {
                        CONTROL.disk_tx.lock().unwrap().send(Response::error(tid, e)).unwrap();
                        return;
                    }
                }
                Ok(Request::Delete { tid, hash } ) => {
                    trace!(self.l, "Deleting torrent!");
                    let mut pb = path::PathBuf::from(sd);
                    pb.push(torrent_name(&hash));
                    if let Err(e) = fs::remove_file(pb) {
                        CONTROL.disk_tx.lock().unwrap().send(Response::error(tid, e)).unwrap();
                    }
                }
                Ok(Request::Shutdown) => {
                    break
                }
                _ => break,
            }
        }
    }
}

pub fn start(l: Logger) -> Handle {
    debug!(l, "Initializing!");
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        Disk::new(rx, l.clone()).run();
        TC.fetch_sub(1, atomic::Ordering::SeqCst);
        debug!(l, "Shutdown!");
    });
    Handle { tx }
}
<commit_msg>Remove unnecessary seek<commit_after>use std::sync::{mpsc, Arc, atomic};
use std::{fs, fmt, thread, path};
use std::io::{self, Seek, SeekFrom, Write, Read};
use std::path::PathBuf;
use slog::Logger;
use util::torrent_name;
use {CONTROL, CONFIG, TC};

pub struct Disk {
    queue: mpsc::Receiver<Request>,
    l: Logger
}

pub struct Handle {
    pub tx: mpsc::Sender<Request>,
}

impl Handle {
    pub fn init(&self) { }

    pub fn get(&self) -> mpsc::Sender<Request> {
        self.tx.clone()
    }
}

unsafe impl Sync for Handle {}

pub enum Request {
    Write { tid: usize, data: Box<[u8; 16384]>, locations: Vec<Location> },
    Read { data: Box<[u8; 16384]>, locations: Vec<Location>, context: Ctx },
    Serialize { tid: usize, data: Vec<u8>, hash: [u8; 20] },
    Delete { tid: usize, hash: [u8; 20] },
    Shutdown,
}

pub struct Ctx {
    pub pid: usize,
    pub tid: usize,
    pub idx: u32,
    pub begin: u32,
    pub length: u32,
}

impl Ctx {
    pub fn new(pid: usize, tid: usize, idx: u32, begin: u32, length: u32) -> Ctx {
        Ctx { pid, tid, idx, begin, length }
    }
}

impl Request {
    pub fn write(tid: usize, data: Box<[u8; 16384]>, locations: Vec<Location>) -> Request {
        Request::Write { tid, data, locations }
    }

    pub fn read(context: Ctx, data: Box<[u8; 16384]>, locations: Vec<Location>) -> Request {
        Request::Read { context, data, locations }
    }

    pub fn serialize(tid: usize, data: Vec<u8>, hash: [u8; 20]) -> Request {
        Request::Serialize { tid, data, hash }
    }

    pub fn delete(tid: usize, hash: [u8; 20]) -> Request {
        Request::Delete { tid, hash }
    }

    pub fn shutdown() -> Request {
        Request::Shutdown
    }
}

pub struct Location {
    pub file: PathBuf,
    pub offset: u64,
    pub start: usize,
    pub end: usize,
}

impl Location {
    pub fn new(file: PathBuf, offset: u64, start: usize, end: usize) -> Location {
        Location { file, offset, start, end }
    }
}

pub enum Response {
    Read { context: Ctx, data: Arc<Box<[u8; 16384]>> },
    Error { tid: usize, err: io::Error, }
}

impl Response {
    pub fn read(context: Ctx, data: Arc<Box<[u8; 16384]>>) -> Response {
        Response::Read { context, data }
    }

    pub fn error(tid: usize, err: io::Error) -> Response {
        Response::Error { tid, err }
    }

    pub fn tid(&self) -> usize {
        match *self {
            Response::Read { ref context, .. } => context.tid,
            Response::Error { tid, .. } => tid
        }
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "disk::Response")
    }
}

impl Disk {
    pub fn new(queue: mpsc::Receiver<Request>, l: Logger) -> Disk {
        Disk {
            queue, l
        }
    }

    pub fn run(&mut self) {
        let sd = &CONFIG.session;
        fs::create_dir_all(sd).unwrap();
        debug!(self.l, "Initialized!");
        loop {
            match self.queue.recv() {
                Ok(Request::Write { tid, data, locations }) => {
                    trace!(self.l, "Writing data!");
                    for loc in locations {
                        let res = fs::OpenOptions::new().write(true).open(&loc.file).and_then(|mut f| {
                            f.seek(SeekFrom::Start(loc.offset)).map(|_| f)
                        }).and_then(|mut f| {
                            f.write(&data[loc.start..loc.end])
                        });
                        if let Err(e) = res {
                            CONTROL.disk_tx.lock().unwrap().send(Response::error(tid, e)).unwrap();
                            return;
                        }
                    }
                }
                Ok(Request::Read { context, mut data, locations }) =>  {
                    trace!(self.l, "Reading data!");
                    for loc in locations {
                        let res = fs::OpenOptions::new().read(true).open(&loc.file).and_then(|mut f| {
                            f.seek(SeekFrom::Start(loc.offset)).map(|_| f)
                        }).and_then(|mut f| {
                            f.read(&mut data[loc.start..loc.end])
                        });
                        if let Err(e) = res {
                            CONTROL.disk_tx.lock().unwrap().send(Response::error(context.tid, e)).unwrap();
                            return;
                        }
                    }
                    let data = Arc::new(data);
                    CONTROL.disk_tx.lock().unwrap().send(Response::read(context, data)).unwrap();
                }
                Ok(Request::Serialize { tid, data, hash }) => {
                    trace!(self.l, "Serializing torrent!");
                    let mut pb = path::PathBuf::from(sd);
                    pb.push(torrent_name(&hash));
                    let res = fs::OpenOptions::new().write(true).create(true).open(&pb).and_then(|mut f| {
                        f.write(&data)
                    });
                    if let Err(e) = res {
                        CONTROL.disk_tx.lock().unwrap().send(Response::error(tid, e)).unwrap();
                        return;
                    }
                }
                Ok(Request::Delete { tid, hash } ) => {
                    trace!(self.l, "Deleting torrent!");
                    let mut pb = path::PathBuf::from(sd);
                    pb.push(torrent_name(&hash));
                    if let Err(e) = fs::remove_file(pb) {
                        CONTROL.disk_tx.lock().unwrap().send(Response::error(tid, e)).unwrap();
                    }
                }
                Ok(Request::Shutdown) => {
                    break
                }
                _ => break,
            }
        }
    }
}

pub fn start(l: Logger) -> Handle {
    debug!(l, "Initializing!");
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        Disk::new(rx, l.clone()).run();
        TC.fetch_sub(1, atomic::Ordering::SeqCst);
        debug!(l, "Shutdown!");
    });
    Handle { tx }
}
<|endoftext|>


<commit_before>//! This module contains the game logic

use std::f64;
use std::env::current_exe;

use graphics::{self, Transformed};
use itertools;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::input::*;
use rand::{self, ThreadRng};

use drawing::{color, Point, Size};
use models::{Bullet, Enemy, Particle, Vector, World};
use traits::{Advance, Collide, Position};

const UPS: u16 = 120;
const BULLET_RATE: f64 = 0.01;

/// The data structure that drives the game
pub struct Game {
    /// The world contains everything that needs to be drawn
    world: World,
    /// The current score of the player
    score: u32,
    /// The active actions
    actions: Actions,
    /// Timers needed by the game
    timers: Timers,
    /// A random number generator
    rng: ThreadRng,
    /// Resources needed for drawing
    resources: Resources
}

/// Active actions (toggled by user input)
#[derive(Default)]
struct Actions {
    rotate_left: bool,
    rotate_right: bool,
    boost: bool,
    shoot: bool
}

/// Timers to handle creation of bullets, enemies and particles
#[derive(Default)]
struct Timers {
    current_time: f64,
    last_tail_particle: f64,
    last_shoot: f64,
    last_spawned_enemy: f64
}

/// Additional resources needed for the game
struct Resources {
    font: GlyphCache<'static>
}

impl Game {
    /// Returns a new `Game` containing a `World` of the given `Size`
    pub fn new(size: Size) -> Game {
        let mut rng = rand::thread_rng();
        let exe_directory = current_exe().unwrap().parent().unwrap().to_owned();
        Game {
            world: World::new(&mut rng, size),
            score: 0,
            actions: Actions::default(),
            timers: Timers::default(),
            rng: rng,
            resources: Resources { font: GlyphCache::new(&exe_directory.join("resources/FiraMono-Bold.ttf")).unwrap() }
        }
    }

    /// Processes a key press
    pub fn key_press(&mut self, key: Key) {
        self.handle_key(key, true);
    }

    /// Processes a key release
    pub fn key_release(&mut self, key: Key) {
        self.handle_key(key, false);
    }

    /// Handles a key press or release
    fn handle_key(&mut self, key: Key, pressed: bool) {
        match key {
            Key::Left => self.actions.rotate_left = pressed,
            Key::Right => self.actions.rotate_right = pressed,
            Key::Up => self.actions.boost = pressed,
            Key::Space => self.actions.shoot = pressed,
            _ => ()
        }
    }

    /// Processes a key press
    pub fn button_press(&mut self, joystick: JoystickButton) {
        self.handle_button(joystick, true);
    }

    /// Processes a key release
    pub fn button_release(&mut self, joystick: JoystickButton) {
        self.handle_button(joystick, false);
    }

    /// Handles a button press or release
    fn handle_button(&mut self, joystick: JoystickButton, pressed: bool) {
        // Button 10 is A button on XInput
        match joystick.button {
            10 => self.actions.shoot = pressed,
            _ => ()
        }
    }

    /// Handles a joystick axis input
    pub fn handle_axis(&mut self, joystick: JoystickAxisArgs) {

        // Axis 0 is left stick (XInput). -1.0 left to 1.0 right
        if joystick.axis == 0 {
            match joystick.position {
                -1.0 ... -0.2 => {
                    self.actions.rotate_left = true;
                    self.actions.rotate_right = false;
                },
                0.2 ... 1.0 => {
                    self.actions.rotate_left = false;
                    self.actions.rotate_right = true;
                },
                -0.199 ... 0.199 => {
                    self.actions.rotate_left = false;
                    self.actions.rotate_right = false;
                },
                _ => {}
            }
        }

        // Axis 5 is right trigger (XInput). -1.0 is not pressed, 1.0 is fully pressed
        if joystick.axis == 5 {
            match joystick.position {
                -0.8 ... 1.0 => {
                    self.actions.boost = true;
                },
                -1.0 ... -0.799 => {
                    self.actions.boost = false;
                },
                _ => {}
            }
        }

        // TODO: Actually use stick position value to affect rotation amount
        //       Actually use trigger position value affect boost amount
    }

    /// Renders the game to the screen
    pub fn render(&mut self, c: graphics::context::Context, g: &mut GlGraphics) {
        // Clear everything
        graphics::clear(color::BLACK, g);

        // Render the world
        self.world.render(c, g);

        // Render the score
        let mut text = graphics::Text::new(22);
        text.color = color::ORANGE;
        text.draw(&format!("Score: {}", self.score),
                  &mut self.resources.font,
                  &c.draw_state,
                  c.trans(10.0, 20.0).transform,
                  g);
    }

    /// Updates the game
    ///
    /// `dt` is the amount of seconds that have passed since the last update
    pub fn update(&mut self, dt: f64) {
        self.timers.current_time += dt;

        // Update rocket rotation
        if self.actions.rotate_left {
            *self.world.player.direction_mut() += (-0.06 * UPS as f64) * dt;
        }
        if self.actions.rotate_right {
            *self.world.player.direction_mut() += (0.06 * UPS as f64) * dt;
        };

        // Set speed and advance the player with wrap around
        let speed = if self.actions.boost { 400.0  } else { 200.0 };
        self.world.player.advance_wrapping(dt * speed, self.world.size.clone());

        // Update particles
        for particle in &mut self.world.particles {
            particle.update(dt);
        }

        // Remove old particles
        self.world.particles.retain(|p| p.ttl > 0.0);

        // Add new particles at the player's position, to leave a trail
        if self.timers.current_time - self.timers.last_tail_particle > 0.05 {
            self.timers.last_tail_particle = self.timers.current_time;
            self.world.particles.push(Particle::new(self.world.player.vector.clone().invert(), 0.5));
        }

        // Add bullets
        if self.actions.shoot && self.timers.current_time - self.timers.last_shoot > BULLET_RATE {
            self.timers.last_shoot = self.timers.current_time;
            self.world.bullets.push(Bullet::new(Vector::new(self.world.player.nose(), self.world.player.direction())));
        }

        // Advance bullets
        for bullet in &mut self.world.bullets {
            bullet.update(dt * 500.0);
        }

        // Remove bullets outside the viewport
        { // Shorten the lifetime of size
        let size = &self.world.size;
        self.world.bullets.retain(|b| size.contains(b.position()));
        }

        // Spawn enemies at random locations
        if self.timers.current_time - self.timers.last_spawned_enemy > 1.0 {
            self.timers.last_spawned_enemy = self.timers.current_time;
            let mut new_enemy: Enemy;
            loop {
                new_enemy = Enemy::new(Vector::random(&mut self.rng, self.world.size.clone()));
                if !self.world.player.collides_with(&new_enemy) {
                    break;
                }
            }
            self.world.enemies.push(new_enemy);
        }

        // Move enemies in the player's direction
        for enemy in &mut self.world.enemies {
            enemy.update(dt * 100.0, self.world.player.position());
        }

        self.handle_player_collisions();
        self.handle_bullet_collisions();
    }

    /// Handles collisions between the bullets and the enemies
    ///
    /// When an enemy is reached by a bullet, both the enemy and the bullet
    /// will be removed. Additionally, the score will be increased by 10
    fn handle_bullet_collisions(&mut self) {
        let old_enemy_count = self.world.enemies.len();

        { // We introduce a scope to shorten the lifetime of the borrows below
        // The references are to avoid using self in the closure
        // (the borrow checker doesn't like that)
        let bullets = &mut self.world.bullets;
        let enemies = &mut self.world.enemies;
        let particles = &mut self.world.particles;

        bullets.retain(|bullet| {
            // Remove the first enemy that collides with a bullet (if any)
            // Add an explosion on its place
            if let Some((index, position)) = enemies.iter().enumerate()
                .find(|&(_, enemy)| enemy.collides_with(bullet))
                .map(|(index, enemy)| (index, enemy.position()))
            {
                Game::make_explosion(particles, position, 10);
                enemies.remove(index);
                false
            } else {
                true
            }
        });
        }

        let killed_enemies = (old_enemy_count - self.world.enemies.len()) as u32;
        self.score += 10 * killed_enemies;
    }

    /// reset our game-state
    fn reset(&mut self) {
        // Reset player position
        *self.world.player.x_mut() = self.world.size.random_x(&mut self.rng);
        *self.world.player.y_mut() = self.world.size.random_y(&mut self.rng);

        // Reset score
        self.score = 0;

        // Remove all enemies and bullets
        self.world.bullets.clear();
        self.world.enemies.clear();
    }

    /// Handles collisions between the player and the enemies
    fn handle_player_collisions(&mut self) {
        if self.world.enemies.iter().any(|enemy| self.world.player.collides_with(enemy)) {
            // Make an explosion where the player was
            let ppos = self.world.player.position();
            Game::make_explosion(&mut self.world.particles, ppos, 8);

            self.reset();
        }
    }

    // Generates a new explosion of the given intensity at the given position. This works best with values between 5 and 25
    fn make_explosion(particles: &mut Vec<Particle>, position: Point, intensity: u8) {
        for rotation in itertools::linspace(0.0, 2.0 * f64::consts::PI, 30) {
            for ttl in (1..intensity).map(|x| (x as f64) / 10.0) {
                particles.push(Particle::new(Vector::new(position.clone(), rotation), ttl));
            }
        }
    }
}
<commit_msg>Update game.rs<commit_after>//! This module contains the game logic

use std::f64;
use std::env::current_exe;

use graphics::{self, Transformed};
use itertools;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::input::*;
use rand::{self, ThreadRng};

use drawing::{color, Point, Size};
use models::{Bullet, Enemy, Particle, Vector, World};
use traits::{Advance, Collide, Position};

const UPS: u16 = 120;
const BULLET_RATE: f64 = 0.01;

/// The data structure that drives the game
pub struct Game {
    /// The world contains everything that needs to be drawn
    world: World,
    /// The current score of the player
    score: u32,
    /// The active actions
    actions: Actions,
    /// Timers needed by the game
    timers: Timers,
    /// A random number generator
    rng: ThreadRng,
    /// Resources needed for drawing
    resources: Resources
}

/// Active actions (toggled by user input)
#[derive(Default)]
struct Actions {
    rotate_left: bool,
    rotate_right: bool,
    boost: bool,
    shoot: bool
}

/// Timers to handle creation of bullets, enemies and particles
#[derive(Default)]
struct Timers {
    current_time: f64,
    last_tail_particle: f64,
    last_shoot: f64,
    last_spawned_enemy: f64
}

/// Additional resources needed for the game
struct Resources {
    font: GlyphCache<'static>
}

impl Game {
    /// Returns a new `Game` containing a `World` of the given `Size`
    pub fn new(size: Size) -> Game {
        let mut rng = rand::thread_rng();
        let exe_directory = current_exe().unwrap().parent().unwrap().to_owned();
        Game {
            world: World::new(&mut rng, size),
            score: 0,
            actions: Actions::default(),
            timers: Timers::default(),
            rng: rng,
            resources: Resources { font: GlyphCache::new(&exe_directory.join("resources/FiraMono-Bold.ttf")).unwrap() }
        }
    }

    /// Processes a key press
    pub fn key_press(&mut self, key: Key) {
        self.handle_key(key, true);
    }

    /// Processes a key release
    pub fn key_release(&mut self, key: Key) {
        self.handle_key(key, false);
    }

    /// Handles a key press or release
    fn handle_key(&mut self, key: Key, pressed: bool) {
        match key {
            Key::Left => self.actions.rotate_left = pressed,
            Key::Right => self.actions.rotate_right = pressed,
            Key::Up => self.actions.boost = pressed,
            Key::Space => self.actions.shoot = pressed,
            _ => ()
        }
    }

    /// Processes a button press
    pub fn button_press(&mut self, controller: ControllerButton) {
        self.handle_button(controller, true);
    }

    /// Processes a button release
    pub fn button_release(&mut self, controller: ControllerButton) {
        self.handle_button(controller, false);
    }

    /// Handles a button press or release
    fn handle_button(&mut self, controller: ControllerButton, pressed: bool) {
        // Button 10 is A button on XInput
        match controller.button {
            10 => self.actions.shoot = pressed,
            _ => ()
        }
    }

    /// Handles a controller axis input
    pub fn handle_axis(&mut self, controller: ControllerAxisArgs) {

        // Axis 0 is left stick (XInput). -1.0 left to 1.0 right
        if controller.axis == 0 {
            match controller.position {
                -1.0 ... -0.2 => {
                    self.actions.rotate_left = true;
                    self.actions.rotate_right = false;
                },
                0.2 ... 1.0 => {
                    self.actions.rotate_left = false;
                    self.actions.rotate_right = true;
                },
                -0.199 ... 0.199 => {
                    self.actions.rotate_left = false;
                    self.actions.rotate_right = false;
                },
                _ => {}
            }
        }

        // Axis 5 is right trigger (XInput). -1.0 is not pressed, 1.0 is fully pressed
        if controller.axis == 5 {
            match controller.position {
                -0.8 ... 1.0 => {
                    self.actions.boost = true;
                },
                -1.0 ... -0.799 => {
                    self.actions.boost = false;
                },
                _ => {}
            }
        }

        // TODO: Actually use stick position value to affect rotation amount
        //       Actually use trigger position value affect boost amount
    }

    /// Renders the game to the screen
    pub fn render(&mut self, c: graphics::context::Context, g: &mut GlGraphics) {
        // Clear everything
        graphics::clear(color::BLACK, g);

        // Render the world
        self.world.render(c, g);

        // Render the score
        let mut text = graphics::Text::new(22);
        text.color = color::ORANGE;
        text.draw(&format!("Score: {}", self.score),
                  &mut self.resources.font,
                  &c.draw_state,
                  c.trans(10.0, 20.0).transform,
                  g);
    }

    /// Updates the game
    ///
    /// `dt` is the amount of seconds that have passed since the last update
    pub fn update(&mut self, dt: f64) {
        self.timers.current_time += dt;

        // Update rocket rotation
        if self.actions.rotate_left {
            *self.world.player.direction_mut() += (-0.06 * UPS as f64) * dt;
        }
        if self.actions.rotate_right {
            *self.world.player.direction_mut() += (0.06 * UPS as f64) * dt;
        };

        // Set speed and advance the player with wrap around
        let speed = if self.actions.boost { 400.0  } else { 200.0 };
        self.world.player.advance_wrapping(dt * speed, self.world.size.clone());

        // Update particles
        for particle in &mut self.world.particles {
            particle.update(dt);
        }

        // Remove old particles
        self.world.particles.retain(|p| p.ttl > 0.0);

        // Add new particles at the player's position, to leave a trail
        if self.timers.current_time - self.timers.last_tail_particle > 0.05 {
            self.timers.last_tail_particle = self.timers.current_time;
            self.world.particles.push(Particle::new(self.world.player.vector.clone().invert(), 0.5));
        }

        // Add bullets
        if self.actions.shoot && self.timers.current_time - self.timers.last_shoot > BULLET_RATE {
            self.timers.last_shoot = self.timers.current_time;
            self.world.bullets.push(Bullet::new(Vector::new(self.world.player.nose(), self.world.player.direction())));
        }

        // Advance bullets
        for bullet in &mut self.world.bullets {
            bullet.update(dt * 500.0);
        }

        // Remove bullets outside the viewport
        { // Shorten the lifetime of size
        let size = &self.world.size;
        self.world.bullets.retain(|b| size.contains(b.position()));
        }

        // Spawn enemies at random locations
        if self.timers.current_time - self.timers.last_spawned_enemy > 1.0 {
            self.timers.last_spawned_enemy = self.timers.current_time;
            let mut new_enemy: Enemy;
            loop {
                new_enemy = Enemy::new(Vector::random(&mut self.rng, self.world.size.clone()));
                if !self.world.player.collides_with(&new_enemy) {
                    break;
                }
            }
            self.world.enemies.push(new_enemy);
        }

        // Move enemies in the player's direction
        for enemy in &mut self.world.enemies {
            enemy.update(dt * 100.0, self.world.player.position());
        }

        self.handle_player_collisions();
        self.handle_bullet_collisions();
    }

    /// Handles collisions between the bullets and the enemies
    ///
    /// When an enemy is reached by a bullet, both the enemy and the bullet
    /// will be removed. Additionally, the score will be increased by 10
    fn handle_bullet_collisions(&mut self) {
        let old_enemy_count = self.world.enemies.len();

        { // We introduce a scope to shorten the lifetime of the borrows below
        // The references are to avoid using self in the closure
        // (the borrow checker doesn't like that)
        let bullets = &mut self.world.bullets;
        let enemies = &mut self.world.enemies;
        let particles = &mut self.world.particles;

        bullets.retain(|bullet| {
            // Remove the first enemy that collides with a bullet (if any)
            // Add an explosion on its place
            if let Some((index, position)) = enemies.iter().enumerate()
                .find(|&(_, enemy)| enemy.collides_with(bullet))
                .map(|(index, enemy)| (index, enemy.position()))
            {
                Game::make_explosion(particles, position, 10);
                enemies.remove(index);
                false
            } else {
                true
            }
        });
        }

        let killed_enemies = (old_enemy_count - self.world.enemies.len()) as u32;
        self.score += 10 * killed_enemies;
    }

    /// reset our game-state
    fn reset(&mut self) {
        // Reset player position
        *self.world.player.x_mut() = self.world.size.random_x(&mut self.rng);
        *self.world.player.y_mut() = self.world.size.random_y(&mut self.rng);

        // Reset score
        self.score = 0;

        // Remove all enemies and bullets
        self.world.bullets.clear();
        self.world.enemies.clear();
    }

    /// Handles collisions between the player and the enemies
    fn handle_player_collisions(&mut self) {
        if self.world.enemies.iter().any(|enemy| self.world.player.collides_with(enemy)) {
            // Make an explosion where the player was
            let ppos = self.world.player.position();
            Game::make_explosion(&mut self.world.particles, ppos, 8);

            self.reset();
        }
    }

    // Generates a new explosion of the given intensity at the given position. This works best with values between 5 and 25
    fn make_explosion(particles: &mut Vec<Particle>, position: Point, intensity: u8) {
        for rotation in itertools::linspace(0.0, 2.0 * f64::consts::PI, 30) {
            for ttl in (1..intensity).map(|x| (x as f64) / 10.0) {
                particles.push(Particle::new(Vector::new(position.clone(), rotation), ttl));
            }
        }
    }
}
<|endoftext|>