<commit_before>use std::fmt;
use std::path;
use std::convert::From;
use std::collections::HashMap;
use std::io::Read;
use std::u16;

use sdl2;
use image;
use gfx;
use gfx::texture;
use gfx::traits::Device;
use gfx::traits::FactoryExt;
use gfx_device_gl;
use gfx_window_sdl;
use gfx::Factory;

use context::Context;
use graphics;
use GameError;
use GameResult;

// Owning the given Image is inconvenient because we might want, say,
// the same Rc<Image> shared among many SpriteBatch'es.
//
// But draw() doesn't
//
// The right way to fix this might be to have another object that implements
// Drawable that is created from a SpriteBatch and an image reference.
// BoundSpriteBatch or something.  That *feels* like the right way to go...
//
// Or just not implement Drawable and provide your own drawing functions, though
// that's squirrelly.
//
// Oh, or maybe make it take a Cow<Image> ?  that might work.

/// A SpriteBatch draws a number of copies of the same image, using a single draw call.
pub struct SpriteBatch {
}

pub type SpriteIdx = usize;

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    pub fn new(image: graphics::Image) {
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which to modify the sprite using `set()`
    pub fn add(&mut self, param: graphics::DrawParam) -> SpriteIdx {
    }

    /// Alters a sprite in the batch to use the given draw params.
    pub fn set(&mut self, handle: SpriteIdx, param: graphics::DrawParam) {
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling `graphics::draw()` on the `SpriteBatch`
    /// will do this automatically.
    pub fn flush(&mut self, ctx: &Context) {
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
    }

    /// Unwraps the contained `Image`
    pub fn into_inner(self) -> Image {
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: Image) -> Image {
    }
}

impl graphics::Drawable for SpriteBatch {
    fn draw_ex(&self, ctx: &mut Context, param: DrawParam) -> GameResult<()> {
        Ok(())
    }
}
<commit_msg>Stubbed out basic spritebatch functionality.<commit_after>use std::fmt;
use std::path;
use std::convert::From;
use std::collections::HashMap;
use std::io::Read;
use std::u16;

use sdl2;
use image;
use gfx;
use gfx::texture;
use gfx::traits::Device;
use gfx::traits::FactoryExt;
use gfx_device_gl;
use gfx_window_sdl;
use gfx::Factory;

use context::Context;
use graphics;
use GameError;
use GameResult;

// Owning the given Image is inconvenient because we might want, say,
// the same Rc<Image> shared among many SpriteBatch'es.
//
// But draw() doesn't
//
// The right way to fix this might be to have another object that implements
// Drawable that is created from a SpriteBatch and an image reference.
// BoundSpriteBatch or something.  That *feels* like the right way to go...
//
// Or just not implement Drawable and provide your own drawing functions, though
// that's squirrelly.
//
// Oh, or maybe make it take a Cow<Image> ?  that might work.

/// A SpriteBatch draws a number of copies of the same image, using a single draw call.
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::DrawParam>,
}

pub type SpriteIdx = usize;

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image: image,
            sprites: vec![],
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which to modify the sprite using `set()`
    pub fn add(&mut self, param: graphics::DrawParam) -> SpriteIdx {
        self.sprites.push(param);
        self.sprites.len() - 1
    }

    /// Alters a sprite in the batch to use the given draw params.
    pub fn set(&mut self, handle: SpriteIdx, param: graphics::DrawParam) {
        self.sprites[handle] = param;
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling `graphics::draw()` on the `SpriteBatch`
    /// will do this automatically.
    pub fn flush(&self, ctx: &mut Context) {
        for s in &self.sprites {
            graphics::draw_ex(ctx, &self.image, *s);
        }
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear()
    }

    /// Unwraps the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }
}

impl graphics::Drawable for SpriteBatch {
    /// Does not properly work yet, ideally the position, scale, etc. of the given
    /// DrawParam would be added to the DrawParam for each sprite.
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        self.flush(ctx);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use base::ast::{self, DisplayEnv, Do, Expr, MutVisitor, Pattern, SpannedAlias, SpannedExpr,
                TypedIdent};
use base::pos::{self, BytePos, Span};
use base::scoped_map::ScopedMap;
use base::symbol::{Symbol, SymbolModule};
use base::types::{self, Type};

struct Environment {
    stack: ScopedMap<Symbol, (Symbol, Span<BytePos>)>,
}

pub fn rename(symbols: &mut SymbolModule, expr: &mut SpannedExpr<Symbol>) {
    enum TailCall {
        TailCall,
        Return,
    }

    struct RenameVisitor<'a: 'b, 'b> {
        symbols: &'b mut SymbolModule<'a>,
        env: Environment,
    }

    impl<'a, 'b> RenameVisitor<'a, 'b> {
        fn new_pattern(&mut self, pattern: &mut ast::SpannedPattern<Symbol>) {
            match pattern.value {
                Pattern::Record { ref mut fields, .. } => for field in fields {
                    match field.value {
                        Some(ref mut pat) => self.new_pattern(pat),
                        None => {
                            let id = field.name.value.clone();
                            let pat = Pattern::Ident(TypedIdent {
                                name: self.stack_var(id, pattern.span),
                                typ: Type::hole(),
                            });
                            field.value = Some(pos::spanned(field.name.span, pat));
                        }
                    }
                },
                Pattern::Ident(ref mut id) => {
                    let new_name = self.stack_var(id.name.clone(), pattern.span);
                    id.name = new_name;
                }
                Pattern::As(ref mut id, ref mut pat) => {
                    let new_name = self.stack_var(id.clone(), pattern.span);
                    *id = new_name;
                    self.new_pattern(pat)
                }
                Pattern::Tuple { ref mut elems, .. } => for elem in elems {
                    self.new_pattern(elem);
                },
                Pattern::Constructor(_, ref mut args) => for arg in args {
                    self.new_pattern(arg);
                },
                Pattern::Literal(_) | Pattern::Error => (),
            }
        }

        fn stack_var(&mut self, id: Symbol, span: Span<BytePos>) -> Symbol {
            let old_id = id.clone();
            let name = self.symbols.string(&id).to_owned();
            let new_id = self.symbols.symbol(format!("{}:{}", name, span.start));
            debug!(
                "Rename binding `{}` = `{}`",
                self.symbols.string(&old_id),
                self.symbols.string(&new_id),
            );
            self.env.stack.insert(old_id, (new_id.clone(), span));
            new_id
        }

        fn stack_type(&mut self, span: Span<BytePos>, alias: &SpannedAlias<Symbol>) {
            // Insert variant constructors into the local scope
            let aliased_type = alias.value.unresolved_type();
            if let Type::Variant(ref row) = **types::remove_forall(aliased_type) {
                for field in types::row_iter(row).cloned() {
                    self.env
                        .stack
                        .insert(field.name.clone(), (field.name, span));
                }
            }
        }

        /// Renames `id` to the unique identifier which have the type `expected`
        /// Returns `Some(new_id)` if renaming was necessary or `None` if no renaming was necessary
        /// as `id` was currently unique (#Int+, #Float*, etc)
        fn rename(&self, id: &Symbol) -> Option<Symbol> {
            self.env.stack.get(id).map(|t| t.0.clone())
        }

        fn rename_expr(&mut self, expr: &mut SpannedExpr<Symbol>) -> TailCall {
            match expr.value {
                Expr::Ident(ref mut id) => if let Some(new_id) = self.rename(&id.name) {
                    debug!("Rename identifier {} = {}", id.name, new_id);
                    id.name = new_id;
                },
                Expr::Record {
                    ref mut exprs,
                    ref mut base,
                    ..
                } => {
                    for expr_field in exprs {
                        match expr_field.value {
                            Some(ref mut expr) => self.visit_expr(expr),
                            None => if let Some(new_id) = self.rename(&expr_field.name.value) {
                                debug!("Rename record field {} = {}", expr_field.name, new_id);
                                expr_field.value = Some(pos::spanned(
                                    expr_field.name.span,
                                    Expr::Ident(TypedIdent {
                                        name: new_id,
                                        typ: Type::hole(),
                                    }),
                                ));
                            },
                        }
                    }

                    if let Some(ref mut base) = *base {
                        self.visit_expr(base);
                    }
                }
                Expr::Infix {
                    ref mut lhs,
                    ref mut op,
                    ref mut rhs,
                    ref mut implicit_args,
                } => {
                    if let Some(new_id) = self.rename(&op.value.name) {
                        debug!(
                            "Rename {} = {}",
                            self.symbols.string(&op.value.name),
                            self.symbols.string(&new_id)
                        );
                        op.value.name = new_id;
                    }
                    self.visit_expr(lhs);
                    self.visit_expr(rhs);
                    for arg in implicit_args {
                        self.visit_expr(arg);
                    }
                }
                Expr::Match(ref mut expr, ref mut alts) => {
                    self.visit_expr(expr);
                    for alt in alts {
                        self.env.stack.enter_scope();
                        self.new_pattern(&mut alt.pattern);
                        self.visit_expr(&mut alt.expr);
                        self.env.stack.exit_scope();
                    }
                }
                Expr::LetBindings(ref mut bindings, ref mut expr) => {
                    self.env.stack.enter_scope();
                    let is_recursive = bindings.iter().all(|bind| !bind.args.is_empty());
                    for bind in bindings.iter_mut() {
                        if !is_recursive {
                            self.visit_expr(&mut bind.expr);
                        }
                        if let Some(ref mut typ) = bind.typ {
                            self.visit_ast_type(typ.as_mut())
                        }
                        self.new_pattern(&mut bind.name);
                    }
                    if is_recursive {
                        for bind in bindings {
                            self.env.stack.enter_scope();
                            for arg in &mut bind.args {
                                arg.name.value.name =
                                    self.stack_var(arg.name.value.name.clone(), expr.span);
                            }
                            self.visit_expr(&mut bind.expr);
                            self.env.stack.exit_scope();
                        }
                    }
                    return TailCall::TailCall;
                }
                Expr::Lambda(ref mut lambda) => {
                    self.env.stack.enter_scope();

                    for arg in &mut lambda.args {
                        arg.name.value.name =
                            self.stack_var(arg.name.value.name.clone(), expr.span);
                    }

                    self.visit_expr(&mut lambda.body);

                    self.env.stack.exit_scope();
                }
                Expr::TypeBindings(ref bindings, _) => {
                    self.env.stack.enter_scope();
                    for bind in bindings {
                        self.stack_type(expr.span, &bind.alias);
                    }

                    return TailCall::TailCall;
                }
                Expr::Do(Do {
                    ref mut id,
                    ref mut bound,
                    ref mut flat_map_id,
                    ..
                }) => {
                    let flat_map = self.symbols.symbol("flat_map");
                    *flat_map_id = Some(Box::new(pos::spanned(
                        id.span,
                        Expr::Ident(TypedIdent {
                            name: flat_map,
                            typ: Type::hole(),
                        }),
                    )));

                    let flat_map_id = flat_map_id
                        .as_mut()
                        .unwrap_or_else(|| ice!("flat_map_id not set before renaming"));

                    self.visit_expr(flat_map_id);
                    self.visit_expr(bound);

                    self.env.stack.enter_scope();

                    id.value.name = self.stack_var(id.value.name.clone(), id.span);

                    return TailCall::TailCall;
                }

                _ => ast::walk_mut_expr(self, expr),
            }
            TailCall::Return
        }
    }

    impl<'a, 'b, 'c> MutVisitor<'c> for RenameVisitor<'a, 'b> {
        type Ident = Symbol;

        fn visit_expr(&mut self, mut expr: &mut SpannedExpr<Self::Ident>) {
            let mut i = 0;
            loop {
                match self.rename_expr(expr) {
                    TailCall::Return => break,
                    TailCall::TailCall => {
                        expr = match { expr }.value {
                            Expr::LetBindings(_, ref mut new_expr)
                            | Expr::TypeBindings(_, ref mut new_expr)
                            | Expr::Do(Do {
                                body: ref mut new_expr,
                                ..
                            }) => new_expr,
                            _ => ice!("Only Let and Type expressions can tailcall"),
                        };
                        i += 1;
                    }
                }
            }

            for _ in 0..i {
                self.env.stack.exit_scope();
            }
        }
    }

    let mut visitor = RenameVisitor {
        symbols: symbols,
        env: Environment {
            stack: ScopedMap::new(),
        },
    };
    visitor.visit_expr(expr);
}
<commit_msg>fix(rename): Rename implicit imports<commit_after>use base::ast::{self, DisplayEnv, Do, Expr, MutVisitor, Pattern, SpannedAlias, SpannedExpr,
                TypedIdent};
use base::pos::{self, BytePos, Span};
use base::scoped_map::ScopedMap;
use base::symbol::{Symbol, SymbolModule};
use base::types::{self, Type};

struct Environment {
    stack: ScopedMap<Symbol, (Symbol, Span<BytePos>)>,
}

pub fn rename(symbols: &mut SymbolModule, expr: &mut SpannedExpr<Symbol>) {
    enum TailCall {
        TailCall,
        Return,
    }

    struct RenameVisitor<'a: 'b, 'b> {
        symbols: &'b mut SymbolModule<'a>,
        env: Environment,
    }

    impl<'a, 'b> RenameVisitor<'a, 'b> {
        fn new_pattern(&mut self, pattern: &mut ast::SpannedPattern<Symbol>) {
            match pattern.value {
                Pattern::Record {
                    ref mut fields,
                    ref mut implicit_import,
                    ..
                } => {
                    for field in fields {
                        match field.value {
                            Some(ref mut pat) => self.new_pattern(pat),
                            None => {
                                let id = field.name.value.clone();
                                let pat = Pattern::Ident(TypedIdent {
                                    name: self.stack_var(id, pattern.span),
                                    typ: Type::hole(),
                                });
                                field.value = Some(pos::spanned(field.name.span, pat));
                            }
                        }
                    }
                    if let Some(ref mut implicit_import) = *implicit_import {
                        let new_name =
                            self.stack_var(implicit_import.value.clone(), implicit_import.span);
                        implicit_import.value = new_name;
                    }
                }
                Pattern::Ident(ref mut id) => {
                    let new_name = self.stack_var(id.name.clone(), pattern.span);
                    id.name = new_name;
                }
                Pattern::As(ref mut id, ref mut pat) => {
                    let new_name = self.stack_var(id.clone(), pattern.span);
                    *id = new_name;
                    self.new_pattern(pat)
                }
                Pattern::Tuple { ref mut elems, .. } => for elem in elems {
                    self.new_pattern(elem);
                },
                Pattern::Constructor(_, ref mut args) => for arg in args {
                    self.new_pattern(arg);
                },
                Pattern::Literal(_) | Pattern::Error => (),
            }
        }

        fn stack_var(&mut self, id: Symbol, span: Span<BytePos>) -> Symbol {
            let old_id = id.clone();
            let name = self.symbols.string(&id).to_owned();
            let new_id = self.symbols.symbol(format!("{}:{}", name, span.start));
            debug!(
                "Rename binding `{}` = `{}`",
                self.symbols.string(&old_id),
                self.symbols.string(&new_id),
            );
            self.env.stack.insert(old_id, (new_id.clone(), span));
            new_id
        }

        fn stack_type(&mut self, span: Span<BytePos>, alias: &SpannedAlias<Symbol>) {
            // Insert variant constructors into the local scope
            let aliased_type = alias.value.unresolved_type();
            if let Type::Variant(ref row) = **types::remove_forall(aliased_type) {
                for field in types::row_iter(row).cloned() {
                    self.env
                        .stack
                        .insert(field.name.clone(), (field.name, span));
                }
            }
        }

        /// Renames `id` to the unique identifier which have the type `expected`
        /// Returns `Some(new_id)` if renaming was necessary or `None` if no renaming was necessary
        /// as `id` was currently unique (#Int+, #Float*, etc)
        fn rename(&self, id: &Symbol) -> Option<Symbol> {
            self.env.stack.get(id).map(|t| t.0.clone())
        }

        fn rename_expr(&mut self, expr: &mut SpannedExpr<Symbol>) -> TailCall {
            match expr.value {
                Expr::Ident(ref mut id) => if let Some(new_id) = self.rename(&id.name) {
                    debug!("Rename identifier {} = {}", id.name, new_id);
                    id.name = new_id;
                },
                Expr::Record {
                    ref mut exprs,
                    ref mut base,
                    ..
                } => {
                    for expr_field in exprs {
                        match expr_field.value {
                            Some(ref mut expr) => self.visit_expr(expr),
                            None => if let Some(new_id) = self.rename(&expr_field.name.value) {
                                debug!("Rename record field {} = {}", expr_field.name, new_id);
                                expr_field.value = Some(pos::spanned(
                                    expr_field.name.span,
                                    Expr::Ident(TypedIdent {
                                        name: new_id,
                                        typ: Type::hole(),
                                    }),
                                ));
                            },
                        }
                    }

                    if let Some(ref mut base) = *base {
                        self.visit_expr(base);
                    }
                }
                Expr::Infix {
                    ref mut lhs,
                    ref mut op,
                    ref mut rhs,
                    ref mut implicit_args,
                } => {
                    if let Some(new_id) = self.rename(&op.value.name) {
                        debug!(
                            "Rename {} = {}",
                            self.symbols.string(&op.value.name),
                            self.symbols.string(&new_id)
                        );
                        op.value.name = new_id;
                    }
                    self.visit_expr(lhs);
                    self.visit_expr(rhs);
                    for arg in implicit_args {
                        self.visit_expr(arg);
                    }
                }
                Expr::Match(ref mut expr, ref mut alts) => {
                    self.visit_expr(expr);
                    for alt in alts {
                        self.env.stack.enter_scope();
                        self.new_pattern(&mut alt.pattern);
                        self.visit_expr(&mut alt.expr);
                        self.env.stack.exit_scope();
                    }
                }
                Expr::LetBindings(ref mut bindings, ref mut expr) => {
                    self.env.stack.enter_scope();
                    let is_recursive = bindings.iter().all(|bind| !bind.args.is_empty());
                    for bind in bindings.iter_mut() {
                        if !is_recursive {
                            self.visit_expr(&mut bind.expr);
                        }
                        if let Some(ref mut typ) = bind.typ {
                            self.visit_ast_type(typ.as_mut())
                        }
                        self.new_pattern(&mut bind.name);
                    }
                    if is_recursive {
                        for bind in bindings {
                            self.env.stack.enter_scope();
                            for arg in &mut bind.args {
                                arg.name.value.name =
                                    self.stack_var(arg.name.value.name.clone(), expr.span);
                            }
                            self.visit_expr(&mut bind.expr);
                            self.env.stack.exit_scope();
                        }
                    }
                    return TailCall::TailCall;
                }
                Expr::Lambda(ref mut lambda) => {
                    self.env.stack.enter_scope();

                    for arg in &mut lambda.args {
                        arg.name.value.name =
                            self.stack_var(arg.name.value.name.clone(), expr.span);
                    }

                    self.visit_expr(&mut lambda.body);

                    self.env.stack.exit_scope();
                }
                Expr::TypeBindings(ref bindings, _) => {
                    self.env.stack.enter_scope();
                    for bind in bindings {
                        self.stack_type(expr.span, &bind.alias);
                    }

                    return TailCall::TailCall;
                }
                Expr::Do(Do {
                    ref mut id,
                    ref mut bound,
                    ref mut flat_map_id,
                    ..
                }) => {
                    let flat_map = self.symbols.symbol("flat_map");
                    *flat_map_id = Some(Box::new(pos::spanned(
                        id.span,
                        Expr::Ident(TypedIdent {
                            name: flat_map,
                            typ: Type::hole(),
                        }),
                    )));

                    let flat_map_id = flat_map_id
                        .as_mut()
                        .unwrap_or_else(|| ice!("flat_map_id not set before renaming"));

                    self.visit_expr(flat_map_id);
                    self.visit_expr(bound);

                    self.env.stack.enter_scope();

                    id.value.name = self.stack_var(id.value.name.clone(), id.span);

                    return TailCall::TailCall;
                }

                _ => ast::walk_mut_expr(self, expr),
            }
            TailCall::Return
        }
    }

    impl<'a, 'b, 'c> MutVisitor<'c> for RenameVisitor<'a, 'b> {
        type Ident = Symbol;

        fn visit_expr(&mut self, mut expr: &mut SpannedExpr<Self::Ident>) {
            let mut i = 0;
            loop {
                match self.rename_expr(expr) {
                    TailCall::Return => break,
                    TailCall::TailCall => {
                        expr = match { expr }.value {
                            Expr::LetBindings(_, ref mut new_expr)
                            | Expr::TypeBindings(_, ref mut new_expr)
                            | Expr::Do(Do {
                                body: ref mut new_expr,
                                ..
                            }) => new_expr,
                            _ => ice!("Only Let and Type expressions can tailcall"),
                        };
                        i += 1;
                    }
                }
            }

            for _ in 0..i {
                self.env.stack.exit_scope();
            }
        }
    }

    let mut visitor = RenameVisitor {
        symbols: symbols,
        env: Environment {
            stack: ScopedMap::new(),
        },
    };
    visitor.visit_expr(expr);
}
<|endoftext|>


<commit_before>use time::get_time;
use time::Timespec;

use std::sync::{Mutex,MutexGuard};

use ewma::EWMA;
use metric::Metric;

const WINDOW: [f64; 3] = [1f64, 5f64, 15f64];

// A MeterSnapshot
pub struct MeterSnapshot {
    count: i64,
    rates: [f64; 3],
    mean: f64,
}

// A StdMeter struct
pub struct StdMeter {
    data: Mutex<MeterSnapshot>,
    ewma: [EWMA; 3],
    start: Timespec,
}

// A Meter trait
pub trait Meter : Metric {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&mut self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock().unwrap();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock().unwrap();

        s.count += n;

        for i in (0..WINDOW.len()) {
            self.ewma[i].update(n as usize);
        }

        self.update_snapshot(s);
    }

    fn tick(&mut self) {
        let s = self.data.lock().unwrap();

        for i in (0..WINDOW.len()) {
            self.ewma[i].tick();
        }

        self.update_snapshot(s);
    }

    /// Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let s = self.data.lock().unwrap();

        if let Some(pos) = WINDOW.position_elem(&rate) {
            let r: f64 = s.rates[pos];
            return r;
        }
        0f64
    }

    /// Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock().unwrap();

        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock().unwrap();

        s.count
    }
}

impl Metric for StdMeter { }

impl StdMeter {
    fn update_snapshot(&self, mut s: MutexGuard<MeterSnapshot>) {
        for i in (0..WINDOW.len()) {
            s.rates[i] = self.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> StdMeter {
        let data: MeterSnapshot = MeterSnapshot{
            count: 0i64,
            rates: [0f64, 0f64, 0f64],
            mean: 0f64,
        };

        let ewma: [EWMA; 3] = [EWMA::new(1f64), EWMA::new(5f64), EWMA::new(15f64)];

        StdMeter {
            data: Mutex::new(data),
            ewma: ewma,
            start: get_time(),
        }
    }
}

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

    #[test]
    fn zero() {
        let m: StdMeter = StdMeter::new();
        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m: StdMeter = StdMeter::new();
        m.mark(3);

        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m: StdMeter = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let mut m: StdMeter = StdMeter::new();

        m.tick();
    }
}
<commit_msg>position_elem is unstable<commit_after>use time::get_time;
use time::Timespec;

use std::sync::{Mutex,MutexGuard};

use ewma::EWMA;
use metric::Metric;

const WINDOW: [f64; 3] = [1f64, 5f64, 15f64];

// A MeterSnapshot
pub struct MeterSnapshot {
    count: i64,
    rates: [f64; 3],
    mean: f64,
}

// A StdMeter struct
pub struct StdMeter {
    data: Mutex<MeterSnapshot>,
    ewma: [EWMA; 3],
    start: Timespec,
}

// A Meter trait
pub trait Meter : Metric {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&mut self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock().unwrap();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock().unwrap();

        s.count += n;

        for i in (0..WINDOW.len()) {
            self.ewma[i].update(n as usize);
        }

        self.update_snapshot(s);
    }

    fn tick(&mut self) {
        let s = self.data.lock().unwrap();

        for i in (0..WINDOW.len()) {
            self.ewma[i].tick();
        }

        self.update_snapshot(s);
    }

    /// Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let s = self.data.lock().unwrap();

        if let Some(pos) = WINDOW.iter().position(|w| *w == rate) {
            let r: f64 = s.rates[pos];
            return r;
        }
        0f64
    }

    /// Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock().unwrap();

        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock().unwrap();

        s.count
    }
}

impl Metric for StdMeter { }

impl StdMeter {
    fn update_snapshot(&self, mut s: MutexGuard<MeterSnapshot>) {
        for i in (0..WINDOW.len()) {
            s.rates[i] = self.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> StdMeter {
        let data: MeterSnapshot = MeterSnapshot{
            count: 0i64,
            rates: [0f64, 0f64, 0f64],
            mean: 0f64,
        };

        let ewma: [EWMA; 3] = [EWMA::new(1f64), EWMA::new(5f64), EWMA::new(15f64)];

        StdMeter {
            data: Mutex::new(data),
            ewma: ewma,
            start: get_time(),
        }
    }
}

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

    #[test]
    fn zero() {
        let m: StdMeter = StdMeter::new();
        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m: StdMeter = StdMeter::new();
        m.mark(3);

        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m: StdMeter = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let mut m: StdMeter = StdMeter::new();

        m.tick();
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

pub struct Model {
    pub board: Board,
    pub turn: Turn,
    pub white_pieces: u32,
    pub white_hexes: u32,
    pub black_pieces: u32,
    pub black_hexes: u32,
    pub selected_piece: Option<FieldCoord>,
}

impl Model {
    pub fn new() -> Model {
        Model {
            board: Board::new(),
            turn: Turn::White,
            white_pieces: 18,
            white_hexes: 0,
            black_pieces: 18,
            black_hexes: 0,
            selected_piece: None,
        }
    }
}

pub enum Turn {
    White,
    Black,
}

impl Turn {
    pub fn switch_turns(&mut self) {
        *self = match *self {
            Turn::White => Turn::Black,
            Turn::Black => Turn::White,
        }
    }
}

pub struct Board {
    /*
                ____
               /    \
          ____/  +y  \____
         /    \      /    \
        /      \____/  +x  \
        \      /    \      /
         \____/      \____/
         /    \      /    \
        /  -x  \____/      \
        \      /    \      /
         \____/  -y  \____/
              \      /
               \____/

        The hex board uses an axial coordinate system with (0, 0) at the center. The x-axis slopes
        up to the right, and the y-axis goes up and down. The board is stored as a dense 2D array,
        because a ragged array won't work (since each row would have to be a different type).

        See http://www.redblobgames.com/grids/hexagons/#coordinates-axial for more info.
    */
    board: [[Option<Hex>; 5]; 5],
}

// Fields are numbered clockwise from the top. Even indicies are black, odd indicies are white.
type Hex = [Field; 6];

// There's no need to store the color of the piece on this field, since only white pieces can be on
// white fields, and vice versa.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Field {
    Piece,
    Empty,
}

impl Board {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    /// Create a new board with the "Laurentius" starting position.
    pub fn new() -> Board {
        let mut board = Board {
            board: [[None; 5]; 5]
        };

        // (0, 0) is the only empty hex.
        board.set_hex(&HexCoord::new(0, 0), Some([Field::Empty; 6]));

        // All other hexes have exactly two pieces on them in the starting position.
        let piece_locations = [
            (-2,  2, 0, 4),
            (-2,  1, 0, 3),
            (-2,  0, 3, 5),
            (-1,  2, 1, 4),
            (-1,  1, 0, 4),
            (-1,  0, 3, 5),
            (-1, -1, 2, 5),
            ( 0,  2, 1, 5),
            ( 0,  1, 1, 5),
            ( 0, -1, 2, 4),
            ( 0, -2, 2, 4),
            ( 1,  1, 2, 5),
            ( 1,  0, 0, 2),
            ( 1, -1, 1, 3),
            ( 1, -2, 1, 4),
            ( 2,  0, 0, 2),
            ( 2, -1, 0, 3),
            ( 2, -2, 1, 3),
        ];

        for &(x, y, f1, f2) in &piece_locations {
            let mut hex = [Field::Empty; 6];
            hex[f1] = Field::Piece;
            hex[f2] = Field::Piece;
            board.set_hex(&HexCoord::new(x, y), Some(hex));
        }

        board
    }

    pub fn get_field(&self, coord: &FieldCoord) -> &Field {
        match *self.get_hex(&coord.to_hex()) {
            Some(ref hex) => &hex[coord.f as usize],
            None => panic!(
                "Cannot get field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    fn set_field(&mut self, coord: &FieldCoord, field: Field) {
        match *self.get_hex(&coord.to_hex()) {
            Some(mut hex) => {
                hex[coord.f as usize] = field;
                self.set_hex(&coord.to_hex(), Some(hex));
            }
            None => panic!(
                "Cannot set field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    /// Return fields that share an edge with the given field. These fields are always the opposite
    /// color of the given field. If all of a piece's edge neighbors are occupied, that piece might
    /// be capturable.
    pub fn get_field_edge_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![
            // There are always two edge neighbors on the same hex as the given field
            FieldCoord::new(coord.x, coord.y, (coord.f + 1) % 6),
            FieldCoord::new(coord.x, coord.y, (coord.f + 5) % 6),
        ];

        for (i, neighbor) in self.get_hex_neighbors(&coord.to_hex()) {
            if coord.f == i {
                let f = (i + 3) % 6;
                neighbors.push(neighbor.to_field(f));
                break;
            }
        }

        neighbors
    }
    /// Return fields that share a vertex with the given field and have the same color as the given
    /// field. Pieces can move to fields that are vertex neighbors of the field they are on.
    pub fn get_field_vertex_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        // A field's vertex neighbors can be defined as the edge neighbors of its edge neighbors
        let mut neighbors = vec![];
        for neighbor in self.get_field_edge_neighbors(coord) {
            neighbors.append(&mut self.get_field_edge_neighbors(&neighbor));
        }
        // A field is not its own neighbor
        neighbors.into_iter().filter(|n| n != coord).collect()
    }
    pub fn move_piece(&mut self, from: &FieldCoord, to: &FieldCoord) {
        assert_eq!(
            self.get_field(from),
            &Field::Piece,
            "There is no piece at {:?} to move",
            from
        );
        assert!(
            self.get_field_vertex_neighbors(from).contains(to),
            "Cannot move piece at {:?} to non-(vertex neighbor) {:?}",
            from,
            to
        );
        assert_eq!(
            self.get_field(to),
            &Field::Empty,
            "Cannot move piece at {:?} to occupied neighbor {:?}",
            from,
            to
        );

        self.set_field(from, Field::Empty);
        self.set_field(to, Field::Piece);
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        assert_eq!(
            self.get_field(coord),
            &Field::Piece,
            "There is no piece at {:?} to remove",
            coord
        );
        self.set_field(coord, Field::Empty);
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        &self.board[(coord.x + 2) as usize][(coord.y + 2) as usize]
    }
    fn set_hex(&mut self, coord: &HexCoord, hex: Option<Hex>) {
        self.board[(coord.x + 2) as usize][(coord.y + 2) as usize] = hex;
    }
    fn is_hex_extant(&self, coord: &HexCoord) -> bool {
        self.get_hex(coord).is_some()
    }
    // We return a Vec of tuples so that get_hex_field_neighbors and is_hex_removable know which
    // neighbors are on which side of the hex. They need to know this for different reasons:
    //   * get_hex_field_neighbors: the index of each neighboring field depends on which hex
    //                              neighbor that field neighbor is on
    //   * is_hex_removable: a hex is removable only if it is "attached to the board by 3 or less
    //                       adjacent sides"
    fn get_hex_neighbors(&self, coord: &HexCoord) -> Vec<(u32, HexCoord)> {
        let neighbors = [
            (coord.x, coord.y + 1),
            (coord.x + 1, coord.y),
            (coord.x + 1, coord.y - 1),
            (coord.x, coord.y - 1),
            (coord.x - 1, coord.y),
            (coord.x - 1, coord.y + 1),
        ];

        neighbors
            .iter()
            .enumerate()
            .filter(|&(_, &(x, y))| HexCoord::is_valid_coord(x, y))
            .filter_map(|(i, &(x, y))| {
                let coord = HexCoord::new(x, y);
                if self.is_hex_extant(&coord) {
                    Some((i as u32, coord))
                } else {
                    None
                }
            })
            .collect()
    }
    /// Return fields that share an edge with the given hex and are outside of the given hex. If a
    /// hex is removed from the board, pieces occupying that hex's field neighbors might be
    /// capturable.
    pub fn get_hex_field_neighbors(&self, coord: &HexCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![];

        for (i, neighbor) in self.get_hex_neighbors(coord) {
            let f = (i + 3) % 6;
            neighbors.push(neighbor.to_field(f));
        }
        neighbors
    }
    /// A hex is removable (and must be removed) if it is empty and is "attached to the board by 3
    /// or less adjacent sides."
    pub fn is_hex_removable(&self, coord: &HexCoord) -> bool {
        match *self.get_hex(coord) {
            Some(hex) => if hex.iter().any(|&f| f == Field::Piece) {
                return false;
            },
            None => panic!("The hex at {:?} has already been removed", coord),
        }

        let neighbor_idxs: Vec<u32> = self.get_hex_neighbors(coord).iter().map(|&(i, _)| i).collect();
        let neighbor_idxs_slice = neighbor_idxs.as_slice();

        match neighbor_idxs_slice.len() {
            0 => panic!("A hex at {:?} is empty and has no neighbors", coord),
            1 => true,
            2 => {
                let valid_idx_combos = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [0, 5]];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            3 => {
                let valid_idx_combos = [
                    [0, 1, 2],
                    [1, 2, 3],
                    [2, 3, 4],
                    [3, 4, 5],
                    [0, 4, 5],
                    [0, 1, 5],
                ];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            _ => false,
        }
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        assert!(
            self.is_hex_removable(coord),
            "Cannot remove the hex at {:?} which is {:?} and has {} neighbors",
            coord,
            self.get_hex(coord),
            self.get_hex_neighbors(coord).len(),
        );
        self.set_hex(coord, None);
    }
    /// > extant (adj.): Still in existence; not destroyed, lost, or extinct (The Free Dictionary)
    ///
    /// Return the coordinates of the hexes that have not been removed yet.
    pub fn extant_hexes(&self) -> Vec<HexCoord> {
        let mut coords = vec![];

        for x in -2..3 {
            for y in -2..3 {
                if HexCoord::is_valid_coord(x, y) {
                    let coord = HexCoord::new(x, y);
                    if self.is_hex_extant(&coord) {
                        coords.push(coord);
                    }
                }
            }
        }
        coords
    }
}

#[derive(Debug, PartialEq)]
pub struct FieldCoord {
    x: i32,
    y: i32,
    f: u32,
}

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

impl FieldCoord {
    pub fn new(x: i32, y: i32, f: u32) -> FieldCoord {
        assert!(Self::is_valid_coord(x, y, f));
        FieldCoord { x, y, f }
    }
    pub fn x(&self) -> i32 {
        self.x
    }
    pub fn y(&self) -> i32 {
        self.y
    }
    pub fn f(&self) -> u32 {
        self.f
    }
    pub fn to_hex(&self) -> HexCoord {
        HexCoord::new(self.x, self.y)
    }
    pub fn is_valid_coord(x: i32, y: i32, f: u32) -> bool {
        (x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2 && f < 6
    }
}

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!(Self::is_valid_coord(x, y));
        HexCoord { x, y }
    }
    pub fn x(&self) -> i32 {
        self.x
    }
    pub fn y(&self) -> i32 {
        self.y
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    pub fn is_valid_coord(x: i32, y: i32) -> bool {
        (x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2
    }
}
<commit_msg>Comment out unused functions<commit_after>/*
 * Copyright (C) 2017 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

pub struct Model {
    pub board: Board,
    pub turn: Turn,
    pub white_pieces: u32,
    pub white_hexes: u32,
    pub black_pieces: u32,
    pub black_hexes: u32,
    pub selected_piece: Option<FieldCoord>,
}

impl Model {
    pub fn new() -> Model {
        Model {
            board: Board::new(),
            turn: Turn::White,
            white_pieces: 18,
            white_hexes: 0,
            black_pieces: 18,
            black_hexes: 0,
            selected_piece: None,
        }
    }
}

pub enum Turn {
    White,
    Black,
}

/*
impl Turn {
    pub fn switch_turns(&mut self) {
        *self = match *self {
            Turn::White => Turn::Black,
            Turn::Black => Turn::White,
        }
    }
}
*/

pub struct Board {
    /*
                ____
               /    \
          ____/  +y  \____
         /    \      /    \
        /      \____/  +x  \
        \      /    \      /
         \____/      \____/
         /    \      /    \
        /  -x  \____/      \
        \      /    \      /
         \____/  -y  \____/
              \      /
               \____/

        The hex board uses an axial coordinate system with (0, 0) at the center. The x-axis slopes
        up to the right, and the y-axis goes up and down. The board is stored as a dense 2D array,
        because a ragged array won't work (since each row would have to be a different type).

        See http://www.redblobgames.com/grids/hexagons/#coordinates-axial for more info.
    */
    board: [[Option<Hex>; 5]; 5],
}

// Fields are numbered clockwise from the top. Even indicies are black, odd indicies are white.
type Hex = [Field; 6];

// There's no need to store the color of the piece on this field, since only white pieces can be on
// white fields, and vice versa.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Field {
    Piece,
    Empty,
}

impl Board {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    /// Create a new board with the "Laurentius" starting position.
    pub fn new() -> Board {
        let mut board = Board {
            board: [[None; 5]; 5]
        };

        // (0, 0) is the only empty hex.
        board.set_hex(&HexCoord::new(0, 0), Some([Field::Empty; 6]));

        // All other hexes have exactly two pieces on them in the starting position.
        let piece_locations = [
            (-2,  2, 0, 4),
            (-2,  1, 0, 3),
            (-2,  0, 3, 5),
            (-1,  2, 1, 4),
            (-1,  1, 0, 4),
            (-1,  0, 3, 5),
            (-1, -1, 2, 5),
            ( 0,  2, 1, 5),
            ( 0,  1, 1, 5),
            ( 0, -1, 2, 4),
            ( 0, -2, 2, 4),
            ( 1,  1, 2, 5),
            ( 1,  0, 0, 2),
            ( 1, -1, 1, 3),
            ( 1, -2, 1, 4),
            ( 2,  0, 0, 2),
            ( 2, -1, 0, 3),
            ( 2, -2, 1, 3),
        ];

        for &(x, y, f1, f2) in &piece_locations {
            let mut hex = [Field::Empty; 6];
            hex[f1] = Field::Piece;
            hex[f2] = Field::Piece;
            board.set_hex(&HexCoord::new(x, y), Some(hex));
        }

        board
    }

    /*
    fn get_field(&self, coord: &FieldCoord) -> &Field {
        match *self.get_hex(&coord.to_hex()) {
            Some(ref hex) => &hex[coord.f as usize],
            None => panic!(
                "Cannot get field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    fn set_field(&mut self, coord: &FieldCoord, field: Field) {
        match *self.get_hex(&coord.to_hex()) {
            Some(mut hex) => {
                hex[coord.f as usize] = field;
                self.set_hex(&coord.to_hex(), Some(hex));
            }
            None => panic!(
                "Cannot set field {} on removed hex at {:?}",
                coord.f,
                coord.to_hex()
            ),
        }
    }
    /// Return fields that share an edge with the given field. These fields are always the opposite
    /// color of the given field. If all of a piece's edge neighbors are occupied, that piece might
    /// be capturable.
    pub fn get_field_edge_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![
            // There are always two edge neighbors on the same hex as the given field
            FieldCoord::new(coord.x, coord.y, (coord.f + 1) % 6),
            FieldCoord::new(coord.x, coord.y, (coord.f + 5) % 6),
        ];

        for (i, neighbor) in self.get_hex_neighbors(&coord.to_hex()) {
            if coord.f == i {
                let f = (i + 3) % 6;
                neighbors.push(neighbor.to_field(f));
                break;
            }
        }

        neighbors
    }
    /// Return fields that share a vertex with the given field and have the same color as the given
    /// field. Pieces can move to fields that are vertex neighbors of the field they are on.
    pub fn get_field_vertex_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        // A field's vertex neighbors can be defined as the edge neighbors of its edge neighbors
        let mut neighbors = vec![];
        for neighbor in self.get_field_edge_neighbors(coord) {
            neighbors.append(&mut self.get_field_edge_neighbors(&neighbor));
        }
        // A field is not its own neighbor
        neighbors.into_iter().filter(|n| n != coord).collect()
    }
    pub fn move_piece(&mut self, from: &FieldCoord, to: &FieldCoord) {
        assert_eq!(
            self.get_field(from),
            &Field::Piece,
            "There is no piece at {:?} to move",
            from
        );
        assert!(
            self.get_field_vertex_neighbors(from).contains(to),
            "Cannot move piece at {:?} to non-(vertex neighbor) {:?}",
            from,
            to
        );
        assert_eq!(
            self.get_field(to),
            &Field::Empty,
            "Cannot move piece at {:?} to occupied neighbor {:?}",
            from,
            to
        );

        self.set_field(from, Field::Empty);
        self.set_field(to, Field::Piece);
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        assert_eq!(
            self.get_field(coord),
            &Field::Piece,
            "There is no piece at {:?} to remove",
            coord
        );
        self.set_field(coord, Field::Empty);
    }
    */
    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        &self.board[(coord.x + 2) as usize][(coord.y + 2) as usize]
    }
    fn set_hex(&mut self, coord: &HexCoord, hex: Option<Hex>) {
        self.board[(coord.x + 2) as usize][(coord.y + 2) as usize] = hex;
    }
    fn is_hex_extant(&self, coord: &HexCoord) -> bool {
        self.get_hex(coord).is_some()
    }
    /*
    // We return a Vec of tuples so that get_hex_field_neighbors and is_hex_removable know which
    // neighbors are on which side of the hex. They need to know this for different reasons:
    //   * get_hex_field_neighbors: the index of each neighboring field depends on which hex
    //                              neighbor that field neighbor is on
    //   * is_hex_removable: a hex is removable only if it is "attached to the board by 3 or less
    //                       adjacent sides"
    fn get_hex_neighbors(&self, coord: &HexCoord) -> Vec<(u32, HexCoord)> {
        let neighbors = [
            (coord.x, coord.y + 1),
            (coord.x + 1, coord.y),
            (coord.x + 1, coord.y - 1),
            (coord.x, coord.y - 1),
            (coord.x - 1, coord.y),
            (coord.x - 1, coord.y + 1),
        ];

        neighbors
            .iter()
            .enumerate()
            .filter(|&(_, &(x, y))| HexCoord::is_valid_coord(x, y))
            .filter_map(|(i, &(x, y))| {
                let coord = HexCoord::new(x, y);
                if self.is_hex_extant(&coord) {
                    Some((i as u32, coord))
                } else {
                    None
                }
            })
            .collect()
    }
    /// Return fields that share an edge with the given hex and are outside of the given hex. If a
    /// hex is removed from the board, pieces occupying that hex's field neighbors might be
    /// capturable.
    pub fn get_hex_field_neighbors(&self, coord: &HexCoord) -> Vec<FieldCoord> {
        let mut neighbors = vec![];

        for (i, neighbor) in self.get_hex_neighbors(coord) {
            let f = (i + 3) % 6;
            neighbors.push(neighbor.to_field(f));
        }
        neighbors
    }
    /// A hex is removable (and must be removed) if it is empty and is "attached to the board by 3
    /// or less adjacent sides."
    pub fn is_hex_removable(&self, coord: &HexCoord) -> bool {
        match *self.get_hex(coord) {
            Some(hex) => if hex.iter().any(|&f| f == Field::Piece) {
                return false;
            },
            None => panic!("The hex at {:?} has already been removed", coord),
        }

        let neighbor_idxs: Vec<u32> = self.get_hex_neighbors(coord).iter().map(|&(i, _)| i).collect();
        let neighbor_idxs_slice = neighbor_idxs.as_slice();

        match neighbor_idxs_slice.len() {
            0 => panic!("A hex at {:?} is empty and has no neighbors", coord),
            1 => true,
            2 => {
                let valid_idx_combos = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [0, 5]];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            3 => {
                let valid_idx_combos = [
                    [0, 1, 2],
                    [1, 2, 3],
                    [2, 3, 4],
                    [3, 4, 5],
                    [0, 4, 5],
                    [0, 1, 5],
                ];
                valid_idx_combos.iter().any(|c| c == neighbor_idxs_slice)
            }
            _ => false,
        }
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        assert!(
            self.is_hex_removable(coord),
            "Cannot remove the hex at {:?} which is {:?} and has {} neighbors",
            coord,
            self.get_hex(coord),
            self.get_hex_neighbors(coord).len(),
        );
        self.set_hex(coord, None);
    }
    */
    /// > extant (adj.): Still in existence; not destroyed, lost, or extinct (The Free Dictionary)
    ///
    /// Return the coordinates of the hexes that have not been removed yet.
    pub fn extant_hexes(&self) -> Vec<HexCoord> {
        let mut coords = vec![];

        for x in -2..3 {
            for y in -2..3 {
                if HexCoord::is_valid_coord(x, y) {
                    let coord = HexCoord::new(x, y);
                    if self.is_hex_extant(&coord) {
                        coords.push(coord);
                    }
                }
            }
        }
        coords
    }
}

#[derive(Debug, PartialEq)]
pub struct FieldCoord {
    x: i32,
    y: i32,
    f: u32,
}

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

impl FieldCoord {
    pub fn new(x: i32, y: i32, f: u32) -> FieldCoord {
        assert!(Self::is_valid_coord(x, y, f));
        FieldCoord { x, y, f }
    }
    pub fn x(&self) -> i32 {
        self.x
    }
    pub fn y(&self) -> i32 {
        self.y
    }
    pub fn f(&self) -> u32 {
        self.f
    }
    pub fn to_hex(&self) -> HexCoord {
        HexCoord::new(self.x, self.y)
    }
    pub fn is_valid_coord(x: i32, y: i32, f: u32) -> bool {
        (x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2 && f < 6
    }
}

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!(Self::is_valid_coord(x, y));
        HexCoord { x, y }
    }
    pub fn x(&self) -> i32 {
        self.x
    }
    pub fn y(&self) -> i32 {
        self.y
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    pub fn is_valid_coord(x: i32, y: i32) -> bool {
        (x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::path::{Path, Component};
use iron::prelude::*;
use iron::middleware::Handler;
use iron::{status, Url};
use iron::typemap;
use sequence_trie::SequenceTrie;
use std::fmt;

/// Exposes the original, unmodified path to be stored in `Request::extensions`.
#[derive(Copy, Clone)]
pub struct OriginalUrl;
impl typemap::Key for OriginalUrl { type Value = Url; }

/// `Mount` is a simple mounting middleware.
///
/// Mounting allows you to install a handler on a route and have it receive requests as if they
/// are relative to that route. For example, a handler mounted on `/foo/` will receive
/// requests like `/foo/bar` as if they are just `/bar`. Iron's mounting middleware allows
/// you to specify multiple mountings using one middleware instance. Requests that pass through
/// the mounting middleware are passed along to the mounted handler that best matches the request's
/// path. `Request::url` is modified so that requests appear to be relative to the mounted handler's route.
///
/// Mounted handlers may also access the *original* URL by requesting the `OriginalUrl` key
/// from `Request::extensions`.
pub struct Mount {
    inner: SequenceTrie<String, Match>
}

struct Match {
    handler: Box<Handler>,
    length: usize
}

/// The error returned by `Mount` when a request doesn't match any mounted handlers.
#[derive(Debug)]
pub struct NoMatch;

impl Error for NoMatch {
    fn description(&self) -> &'static str { "No Match" }
}

impl fmt::Display for NoMatch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl Mount {
    /// Creates a new instance of `Mount`.
    pub fn new() -> Mount {
        Mount {
            inner: SequenceTrie::new()
        }
    }

    /// Mounts a given `Handler` onto a route.
    ///
    /// This method may be called multiple times with different routes.
    /// For a given request, the *most specific* handler will be selected.
    ///
    /// Existing handlers on the same route will be overwritten.
    pub fn mount<H: Handler>(&mut self, route: &str, handler: H) -> &mut Mount {
        // Parse the route into a list of strings. The unwrap is safe because strs are UTF-8.
        let key: Vec<String> = Path::new(route).components().flat_map(|c|
            match c {
                Component::RootDir => None,
                c => Some(c.as_os_str().to_str().unwrap().to_string())
            }.into_iter()
        ).collect();

        // Insert a match struct into the trie.
        self.inner.insert(key.as_ref(), Match {
            handler: Box::new(handler) as Box<Handler>,
            length: key.len()
        });
        self
    }
}

impl Handler for Mount {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        // Find the matching handler.
        let matched = {
            // Extract the request path.
            let path = req.url.path();

            // If present, remove the trailing empty string (which represents a trailing slash).
            // If it isn't removed the path will never match anything, because
            // Path::str_components ignores trailing slashes and will never create routes
            // ending in "".
            let key = match path.last() {
                Some(s) if s.is_empty() => &path[..path.len() - 1],
                _ => &path
            };

            let key: Vec<_> = key.into_iter().map(|s| String::from(*s)).collect();

            // Search the Trie for the nearest most specific match.
            match self.inner.get_ancestor(&key) {
                Some(matched) => matched,
                None => return Err(IronError::new(NoMatch, status::NotFound))
            }
        };

        // We have a match, so fire off the child.
        // If another mount middleware hasn't already, insert the unmodified url
        // into the extensions as the "original url".
        let is_outer_mount = !req.extensions.contains::<OriginalUrl>();
        if is_outer_mount {
            req.extensions.insert::<OriginalUrl>(req.url.clone());
        }

        // Remove the prefix from the request's path before passing it to the mounted handler.
        // If the prefix is entirely removed and no trailing slash was present, the new path
        // will be the empty list. For the purposes of redirection, conveying that the path
        // did not include a trailing slash is more important than providing a non-empty list.
        req.url.path().clone_from(&req.url.path()[matched.length..].to_vec());
        let res = matched.handler.handle(req);

        // Reverse the URL munging, for future middleware.
        req.url = match req.extensions.get::<OriginalUrl>() {
            Some(original) => original.clone(),
            None => panic!("OriginalUrl unexpectedly removed from req.extensions.")
        };

        // If this mount middleware is the outermost mount middleware,
        // remove the original url from the extensions map to prevent leakage.
        if is_outer_mount {
            req.extensions.remove::<OriginalUrl>();
        }

        res
    }
}

<commit_msg>(fix) rebuild requests iron::Url via from_generic_url as we can't set iron::Urls path directly [Fixes #85]<commit_after>use std::error::Error;
use std::path::{Path, Component};
use iron::prelude::*;
use iron::middleware::Handler;
use iron::{status, Url};
use iron::typemap;
use sequence_trie::SequenceTrie;
use std::fmt;

/// Exposes the original, unmodified path to be stored in `Request::extensions`.
#[derive(Copy, Clone)]
pub struct OriginalUrl;
impl typemap::Key for OriginalUrl { type Value = Url; }

/// `Mount` is a simple mounting middleware.
///
/// Mounting allows you to install a handler on a route and have it receive requests as if they
/// are relative to that route. For example, a handler mounted on `/foo/` will receive
/// requests like `/foo/bar` as if they are just `/bar`. Iron's mounting middleware allows
/// you to specify multiple mountings using one middleware instance. Requests that pass through
/// the mounting middleware are passed along to the mounted handler that best matches the request's
/// path. `Request::url` is modified so that requests appear to be relative to the mounted handler's route.
///
/// Mounted handlers may also access the *original* URL by requesting the `OriginalUrl` key
/// from `Request::extensions`.
pub struct Mount {
    inner: SequenceTrie<String, Match>
}

struct Match {
    handler: Box<Handler>,
    length: usize
}

/// The error returned by `Mount` when a request doesn't match any mounted handlers.
#[derive(Debug)]
pub struct NoMatch;

impl Error for NoMatch {
    fn description(&self) -> &'static str { "No Match" }
}

impl fmt::Display for NoMatch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl Mount {
    /// Creates a new instance of `Mount`.
    pub fn new() -> Mount {
        Mount {
            inner: SequenceTrie::new()
        }
    }

    /// Mounts a given `Handler` onto a route.
    ///
    /// This method may be called multiple times with different routes.
    /// For a given request, the *most specific* handler will be selected.
    ///
    /// Existing handlers on the same route will be overwritten.
    pub fn mount<H: Handler>(&mut self, route: &str, handler: H) -> &mut Mount {
        // Parse the route into a list of strings. The unwrap is safe because strs are UTF-8.
        let key: Vec<String> = Path::new(route).components().flat_map(|c|
            match c {
                Component::RootDir => None,
                c => Some(c.as_os_str().to_str().unwrap().to_string())
            }.into_iter()
        ).collect();

        // Insert a match struct into the trie.
        self.inner.insert(key.as_ref(), Match {
            handler: Box::new(handler) as Box<Handler>,
            length: key.len()
        });
        self
    }
}

impl Handler for Mount {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        // Find the matching handler.
        let matched = {
            // Extract the request path.
            let path = req.url.path();

            // If present, remove the trailing empty string (which represents a trailing slash).
            // If it isn't removed the path will never match anything, because
            // Path::str_components ignores trailing slashes and will never create routes
            // ending in "".
            let key = match path.last() {
                Some(s) if s.is_empty() => &path[..path.len() - 1],
                _ => &path
            };

            let key: Vec<_> = key.into_iter().map(|s| String::from(*s)).collect();

            // Search the Trie for the nearest most specific match.
            match self.inner.get_ancestor(&key) {
                Some(matched) => matched,
                None => return Err(IronError::new(NoMatch, status::NotFound))
            }
        };

        // We have a match, so fire off the child.
        // If another mount middleware hasn't already, insert the unmodified url
        // into the extensions as the "original url".
        let is_outer_mount = !req.extensions.contains::<OriginalUrl>();
        if is_outer_mount {
            req.extensions.insert::<OriginalUrl>(req.url.clone());
        }

        // Remove the prefix from the request's path before passing it to the mounted handler.
        // If the prefix is entirely removed and no trailing slash was present, the new path
        // will be the empty list. For the purposes of redirection, conveying that the path
        // did not include a trailing slash is more important than providing a non-empty list.
        let path = req.url.path()[matched.length..].join("/");
        let mut nu = req.url.clone().into_generic_url();
        nu.set_path(&path);
        req.url = Url::from_generic_url(nu).unwrap();

        let res = matched.handler.handle(req);

        // Reverse the URL munging, for future middleware.
        req.url = match req.extensions.get::<OriginalUrl>() {
            Some(original) => original.clone(),
            None => panic!("OriginalUrl unexpectedly removed from req.extensions.")
        };

        // If this mount middleware is the outermost mount middleware,
        // remove the original url from the extensions map to prevent leakage.
        if is_outer_mount {
            req.extensions.remove::<OriginalUrl>();
        }

        res
    }
}

<|endoftext|>


<commit_before>// This file is part of rust-web/twig
//
// For the copyright and license information, please view the LICENSE
// file that was distributed with this source code.

/// Data state of the lexer.

use super::{TokenizeState, Code};
use lexer::job::state;
use lexer::job::Job;
use lexer::token::Token;
use lexer::patterns::{token_start, verbatim_start, Extract};
use lexer::error::{LexerError, SyntaxError, SyntaxErrorCode};
use error::api::Dump;

pub struct Data;

#[allow(unused_variables)]
impl TokenizeState for Data {
    fn state() -> Code {
        Code::Data
    }

    fn tokenize<'a>(job: &'a mut Job) -> Result<(),LexerError> {
        let capture = match Self::next_token_start_after_cursor(job) {
            Some(capture) => capture,
            None => {
                let slice = job.cursor.slice_to_end();
                job.push_token(Token::Text(slice.to_string()));

                return state::Final::tokenize(job)
            },
        };

        let mut slice = job.cursor.slice_to(capture.position.0);

        if capture.whitespace_trim {
            slice = slice.trim_right();
        }

        job.cursor.move_to(capture.position.1);
        job.push_token(Token::Text(slice.to_string()));

        match capture.tag {
            token_start::Tag::Comment => {
                try_chain!(Self::lex_comment(job));

                return Self::tokenize(job);
            },
            token_start::Tag::Block => {
                // #TODO:300 nested matches don't look nice - alternative??
                // raw data?
                match job.patterns.verbatim_start.extract(job.cursor.tail()) {
                    Some(verbatim_start) => {
                        job.cursor.move_by(verbatim_start.position.1);
                        try_chain!(Self::lex_verbatim_data(job, verbatim_start.tag));

                        return Self::tokenize(job);
                    },
                    _ => {
                        // {% line \d+ %}
                        match job.patterns.block_line.extract(job.cursor.tail()) {
                            Some(block_line) => {
                                let block_line = try!(block_line);

                                job.cursor.move_by(block_line.position.1);
                                job.cursor.set_line(block_line.line);

                                return Self::tokenize(job);
                            },
                            _ => {
                                job.current_exp_block_line = job.cursor.line();
                                job.push_token(Token::BlockStart);
                                try!(state::Block::tokenize(job));

                                return Self::tokenize(job);
                            },
                        }
                    },
                }
            },
            token_start::Tag::Expression => {
                job.current_exp_block_line = job.cursor.line();
                job.push_token(Token::ExpressionStart);
                try!(state::Expression::tokenize(job));

                return Self::tokenize(job);
            }
        }
    }
}

impl<'a> Data {
    fn lex_comment(job: &'a mut Job) -> Result<(), SyntaxError> {
        match job.patterns.comment_end.find(job.cursor.tail()) {
            None => return err!(SyntaxErrorCode::UnclosedComment {
                cursor: job.cursor.dump()
            }),
            Some(position) => job.cursor.move_by(position.1),
        }
        Ok(())
    }

    fn lex_verbatim_data(job: &'a mut Job, tag: verbatim_start::Tag) -> Result<(), SyntaxError> {
        let capture = match job.patterns.verbatim_end.extract_iter(job.cursor.tail())
                                                 .find(|capture| capture.tag == tag) {
            Some(capture) => capture,
            _ => return err!(SyntaxErrorCode::UnexpectedEof {
                    reason: "Unclosed (raw|verbatim) block",
                    cursor: job.cursor().dump()
                }),
        };

        let mut slice = job.cursor.slice_by(capture.position.0);
        job.cursor.move_by(capture.position.1 - capture.position.0);

        if capture.whitespace_trim {
            slice = slice.trim_right();
        }

        job.push_token(Token::Text(slice.to_string()));
        Ok(())
    }

    /// Find the first token after the current cursor
    fn next_token_start_after_cursor(job: &'a mut Job) -> Option<token_start::ItemData> {
        let position = job.cursor.position();

        job.token_start_iter.find(|x| {
            x.position.0 >= position
        })
    }
}

#[cfg(test)]
mod test {
    use lexer::test::tokenize_err;
    use lexer::test::assert_tokenize;
    use lexer::token::Token;
    use std::error::Error;
    use lexer::SyntaxErrorCode;

    #[test]
    pub fn no_more_tokens() {
        assert_tokenize(
            "only data no tokens",
            vec![
                Token::Text("only data no tokens".to_string())
            ]
        )
    }

    #[test]
    pub fn comment() {
        assert_tokenize(
            " Hello \n {#- World -#} !",
            vec![
                Token::Text(" Hello".to_string()),
                Token::Text("!".to_string()),
            ]);
    }

    #[test]
    pub fn unclosed_comment() {
        let cursor_dump = "`test-example` line 1 column 19".to_string();
        let expect = SyntaxErrorCode::UnclosedComment {
            cursor: cursor_dump
        }.to_string();

        assert_eq!(
            &tokenize_err(" lost in space {#-").cause().unwrap().to_string()[0..expect.len()],
            expect
        );
    }

    #[test]
    pub fn block_verbatim() {
        assert_tokenize(
            "{% verbatim %}
{% for x in list %}
{{ x }}
{% endfor %}
{% endverbatim %}",
            vec![
                Token::Text("".to_string()),
                Token::Text("
{% for x in list %}
{{ x }}
{% endfor %}
".to_string()),
                Token::Text("".to_string()),
            ]);
    }

    #[test]
    pub fn block_line() {
        let cursor_dump = "`test-example` line 100 column 9".to_string();
        let expect = SyntaxErrorCode::UnclosedBlock {
            cursor: cursor_dump
        }.to_string();

        assert_eq!(
            &tokenize_err("line1 {% line 99 %}\nline 2{%").cause().unwrap().to_string()[0..expect.len()],
            expect
        );
    }

    #[test]
    pub fn block() {
        assert_tokenize(
            " To \n be   {%- something -%}  ",
            vec![
                Token::Text(" To \n be".to_string()),
                Token::BlockStart,
                Token::Name("something".to_string()),
                Token::BlockEnd,
                Token::Text("".to_string()),
            ]);
    }

    #[test]
    pub fn unclosed_block() {
        let cursor_dump = "`test-example` line 2 column 10".to_string();
        let expect = SyntaxErrorCode::UnclosedBlock {
            cursor: cursor_dump
        }.to_string();

        assert_eq!(
            &tokenize_err(" To \n be   {%-").cause().unwrap().to_string()[0..expect.len()],
            expect
        );
    }

    #[test]
    pub fn var() {
        assert_tokenize(
            " foo bar  {{ x }} baz",
            vec![
                Token::Text(" foo bar  ".to_string()),
                Token::ExpressionStart,
                Token::Name("x".to_string()),
                Token::ExpressionEnd,
                Token::Text(" baz".to_string()),
            ]);
    }

    #[test]
    pub fn unclosed_var() {
        let cursor_dump = "`test-example` line 2 column 13".to_string();
        let expect = SyntaxErrorCode::UnclosedVariable {
            cursor: cursor_dump
        }.to_string();

        assert_eq!(
            &tokenize_err(" or not \n to be !  {{").cause().unwrap().to_string()[0..expect.len()],
            expect
        );
    }
}
<commit_msg>cleanup<commit_after>// This file is part of rust-web/twig
//
// For the copyright and license information, please view the LICENSE
// file that was distributed with this source code.

/// Data state of the lexer.

use super::{TokenizeState, Code};
use lexer::job::state;
use lexer::job::Job;
use lexer::token::Token;
use lexer::patterns::{token_start, verbatim_start, Extract};
use lexer::error::{LexerError, SyntaxError, SyntaxErrorCode};
use error::api::Dump;

pub struct Data;

#[allow(unused_variables)]
impl TokenizeState for Data {
    fn state() -> Code {
        Code::Data
    }

    fn tokenize<'a>(job: &'a mut Job) -> Result<(),LexerError> {
        let capture = match Self::next_token_start_after_cursor(job) {
            Some(capture) => capture,
            None => {
                let slice = job.cursor.slice_to_end();
                job.push_token(Token::Text(slice.to_string()));

                return state::Final::tokenize(job)
            },
        };

        let mut slice = job.cursor.slice_to(capture.position.0);

        if capture.whitespace_trim {
            slice = slice.trim_right();
        }

        job.cursor.move_to(capture.position.1);
        job.push_token(Token::Text(slice.to_string()));

        match capture.tag {
            token_start::Tag::Comment => {
                try_chain!(Self::lex_comment(job));

                return Self::tokenize(job);
            },
            token_start::Tag::Block => {
                // #TODO:300 nested matches don't look nice - alternative??
                // raw data?
                match job.patterns.verbatim_start.extract(job.cursor.tail()) {
                    Some(verbatim_start) => {
                        job.cursor.move_by(verbatim_start.position.1);
                        try_chain!(Self::lex_verbatim_data(job, verbatim_start.tag));

                        return Self::tokenize(job);
                    },
                    _ => {
                        // {% line \d+ %}
                        match job.patterns.block_line.extract(job.cursor.tail()) {
                            Some(block_line) => {
                                let block_line = try!(block_line);

                                job.cursor.move_by(block_line.position.1);
                                job.cursor.set_line(block_line.line);

                                return Self::tokenize(job);
                            },
                            _ => {
                                job.current_exp_block_line = job.cursor.line();
                                job.push_token(Token::BlockStart);
                                try!(state::Block::tokenize(job));

                                return Self::tokenize(job);
                            },
                        }
                    },
                }
            },
            token_start::Tag::Expression => {
                job.current_exp_block_line = job.cursor.line();
                job.push_token(Token::ExpressionStart);
                try!(state::Expression::tokenize(job));

                return Self::tokenize(job);
            }
        }
    }
}

impl<'a> Data {
    fn lex_comment(job: &'a mut Job) -> Result<(), SyntaxError> {
        match job.patterns.comment_end.find(job.cursor.tail()) {
            None => return err!(SyntaxErrorCode::UnclosedComment {
                cursor: job.cursor.dump()
            }),
            Some(position) => job.cursor.move_by(position.1),
        }
        Ok(())
    }

    fn lex_verbatim_data(job: &'a mut Job, tag: verbatim_start::Tag) -> Result<(), SyntaxError> {
        let capture = match job.patterns.verbatim_end.extract_iter(job.cursor.tail())
                                                 .find(|capture| capture.tag == tag) {
            Some(capture) => capture,
            _ => return err!(SyntaxErrorCode::UnexpectedEof {
                    reason: "Unclosed (raw|verbatim) block",
                    cursor: job.cursor().dump()
                }),
        };

        let mut slice = job.cursor.slice_by(capture.position.0);
        job.cursor.move_by(capture.position.1 - capture.position.0);

        if capture.whitespace_trim {
            slice = slice.trim_right();
        }

        job.push_token(Token::Text(slice.to_string()));
        Ok(())
    }

    /// Find the first token after the current cursor
    fn next_token_start_after_cursor(job: &'a mut Job) -> Option<token_start::ItemData> {
        let position = job.cursor.position();

        job.token_start_iter.find(|x| {
            x.position.0 >= position
        })
    }
}

#[cfg(test)]
mod test {
    use lexer::test::tokenize_err;
    use lexer::test::assert_tokenize;
    use lexer::token::Token;
    use std::error::Error;
    use lexer::SyntaxErrorCode;

    #[test]
    pub fn no_more_tokens() {
        assert_tokenize(
            "only data no tokens",
            vec![
                Token::Text("only data no tokens".to_string())
            ]
        )
    }

    #[test]
    pub fn comment() {
        assert_tokenize(
            " Hello \n {#- World -#} !",
            vec![
                Token::Text(" Hello".to_string()),
                Token::Text("!".to_string()),
            ]);
    }

    #[test]
    pub fn unclosed_comment() {
        let cursor_dump = "`test-example` line 1 column 19".to_string();
        let expect = SyntaxErrorCode::UnclosedComment {
            cursor: cursor_dump
        }.to_string();

        let err = tokenize_err(" lost in space {#-").cause().unwrap().to_string();
        assert!(err.starts_with(&expect), "error {} should start with {}", err, expect);
    }

    #[test]
    pub fn block_verbatim() {
        assert_tokenize(
            "{% verbatim %}
{% for x in list %}
{{ x }}
{% endfor %}
{% endverbatim %}",
            vec![
                Token::Text("".to_string()),
                Token::Text("
{% for x in list %}
{{ x }}
{% endfor %}
".to_string()),
                Token::Text("".to_string()),
            ]);
    }

    #[test]
    pub fn block_line() {
        let cursor_dump = "`test-example` line 100 column 9".to_string();
        let expect = SyntaxErrorCode::UnclosedBlock {
            cursor: cursor_dump
        }.to_string();

        let err = tokenize_err("line1 {% line 99 %}\nline 2{%").cause().unwrap().to_string();
        assert!(err.starts_with(&expect), "error {} should start with {}", err, expect);
    }

    #[test]
    pub fn block() {
        assert_tokenize(
            " To \n be   {%- something -%}  ",
            vec![
                Token::Text(" To \n be".to_string()),
                Token::BlockStart,
                Token::Name("something".to_string()),
                Token::BlockEnd,
                Token::Text("".to_string()),
            ]);
    }

    #[test]
    pub fn unclosed_block() {
        let cursor_dump = "`test-example` line 2 column 10".to_string();
        let expect = SyntaxErrorCode::UnclosedBlock {
            cursor: cursor_dump
        }.to_string();

        let err = tokenize_err(" To \n be   {%-").cause().unwrap().to_string();
        assert!(err.starts_with(&expect), "error {} should start with {}", err, expect);
    }

    #[test]
    pub fn var() {
        assert_tokenize(
            " foo bar  {{ x }} baz",
            vec![
                Token::Text(" foo bar  ".to_string()),
                Token::ExpressionStart,
                Token::Name("x".to_string()),
                Token::ExpressionEnd,
                Token::Text(" baz".to_string()),
            ]);
    }

    #[test]
    pub fn unclosed_var() {
        let cursor_dump = "`test-example` line 2 column 13".to_string();
        let expect = SyntaxErrorCode::UnclosedVariable {
            cursor: cursor_dump
        }.to_string();

        let err = tokenize_err(" or not \n to be !  {{").cause().unwrap().to_string();
        assert!(err.starts_with(&expect), "error {} should start with {}", err, expect);
    }
}
<|endoftext|>


<commit_before>extern crate toml;
#[macro_use]
extern crate serde_derive;

use toml::Value;

macro_rules! float_inf_tests {
    ($ty:ty) => {{
        #[derive(Serialize, Deserialize)]
        struct S {
            sf1: $ty,
            sf2: $ty,
            sf3: $ty,
            sf4: $ty,
            sf5: $ty,
            sf6: $ty,
            sf7: $ty,
            sf8: $ty,
        }
        let inf: S = toml::from_str(
            r"
        # infinity
        sf1 = inf  # positive infinity
        sf2 = +inf # positive infinity
        sf3 = -inf # negative infinity

        # not a number
        sf4 = nan  # actual sNaN/qNaN encoding is implementation specific
        sf5 = +nan # same as `nan`
        sf6 = -nan # valid, actual encoding is implementation specific

        # zero
        sf7 = +0.0
        sf8 = -0.0
        ",
        )
        .expect("Parse infinities.");

        assert!(inf.sf1.is_infinite());
        assert!(inf.sf1.is_sign_positive());
        assert!(inf.sf2.is_infinite());
        assert!(inf.sf2.is_sign_positive());
        assert!(inf.sf3.is_infinite());
        assert!(inf.sf3.is_sign_negative());

        assert!(inf.sf4.is_nan());
        assert!(inf.sf4.is_sign_positive());
        assert!(inf.sf5.is_nan());
        assert!(inf.sf5.is_sign_positive());
        assert!(inf.sf6.is_nan());
        assert!(inf.sf6.is_sign_negative());

        assert_eq!(inf.sf7, 0.0);
        assert!(inf.sf7.is_sign_positive());
        assert_eq!(inf.sf8, 0.0);
        assert!(inf.sf8.is_sign_negative());

        let s = toml::to_string(&inf).unwrap();
        assert_eq!(
            s,
            "\
                        sf1 = inf
sf2 = inf
sf3 = -inf
sf4 = nan
sf5 = nan
sf6 = -nan
sf7 = 0.0
sf8 = -0.0
"
        );

        toml::from_str::<Value>(&s).expect("roundtrip");
    }};
}

#[test]
fn float_inf() {
    float_inf_tests!(f32);
    float_inf_tests!(f64);
}
<commit_msg>Work around a rustfmt bug<commit_after>extern crate toml;
#[macro_use]
extern crate serde_derive;

use toml::Value;

#[rustfmt::skip] // appears to be a bug in rustfmt to make this converge...
macro_rules! float_inf_tests {
    ($ty:ty) => {{
        #[derive(Serialize, Deserialize)]
        struct S {
            sf1: $ty,
            sf2: $ty,
            sf3: $ty,
            sf4: $ty,
            sf5: $ty,
            sf6: $ty,
            sf7: $ty,
            sf8: $ty,
        }
        let inf: S = toml::from_str(
            r"
        # infinity
        sf1 = inf  # positive infinity
        sf2 = +inf # positive infinity
        sf3 = -inf # negative infinity

        # not a number
        sf4 = nan  # actual sNaN/qNaN encoding is implementation specific
        sf5 = +nan # same as `nan`
        sf6 = -nan # valid, actual encoding is implementation specific

        # zero
        sf7 = +0.0
        sf8 = -0.0
        ",
        )
        .expect("Parse infinities.");

        assert!(inf.sf1.is_infinite());
        assert!(inf.sf1.is_sign_positive());
        assert!(inf.sf2.is_infinite());
        assert!(inf.sf2.is_sign_positive());
        assert!(inf.sf3.is_infinite());
        assert!(inf.sf3.is_sign_negative());

        assert!(inf.sf4.is_nan());
        assert!(inf.sf4.is_sign_positive());
        assert!(inf.sf5.is_nan());
        assert!(inf.sf5.is_sign_positive());
        assert!(inf.sf6.is_nan());
        assert!(inf.sf6.is_sign_negative());

        assert_eq!(inf.sf7, 0.0);
        assert!(inf.sf7.is_sign_positive());
        assert_eq!(inf.sf8, 0.0);
        assert!(inf.sf8.is_sign_negative());

        let s = toml::to_string(&inf).unwrap();
        assert_eq!(
            s,
            "\
sf1 = inf
sf2 = inf
sf3 = -inf
sf4 = nan
sf5 = nan
sf6 = -nan
sf7 = 0.0
sf8 = -0.0
"
        );

        toml::from_str::<Value>(&s).expect("roundtrip");
    }};
}

#[test]
fn float_inf() {
    float_inf_tests!(f32);
    float_inf_tests!(f64);
}
<|endoftext|>