<commit_before>//! This module has the base structures for the game elements.
//!
//! The map is made of tiles, where each tile references an entry in the tile
//! type array. Tiles are ordered row first (Y goes from bottom to top) then
//! column (X goes from left to right).
//!
//! Apart from the static grid of tiles, entities represent everything else:
//! characters, items, bullets. They can occupy any decimal position, and move.
//!
//! Some tiles are active in some way, meaning that they have logic attached to
//! them. These are represented by tile entities, which means the tile types has
//! `has_entity` set to `true`, and an entity exists for each tile of that type.

use std::collections::HashMap;
use std::path::Path;

use vecmath::*;

/// This represents the logic for a type of entity.
pub trait EntityLogic {
    fn update(&mut self, &mut Entity) -> bool;
}

/// This is an entity in the world, with a position and pointer to the logic.
pub struct Entity {
    pub pos: Vector2,
    logic: Box<EntityLogic>,
}

type TileEntityFactory = &'static Fn(Tile, &TileType, (usize, usize)) -> Option<Entity>;

/// Definition of a tile type, referenced by tiles.
#[derive(Clone)]
struct TileType {
    /// Color to use to draw that tile.
    // TODO replace with texture
    color: [f32; 4],
    /// Damage suffered from touching that tile.
    damage: f32,
    /// Whether entities will collide with that tile, or pass through.
    collide: bool,
    /// Factory function (creates entity).
    tile_entity: Option<Box<TileEntityFactory>>,
}

/// A tile in the map, just references a TileType.
pub type Tile = u16;

/// The map, representing the status of the world at a given instant.
pub struct Map {
    /// Width in number of tiles.
    width: usize,
    /// Height in number of tiles.
    height: usize,
    /// The tile types, referenced by the tile array.
    tiletypes: Vec<TileType>,
    /// The tiles, ordered Y first (bottom to top) then X (left to right).
    tiles: Vec<Tile>,
    /// The entities.
    entities: Vec<Box<Entity>>,
    /// The entities associated with tiles.
    tile_entities: HashMap<(usize, usize), Entity>,
}

struct EntityDefinition {
    type_id: String,
    position: Vector2,
}

impl EntityDefinition {
    fn create(&self, seed: u32) -> Box<Entity> {
        unimplemented!()
    }
}

/// Initial map definition, loaded from disk.
///
/// This can be turned into a live Map using `create()`.
pub struct MapFactory {
    width: usize,
    height: usize,
    tiletypes: Vec<TileType>,
    tiles: Vec<Tile>,
    entities: Vec<EntityDefinition>,
}

impl MapFactory {
    /// Load a map file.
    pub fn from_file(filename: &Path) -> MapFactory {
        unimplemented!()
    }

    /// Create the hardcoded example map.
    fn example() -> MapFactory {
        // Initialize with background color
        let mut tiles = vec![1; 100 * 100];
        // Different background for top part
        for y in 70..100 {
            for x in 0..100 {
                tiles[y * 100 + x] = 2;
            }
        }
        // Walls all around
        for i in 0..100 {
            tiles[ 0 * 100 + i] = 0;
            tiles[99 * 100 + i] = 0;
            tiles[i * 100 +  0] = 0;
            tiles[i * 100 + 99] = 0;
        }
        // Lava at the bottom
        for x in 40..60 {
            tiles[0 * 100 + x] = 3;
        }
        MapFactory {
            width: 100,
            height: 100,
            tiletypes: vec![
                TileType {
                    color: [0.5, 0.5, 0.5, 1.0],
                    damage: 0.0,
                    collide: true,
                    tile_entity: None,
                },
                TileType {
                    color: [0.0, 0.0, 0.0, 1.0],
                    damage: 0.0,
                    collide: false,
                    tile_entity: None,
                },
                TileType {
                    color: [0.0, 0.0, 1.0, 1.0],
                    damage: 0.0,
                    collide: false,
                    tile_entity: None,
                },
                TileType {
                    color: [1.0, 0.0, 0.0, 1.0],
                    damage: 1.0,
                    collide: false,
                    tile_entity: None,
                },
            ],
            tiles: tiles,
            entities: Vec::new(),
        }
    }

    /// Create a live `Map` from this map definition.
    fn create(&self, seed: u32) -> Map {
        let mut tile_entities = HashMap::new();

        let tiles = self.tiles.clone();
        for y in 0..self.height {
            for x in 0..self.width {
                let tile = tiles[y * self.width + x];
                let tiletype = &self.tiletypes[tile as usize];
                if let Some(ref factory) = tiletype.tile_entity {
                    if let Some(entity) = factory(tile, tiletype, (x, y)) {
                        tile_entities.insert((x, y), entity);
                    }
                }
            }
        }

        Map {
            width: self.width,
            height: self.height,
            tiletypes: self.tiletypes.clone(),
            tiles: tiles,
            entities: self.entities.iter().map(|e| e.create(seed)).collect(),
            tile_entities: tile_entities,
        }
    }
}
<commit_msg>Add spawns<commit_after>//! This module has the base structures for the game elements.
//!
//! The map is made of tiles, where each tile references an entry in the tile
//! type array. Tiles are ordered row first (Y goes from bottom to top) then
//! column (X goes from left to right).
//!
//! Apart from the static grid of tiles, entities represent everything else:
//! characters, items, bullets. They can occupy any decimal position, and move.
//!
//! Some tiles are active in some way, meaning that they have logic attached to
//! them. These are represented by tile entities, which means the tile types has
//! `has_entity` set to `true`, and an entity exists for each tile of that type.

use std::collections::HashMap;
use std::path::Path;

use vecmath::*;

/// This represents the logic for a type of entity.
pub trait EntityLogic {
    fn update(&mut self, &mut Entity) -> bool;
}

/// This is an entity in the world, with a position and pointer to the logic.
pub struct Entity {
    pub pos: Vector2,
    logic: Box<EntityLogic>,
}

type TileEntityFactory = &'static Fn(Tile, &TileType, (usize, usize)) -> Option<Entity>;

/// Definition of a tile type, referenced by tiles.
#[derive(Clone)]
struct TileType {
    /// Color to use to draw that tile.
    // TODO replace with texture
    color: [f32; 4],
    /// Damage suffered from touching that tile.
    damage: f32,
    /// Whether entities will collide with that tile, or pass through.
    collide: bool,
    /// Factory function (creates entity).
    tile_entity: Option<Box<TileEntityFactory>>,
}

/// A tile in the map, just references a TileType.
pub type Tile = u16;

/// The map, representing the status of the world at a given instant.
pub struct Map {
    /// Width in number of tiles.
    width: usize,
    /// Height in number of tiles.
    height: usize,
    /// The tile types, referenced by the tile array.
    tiletypes: Vec<TileType>,
    /// The tiles, ordered Y first (bottom to top) then X (left to right).
    tiles: Vec<Tile>,
    /// The entities.
    entities: Vec<Box<Entity>>,
    /// The entities associated with tiles.
    tile_entities: HashMap<(usize, usize), Entity>,
}

struct EntityDefinition {
    type_id: String,
    position: Vector2,
}

impl EntityDefinition {
    fn create(&self, seed: u32) -> Box<Entity> {
        unimplemented!()
    }
}

/// Initial map definition, loaded from disk.
///
/// This can be turned into a live Map using `create()`.
pub struct MapFactory {
    width: usize,
    height: usize,
    nb_players: usize,
    tiletypes: Vec<TileType>,
    tiles: Vec<Tile>,
    entities: Vec<EntityDefinition>,
}

impl MapFactory {
    /// Load a map file.
    pub fn from_file(filename: &Path) -> MapFactory {
        unimplemented!()
    }

    /// Create the hardcoded example map.
    fn example() -> MapFactory {
        // Initialize with background color
        let mut tiles = vec![1; 100 * 100];
        // Different background for top part
        for y in 70..100 {
            for x in 0..100 {
                tiles[y * 100 + x] = 2;
            }
        }
        // Walls all around
        for i in 0..100 {
            tiles[ 0 * 100 + i] = 0;
            tiles[99 * 100 + i] = 0;
            tiles[i * 100 +  0] = 0;
            tiles[i * 100 + 99] = 0;
        }
        // Lava at the bottom
        for x in 40..60 {
            tiles[0 * 100 + x] = 3;
        }
        MapFactory {
            width: 100,
            height: 100,
            nb_players: 4,
            tiletypes: vec![
                TileType {
                    color: [0.5, 0.5, 0.5, 1.0],
                    damage: 0.0,
                    collide: true,
                    tile_entity: None,
                },
                TileType {
                    color: [0.0, 0.0, 0.0, 1.0],
                    damage: 0.0,
                    collide: false,
                    tile_entity: None,
                },
                TileType {
                    color: [0.0, 0.0, 1.0, 1.0],
                    damage: 0.0,
                    collide: false,
                    tile_entity: None,
                },
                TileType {
                    color: [1.0, 0.0, 0.0, 1.0],
                    damage: 1.0,
                    collide: false,
                    tile_entity: None,
                },
            ],
            tiles: tiles,
            entities: vec![
                EntityDefinition {
                    type_id: "f.spawn".to_string(),
                    position: [15.0, 1.0],
                },
                EntityDefinition {
                    type_id: "f.spawn".to_string(),
                    position: [25.0, 1.0],
                },
                EntityDefinition {
                    type_id: "f.spawn".to_string(),
                    position: [75.0, 1.0],
                },
                EntityDefinition {
                    type_id: "f.spawn".to_string(),
                    position: [85.0, 1.0],
                },
            ],
        }
    }

    /// Create a live `Map` from this map definition.
    fn create(&self, seed: u32) -> Map {
        let mut tile_entities = HashMap::new();

        let tiles = self.tiles.clone();
        for y in 0..self.height {
            for x in 0..self.width {
                let tile = tiles[y * self.width + x];
                let tiletype = &self.tiletypes[tile as usize];
                if let Some(ref factory) = tiletype.tile_entity {
                    if let Some(entity) = factory(tile, tiletype, (x, y)) {
                        tile_entities.insert((x, y), entity);
                    }
                }
            }
        }

        Map {
            width: self.width,
            height: self.height,
            tiletypes: self.tiletypes.clone(),
            tiles: tiles,
            entities: self.entities.iter().map(|e| e.create(seed)).collect(),
            tile_entities: tile_entities,
        }
    }
}
<|endoftext|>


<commit_before>//! Implementation of a nonlinear conjugate gradient method.

use num_traits::Float;
use secant2::{Secant2, Secant2Error};
use ndarray::Array1;
use ndarray::ArrayView;
use std::fmt;
use std::error::Error as StdError;
use std::mem::swap;

/// Implementation of a nonlinear conjugate gradient method.
#[derive(Debug,Clone)]
pub struct NonlinearCG<S: Float> {
    /// Nonlinear CG method
    pub method: NonlinearCGMethod<S>,
    /// Parameters for line minimization `secant2` method
    pub line_method: Secant2<S>,
    /// Initial line minimization bracketing interval: `[0, alpha0]`
    pub alpha0: S,
    /// Multiplier for initial line minimization bracketing interval: `[0, psi2 * alpha]`,
    /// where `alpha` was obtained in previous iteration.
    pub psi2: S,
    /// Desired norm of the gradient
    pub grad_norm_tol: S,
    /// Maximum number of iterations to take
    pub max_iter: u32,
}

#[derive(Debug,Clone)]
pub enum NonlinearCGMethod<S> {
    /// Naive method of steepest descent. Really only good for testing.
    SteepestDescent,
    /// `CG_DESCENT` method from [HZ'06] with `eta` parameter
    HagerZhang(S),
}

#[derive(Debug,Clone)]
pub enum Error<S> {
    /// Line minimization `secant2` method failed to converge; returns the current point and search
    /// direction.
    LineMethodError {
        x: Vec<S>,
        d: Vec<S>,
        err: Secant2Error,
    },
    MaxIterReached(u32),
}

/// Information about a performed iteration of the nonlinear CG method
#[derive(Debug, Clone)]
pub struct NonlinearCGIteration<S> {
    /// Iteration number (indexed from 0)
    pub k: u32,
    /// Gradient norm at the beginning of the iteration
    pub grad_norm: S,
    /// Function value at the beginning of the iteration
    pub value: S,
    /// `beta` coefficient for the nonlinear CG search direction update
    pub beta: S,
    /// Line minimization result
    pub alpha: S,
    /// Number of function evaluations by the line minimization method
    pub line_eval_count: u32,
}

impl<S: From<f32> + Float> NonlinearCG<S> {
    /// Defaults: values mostly based on [HZ'06]
    pub fn new() -> Self {
        NonlinearCG {
            method: NonlinearCGMethod::HagerZhang(From::from(0.01f32)),
            line_method: Default::default(),
            alpha0: From::from(1f32),
            psi2: From::from(2f32),
            grad_norm_tol: From::from(1e-3f32),
            max_iter: 100,
        }
    }
}

impl<S: From<f32> + Float> Default for NonlinearCG<S> {
    fn default() -> Self {
        NonlinearCG::new()
    }
}

trait Norm<S> {
    fn norm(&self) -> S;
    fn norm_squared(&self) -> S;
}

impl<S: Float + 'static> Norm<S> for Array1<S> {
    fn norm(&self) -> S {
        self.dot(self).sqrt()
    }

    fn norm_squared(&self) -> S {
        self.dot(self)
    }
}

impl<S: Float + 'static> NonlinearCG<S> {
    /// Mininimize the given nonlinear function over a linear space.
    ///
    /// The function `f` must provide its value as well as its gradient,
    /// returned in the provided `&mut V` (to avoid allocation).
    /// `x0` is used as the initial guess.
    pub fn minimize<Func>(&self, x0: &[S], f: Func) -> Result<Vec<S>, Error<S>>
        where Func: FnMut(&[S], &mut [S]) -> S
    {
        self.minimize_with_trace(x0, f, |_, _| {})
    }

    /// The same as `minimize`, but allows to pass in a callback function that
    /// is called after every iteration.
    /// It is provided with the new point after the iteration is finished,
    /// and with additional information about the performed iteration.
    pub fn minimize_with_trace<Func, Callback>(&self,
                                               x0: &[S],
                                               mut f: Func,
                                               mut trace: Callback)
                                               -> Result<Vec<S>, Error<S>>
        where Func: FnMut(&[S], &mut [S]) -> S,
              Callback: FnMut(&[S], NonlinearCGIteration<S>)
    {
        let x0 = ArrayView::from_shape(x0.len(), x0).unwrap();
        // allocate storage
        let mut x = x0.to_owned();
        let mut g_k_1 = x0.to_owned();
        let mut g_k = x0.to_owned();
        let mut d_k;
        let mut d_k_1 = Array1::from_elem(x0.dim(), S::zero());
        let mut x_temp = x0.to_owned();
        let mut grad_temp = x0.to_owned();
        let mut y = x0.to_owned();

        let mut alpha = self.alpha0;

        for k in 0..self.max_iter {
            // move from previous iteration (swap by moving)
            swap(&mut g_k, &mut g_k_1);
            d_k = d_k_1;
            // compute gradient
            // TODO: use the last evaluation in the line minimization to save this call
            let fx = f(x.as_slice().unwrap(), g_k_1.as_slice_mut().unwrap());

            // test gradient
            let grad_norm = g_k_1.norm();
            if grad_norm < self.grad_norm_tol {
                return Ok(x.into_raw_vec());
            }

            // compute new direction
            let beta = if k == 0 {
                S::zero()
            } else {
                match self.method {
                    NonlinearCGMethod::SteepestDescent => S::zero(),
                    NonlinearCGMethod::HagerZhang(eta) => {
                        y.clone_from(&g_k_1);
                        y = y - &g_k;
                        let dk_yk = d_k.dot(&y);
                        let two = S::one() + S::one();
                        let betan_k = (y.dot(&g_k_1) -
                                       two * d_k.dot(&g_k_1) * y.norm_squared() / dk_yk) /
                                      dk_yk;
                        let eta_k = -S::one() / (d_k.norm() * eta.min(g_k.norm()));
                        betan_k.max(eta_k)
                    }
                }
            };

            // compute new direction
            d_k_1 = {
                azip!(mut d_k, g_k_1 in { *d_k = *d_k * beta - g_k_1});
                d_k
            };
            assert!(d_k_1.dot(&g_k_1) < S::zero(),
                    "The gradient and search direction point in opposite directions");

            // minimize along the ray
            let mut line_eval_count = 0;
            alpha = {
                let mut f_line = |t| {
                    line_eval_count += 1;
                    x_temp.clone_from(&x);
                    azip!(mut x_temp, d_k_1 in { *x_temp = *x_temp + t * d_k_1});
                    let v = f(x_temp.as_slice().unwrap(),
                              grad_temp.as_slice_mut().unwrap());
                    (v, grad_temp.dot(&d_k_1))
                };
                self.line_method
                    .find_wolfe(self.psi2 * alpha,
                                &mut f_line,
                                Some((fx, g_k_1.dot(&d_k_1))))
                    .map_err(|e| {
                                 Error::LineMethodError {
                                     x: x.clone().into_raw_vec(),
                                     d: d_k_1.clone().into_raw_vec(),
                                     err: e,
                                 }
                             })?
            };

            // update position
            azip!(mut x, d_k_1 in { *x = *x + alpha * d_k_1});

            trace(x.as_slice().unwrap(),
                     NonlinearCGIteration {
                         k,
                         beta,
                         grad_norm,
                         value: fx,
                         alpha,
                         line_eval_count,
                     });
        }

        Err(Error::MaxIterReached(self.max_iter))
    }
}

impl<S: fmt::Display> fmt::Display for Error<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::LineMethodError { ref err, .. } => {
                write!(f, "Line minimization failed due to: {}", err)
            }
            &Error::MaxIterReached(n) => write!(f, "Maximum number of iterations reached: {}", n),
        }
    }
}

impl<S: fmt::Display + fmt::Debug> StdError for Error<S> {
    fn description(&self) -> &str {
        match self {
            &Error::LineMethodError { ref err, .. } => err.description(),
            &Error::MaxIterReached(_) => "Maximum number of iterations reached",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self {
            &Error::LineMethodError { err: ref e, .. } => Some(e),
            &Error::MaxIterReached(_) => None,
        }
    }
}
<commit_msg>cosmetic edits<commit_after>//! Implementation of a nonlinear conjugate gradient method.

use num_traits::Float;
use secant2::{Secant2, Secant2Error};
use ndarray::Array1;
use ndarray::ArrayView;
use std::fmt;
use std::error::Error as StdError;
use std::mem::swap;

/// Implementation of a nonlinear conjugate gradient method.
#[derive(Debug,Clone)]
pub struct NonlinearCG<S: Float> {
    /// Nonlinear CG method
    pub method: NonlinearCGMethod<S>,
    /// Parameters for the line minimization `secant2` method
    pub line_method: Secant2<S>,
    /// Initial line minimization bracketing interval: `[0, alpha0]`
    pub alpha0: S,
    /// Multiplier for the initial line minimization bracketing interval: `[0, psi2 * alpha]`,
    /// where `alpha` was obtained in the previous iteration.
    pub psi2: S,
    /// Desired norm of the gradient
    pub grad_norm_tol: S,
    /// Maximum number of iterations to take
    pub max_iter: u32,
}

#[derive(Debug,Clone)]
pub enum NonlinearCGMethod<S> {
    /// The naive method of steepest descent. Really only good for testing.
    SteepestDescent,
    /// The `CG_DESCENT` method from [HZ'06] with an `eta` parameter
    HagerZhang{eta: S},
}

#[derive(Debug,Clone)]
pub enum Error<S> {
    /// Line minimization `secant2` method failed to converge; returns the current point and search
    /// direction.
    LineMethodError {
        x: Vec<S>,
        d: Vec<S>,
        err: Secant2Error,
    },
    MaxIterReached(u32),
}

/// Information about a performed iteration of the nonlinear CG method
#[derive(Debug, Clone)]
pub struct NonlinearCGIteration<S> {
    /// Iteration number (indexed from 0)
    pub k: u32,
    /// Gradient norm at the beginning of the iteration
    pub grad_norm: S,
    /// Function value at the beginning of the iteration
    pub value: S,
    /// `beta` coefficient for the nonlinear CG search direction update
    pub beta: S,
    /// Line minimization result
    pub alpha: S,
    /// Number of function evaluations by the line minimization method
    pub line_eval_count: u32,
}

impl<S: From<f32> + Float> NonlinearCG<S> {
    /// Defaults: values mostly based on [HZ'06]
    pub fn new() -> Self {
        NonlinearCG {
            method: NonlinearCGMethod::HagerZhang{eta: From::from(0.01f32)},
            line_method: Default::default(),
            alpha0: From::from(1f32),
            psi2: From::from(2f32),
            grad_norm_tol: From::from(1e-3f32),
            max_iter: 100,
        }
    }
}

impl<S: From<f32> + Float> Default for NonlinearCG<S> {
    fn default() -> Self {
        NonlinearCG::new()
    }
}

trait Norm<S> {
    fn norm(&self) -> S;
    fn norm_squared(&self) -> S;
}

impl<S: Float + 'static> Norm<S> for Array1<S> {
    fn norm(&self) -> S {
        self.dot(self).sqrt()
    }

    fn norm_squared(&self) -> S {
        self.dot(self)
    }
}

impl<S: Float + 'static> NonlinearCG<S> {
    /// Mininimize the given nonlinear function over a linear space.
    ///
    /// The function `f` must provide its value as well as its gradient,
    /// returned in the provided `&mut V` (to avoid allocation).
    /// `x0` is used as the initial guess.
    pub fn minimize<Func>(&self, x0: &[S], f: Func) -> Result<Vec<S>, Error<S>>
        where Func: FnMut(&[S], &mut [S]) -> S
    {
        self.minimize_with_trace(x0, f, |_, _| {})
    }

    /// The same as `minimize`, but allows to pass in a callback function that
    /// is called after every iteration.
    /// It is provided with the new point after the iteration is finished,
    /// and with additional information about the performed iteration.
    pub fn minimize_with_trace<Func, Callback>(&self,
                                               x0: &[S],
                                               mut f: Func,
                                               mut trace: Callback)
                                               -> Result<Vec<S>, Error<S>>
        where Func: FnMut(&[S], &mut [S]) -> S,
              Callback: FnMut(&[S], NonlinearCGIteration<S>)
    {
        let x0 = ArrayView::from_shape(x0.len(), x0).unwrap();
        // allocate storage
        let mut x = x0.to_owned();
        let mut g_k_1 = x0.to_owned();
        let mut g_k = x0.to_owned();
        let mut d_k;
        let mut d_k_1 = Array1::from_elem(x0.dim(), S::zero());
        let mut x_temp = x0.to_owned();
        let mut grad_temp = x0.to_owned();
        let mut y = x0.to_owned();

        let mut alpha = self.alpha0;

        for k in 0..self.max_iter {
            // move from previous iteration
            swap(&mut g_k, &mut g_k_1);
            d_k = d_k_1;
            // compute gradient
            // TODO: use the last evaluation in the line minimization to save this call
            let fx = f(x.as_slice().unwrap(), g_k_1.as_slice_mut().unwrap());

            // test gradient
            let grad_norm = g_k_1.norm();
            if grad_norm < self.grad_norm_tol {
                return Ok(x.into_raw_vec());
            }

            // compute new direction
            let beta = if k == 0 {
                S::zero()
            } else {
                match self.method {
                    NonlinearCGMethod::SteepestDescent => S::zero(),
                    NonlinearCGMethod::HagerZhang{eta} => {
                        y.clone_from(&g_k_1);
                        y = y - &g_k;
                        let dk_yk = d_k.dot(&y);
                        let two = S::one() + S::one();
                        let betan_k = (y.dot(&g_k_1) -
                                       two * d_k.dot(&g_k_1) * y.norm_squared() / dk_yk) /
                                      dk_yk;
                        let eta_k = -S::one() / (d_k.norm() * eta.min(g_k.norm()));
                        betan_k.max(eta_k)
                    }
                }
            };

            // compute the new direction
            d_k_1 = {
                azip!(mut d_k, g_k_1 in { *d_k = *d_k * beta - g_k_1});
                d_k
            };
            assert!(d_k_1.dot(&g_k_1) < S::zero(),
                    "The gradient and search direction point in opposite directions");

            // minimize along the ray
            let mut line_eval_count = 0;
            alpha = {
                let mut f_line = |t| {
                    line_eval_count += 1;
                    x_temp.clone_from(&x);
                    azip!(mut x_temp, d_k_1 in { *x_temp = *x_temp + t * d_k_1});
                    let v = f(x_temp.as_slice().unwrap(),
                              grad_temp.as_slice_mut().unwrap());
                    (v, grad_temp.dot(&d_k_1))
                };
                self.line_method
                    .find_wolfe(self.psi2 * alpha,
                                &mut f_line,
                                Some((fx, g_k_1.dot(&d_k_1))))
                    .map_err(|e| {
                                 Error::LineMethodError {
                                     x: x.clone().into_raw_vec(),
                                     d: d_k_1.clone().into_raw_vec(),
                                     err: e,
                                 }
                             })?
            };

            // update the position
            azip!(mut x, d_k_1 in { *x = *x + alpha * d_k_1});

            trace(x.as_slice().unwrap(),
                     NonlinearCGIteration {
                         k,
                         beta,
                         grad_norm,
                         value: fx,
                         alpha,
                         line_eval_count,
                     });
        }

        Err(Error::MaxIterReached(self.max_iter))
    }
}

impl<S: fmt::Display> fmt::Display for Error<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::LineMethodError { ref err, .. } => {
                write!(f, "Line minimization failed due to: {}", err)
            }
            &Error::MaxIterReached(n) => write!(f, "Maximum number of iterations reached: {}", n),
        }
    }
}

impl<S: fmt::Display + fmt::Debug> StdError for Error<S> {
    fn description(&self) -> &str {
        match self {
            &Error::LineMethodError { ref err, .. } => err.description(),
            &Error::MaxIterReached(_) => "Maximum number of iterations reached",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match self {
            &Error::LineMethodError { err: ref e, .. } => Some(e),
            &Error::MaxIterReached(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![cfg_attr(not(target_os = "redox"), feature(io))]

extern crate extra;

use std::ascii::AsciiExt;
use std::env::args;
use std::io::{self, Write, Read};
use std::process::exit;

use extra::option::OptionalExt;
use extra::io::{fail, WriteExt};

static HELP: &'static str = /* @MANSTART{mtxt} */ r#"
NAME
    mtxt - a simple tool to manipulate text from standard input.

SYNOPSIS
    mtxt [-h | --help | -u | --to-uppercase-w | -l | --to-lowercase | -a | --strip-non-ascii]

DESCRIPTION
    This utility will manipulate UTF-8 encoded text from the standard input. Unicode is supported.
    The flags are composable, unless otherwise stated.

OPTIONS
    -h
    --help
        Print this manual page.

    -u
    --to-uppercase
        Convert the input to UPPERCASE. Works correctly with Unicode. Incompatible with '-l'.

    -l
    --lowercase
        Convert the input to lowercase. Works correctly with Unicode.

    -a
    --strip-non-ascii
        Strip the input for non-ASCII bytes, outputting a valid ASCII string.

EXAMPLES
    $ echo Δ | mtxt -l
    > δ
    $ echo we got deltas Δ right | mtxt -a
    > we got deltas  right
    $ echo Japanese scripts do not have case thus 山will stay unchanged | mtxt -u
    > JAPANESE SCRIPTS DO NOT HAVE CASE THUS 山WILL STAY UNCHANGED

AUTHOR
    This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be
    reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 Ticki

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    Do you actually read the license? wat?
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    // These are the options.
    let mut to_uppercase = false;
    let mut to_lowercase = false;
    let mut strip_non_ascii = false;

    for arg in args().skip(1) {
        match arg.as_str() {
            "-u" | "--to-uppercase" => to_uppercase = true,
            "-l" | "--to-lowercase" => to_lowercase = true,
            "-a" | "--strip-non-ascii" => strip_non_ascii = true,
            "-h" | "--help" => {
                // The help page.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
            },
            a => {
                // The argument, a, is unknown.
                stderr.write(b"error: unknown argument, ").try(&mut stderr);
                stderr.write(a.as_bytes()).try(&mut stderr);
                stderr.write(b".\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            },
        }
    }

    if to_lowercase && to_uppercase {
        // Fail, since -u and -l are incompatible.
        fail("-u and -l are incompatible. Aborting.", &mut stderr);
    }

    // My eyes bleed.
    //
    // Anyone?
    // ...
    //
    // Silence.
    //
    // If you see this, rewrite the code below. Now, you can't say no. Too late.
    // Muhahahaha.
    for i in stdin.chars() {
        let i = i.try(&mut stderr);

        // TODO handle -a more efficient

        // If -u is set, convert to uppercase
        if to_uppercase {
            for uppercase in i.to_uppercase().filter(|x| !strip_non_ascii || x.is_ascii() ) {
                stdout.write_char(uppercase).try(&mut stderr);
            }
        // If -l is set, convert to lowercase
        } else if to_lowercase {
            for lowercase in i.to_lowercase().filter(|x| !strip_non_ascii || x.is_ascii()) {
                stdout.write_char(lowercase).try(&mut stderr);
            }
        // If -a is set, strip non-ASCII.
        } else if !strip_non_ascii || strip_non_ascii && i.is_ascii() {
            stdout.write_char(i).try(&mut stderr);
        }
    }
}
<commit_msg>Allow io feature on redox<commit_after>#![deny(warnings)]
#![feature(io)]

extern crate extra;

use std::ascii::AsciiExt;
use std::env::args;
use std::io::{self, Write, Read};
use std::process::exit;

use extra::option::OptionalExt;
use extra::io::{fail, WriteExt};

static HELP: &'static str = /* @MANSTART{mtxt} */ r#"
NAME
    mtxt - a simple tool to manipulate text from standard input.

SYNOPSIS
    mtxt [-h | --help | -u | --to-uppercase-w | -l | --to-lowercase | -a | --strip-non-ascii]

DESCRIPTION
    This utility will manipulate UTF-8 encoded text from the standard input. Unicode is supported.
    The flags are composable, unless otherwise stated.

OPTIONS
    -h
    --help
        Print this manual page.

    -u
    --to-uppercase
        Convert the input to UPPERCASE. Works correctly with Unicode. Incompatible with '-l'.

    -l
    --lowercase
        Convert the input to lowercase. Works correctly with Unicode.

    -a
    --strip-non-ascii
        Strip the input for non-ASCII bytes, outputting a valid ASCII string.

EXAMPLES
    $ echo Δ | mtxt -l
    > δ
    $ echo we got deltas Δ right | mtxt -a
    > we got deltas  right
    $ echo Japanese scripts do not have case thus 山will stay unchanged | mtxt -u
    > JAPANESE SCRIPTS DO NOT HAVE CASE THUS 山WILL STAY UNCHANGED

AUTHOR
    This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be
    reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 Ticki

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    Do you actually read the license? wat?
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    // These are the options.
    let mut to_uppercase = false;
    let mut to_lowercase = false;
    let mut strip_non_ascii = false;

    for arg in args().skip(1) {
        match arg.as_str() {
            "-u" | "--to-uppercase" => to_uppercase = true,
            "-l" | "--to-lowercase" => to_lowercase = true,
            "-a" | "--strip-non-ascii" => strip_non_ascii = true,
            "-h" | "--help" => {
                // The help page.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
            },
            a => {
                // The argument, a, is unknown.
                stderr.write(b"error: unknown argument, ").try(&mut stderr);
                stderr.write(a.as_bytes()).try(&mut stderr);
                stderr.write(b".\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            },
        }
    }

    if to_lowercase && to_uppercase {
        // Fail, since -u and -l are incompatible.
        fail("-u and -l are incompatible. Aborting.", &mut stderr);
    }

    // My eyes bleed.
    //
    // Anyone?
    // ...
    //
    // Silence.
    //
    // If you see this, rewrite the code below. Now, you can't say no. Too late.
    // Muhahahaha.
    for i in stdin.chars() {
        let i = i.try(&mut stderr);

        // TODO handle -a more efficient

        // If -u is set, convert to uppercase
        if to_uppercase {
            for uppercase in i.to_uppercase().filter(|x| !strip_non_ascii || x.is_ascii() ) {
                stdout.write_char(uppercase).try(&mut stderr);
            }
        // If -l is set, convert to lowercase
        } else if to_lowercase {
            for lowercase in i.to_lowercase().filter(|x| !strip_non_ascii || x.is_ascii()) {
                stdout.write_char(lowercase).try(&mut stderr);
            }
        // If -a is set, strip non-ASCII.
        } else if !strip_non_ascii || strip_non_ascii && i.is_ascii() {
            stdout.write_char(i).try(&mut stderr);
        }
    }
}
<|endoftext|>


<commit_before>/// The Toml Set extensions

#[cfg(feature = "typed")]
use serde::Serialize;
use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::{Error, Result};

pub trait TomlValueSetExt {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &str, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &str, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

    /// A convenience method for setting any arbitrary serializable value.
    #[cfg(feature = "typed")]
    fn set_serialized<S: Serialize>(&mut self, query: &str, value: S) -> Result<Option<Value>> {
        let value = Value::try_from(value).map_err(Error::TomlSerialize)?;
        self.set(query, value)
    }

}

impl TomlValueSetExt for Value {

    fn set_with_seperator(&mut self, query: &str, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();

        let val = try!(resolve(self, &tokens, true))
            .unwrap(); // safe because of resolve() guarantees
        let last = last.unwrap_or_else(|| Box::new(tokens));

        match *last {
            Token::Identifier { ident, .. } => {
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    },
                    &mut Value::Array(_) => Err(Error::NoIdentifierInArray(ident)),
                    _ => Err(Error::QueryingValueAsTable(ident)),
                }
            }

            Token::Index { idx, .. } => {
                match val {
                    &mut Value::Array(ref mut a) => {
                        if a.len() > idx {
                            let result = a.swap_remove(idx);
                            a.insert(idx, value);
                            Ok(Some(result))
                        } else {
                            a.push(value);
                            Ok(None)
                        }
                    }
                    &mut Value::Table(_) => Err(Error::NoIndexInTable(idx)),
                    _ => Err(Error::QueryingValueAsArray(idx)),
                }
            }

        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_key_nonexistent() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());
        let res = res.unwrap();

        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_index_nonexistent() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_table() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res, Error::IdentifierNotFoundInDocument(_)));
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_array() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("[0]"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res, Error::NoIndexInTable(0)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_ary() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::NoIdentifierInArray(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_table() {
        let mut toml : Value = toml_from_str(r#"
        foo = { bar = 1 }
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::NoIndexInTable(_)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        val = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("val.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::QueryingValueAsTable(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        foo = 1
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::QueryingValueAsArray(_)));
    }

    #[cfg(feature = "typed")]
    #[test]
    fn test_serialize() {
        use std::collections::BTreeMap;
        use insert::TomlValueInsertExt;
        use read::TomlValueReadExt;

        #[derive(Serialize, Deserialize, Debug)]
        struct Test {
            a: u64,
            s: String,
        }

        let mut toml = Value::Table(BTreeMap::new());
        let test     = Test {
            a: 15,
            s: String::from("Helloworld"),
        };

        assert!(toml.insert_serialized("table.value", test).unwrap().is_none());

        eprintln!("{:#}", toml);

        match toml {
            Value::Table(ref tab) => match tab.get("table").unwrap() {
                &Value::Table(ref inner) => {
                    match inner.get("value").unwrap() {
                        &Value::Table(ref data) => {
                            assert!(is_match!(data.get("a").unwrap(), &Value::Integer(15)));
                            match data.get("s").unwrap() {
                                &Value::String(ref s) => assert_eq!(s, "Helloworld"),
                                _ => assert!(false),
                            };
                        }
                        _ => assert!(false),
                    }
                },
                _ => assert!(false)
            },
            _ => assert!(false),
        }

    }

}

<commit_msg>Remove unused import<commit_after>/// The Toml Set extensions

#[cfg(feature = "typed")]
use serde::Serialize;
use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::{Error, Result};

pub trait TomlValueSetExt {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &str, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &str, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

    /// A convenience method for setting any arbitrary serializable value.
    #[cfg(feature = "typed")]
    fn set_serialized<S: Serialize>(&mut self, query: &str, value: S) -> Result<Option<Value>> {
        let value = Value::try_from(value).map_err(Error::TomlSerialize)?;
        self.set(query, value)
    }

}

impl TomlValueSetExt for Value {

    fn set_with_seperator(&mut self, query: &str, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();

        let val = try!(resolve(self, &tokens, true))
            .unwrap(); // safe because of resolve() guarantees
        let last = last.unwrap_or_else(|| Box::new(tokens));

        match *last {
            Token::Identifier { ident, .. } => {
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    },
                    &mut Value::Array(_) => Err(Error::NoIdentifierInArray(ident)),
                    _ => Err(Error::QueryingValueAsTable(ident)),
                }
            }

            Token::Index { idx, .. } => {
                match val {
                    &mut Value::Array(ref mut a) => {
                        if a.len() > idx {
                            let result = a.swap_remove(idx);
                            a.insert(idx, value);
                            Ok(Some(result))
                        } else {
                            a.push(value);
                            Ok(None)
                        }
                    }
                    &mut Value::Table(_) => Err(Error::NoIndexInTable(idx)),
                    _ => Err(Error::QueryingValueAsArray(idx)),
                }
            }

        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_key_nonexistent() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());
        let res = res.unwrap();

        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_index_nonexistent() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_table() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res, Error::IdentifierNotFoundInDocument(_)));
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_array() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("[0]"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res, Error::NoIndexInTable(0)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_ary() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::NoIdentifierInArray(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_table() {
        let mut toml : Value = toml_from_str(r#"
        foo = { bar = 1 }
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::NoIndexInTable(_)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        val = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("val.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::QueryingValueAsTable(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        foo = 1
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res, Error::QueryingValueAsArray(_)));
    }

    #[cfg(feature = "typed")]
    #[test]
    fn test_serialize() {
        use std::collections::BTreeMap;
        use insert::TomlValueInsertExt;

        #[derive(Serialize, Deserialize, Debug)]
        struct Test {
            a: u64,
            s: String,
        }

        let mut toml = Value::Table(BTreeMap::new());
        let test     = Test {
            a: 15,
            s: String::from("Helloworld"),
        };

        assert!(toml.insert_serialized("table.value", test).unwrap().is_none());

        eprintln!("{:#}", toml);

        match toml {
            Value::Table(ref tab) => match tab.get("table").unwrap() {
                &Value::Table(ref inner) => {
                    match inner.get("value").unwrap() {
                        &Value::Table(ref data) => {
                            assert!(is_match!(data.get("a").unwrap(), &Value::Integer(15)));
                            match data.get("s").unwrap() {
                                &Value::String(ref s) => assert_eq!(s, "Helloworld"),
                                _ => assert!(false),
                            };
                        }
                        _ => assert!(false),
                    }
                },
                _ => assert!(false)
            },
            _ => assert!(false),
        }

    }

}

<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
#![feature(std_misc)]
/* workaround: the rust compiler doesn't recognize
   the feature std_misc yet, still it warns
   about using it */
#![allow(unused_features)]
#![feature(std_misc)]

extern crate libc;
use libc::{c_int, c_ulonglong, c_char, size_t};

include!("src/core.rs");
include!("src/crypto_aead_chacha20poly1305.rs");

include!("src/crypto_auth.rs");
include!("src/crypto_auth_hmacsha256.rs");
include!("src/crypto_auth_hmacsha512.rs");
include!("src/crypto_auth_hmacsha512256.rs");

include!("src/crypto_box_curve25519xsalsa20poly1305.rs");

include!("src/crypto_hash.rs");
include!("src/crypto_hash_sha256.rs");
include!("src/crypto_hash_sha512.rs");

include!("src/crypto_onetimeauth.rs");
include!("src/crypto_onetimeauth_poly1305.rs");

include!("src/crypto_pwhash_scryptsalsa208sha256.rs");

include!("src/crypto_scalarmult_curve25519.rs");
include!("src/crypto_secretbox_xsalsa20poly1305.rs");
include!("src/crypto_shorthash_siphash24.rs");
include!("src/crypto_sign_ed25519.rs");
include!("src/crypto_sign_edwards25519sha512batch.rs");

include!("src/crypto_stream.rs");
include!("src/crypto_stream_aes128ctr.rs");
include!("src/crypto_stream_chacha20.rs");
include!("src/crypto_stream_salsa20.rs");
include!("src/crypto_stream_salsa2012.rs");
include!("src/crypto_stream_salsa208.rs");
include!("src/crypto_stream_xsalsa20.rs");

include!("src/crypto_verify_16.rs");
include!("src/crypto_verify_32.rs");

include!("src/randombytes.rs");
<commit_msg>Removed unnecessary #![feature(..)] directives<commit_after>#![allow(non_upper_case_globals)]

extern crate libc;
use libc::{c_int, c_ulonglong, c_char, size_t};

include!("src/core.rs");
include!("src/crypto_aead_chacha20poly1305.rs");

include!("src/crypto_auth.rs");
include!("src/crypto_auth_hmacsha256.rs");
include!("src/crypto_auth_hmacsha512.rs");
include!("src/crypto_auth_hmacsha512256.rs");

include!("src/crypto_box_curve25519xsalsa20poly1305.rs");

include!("src/crypto_hash.rs");
include!("src/crypto_hash_sha256.rs");
include!("src/crypto_hash_sha512.rs");

include!("src/crypto_onetimeauth.rs");
include!("src/crypto_onetimeauth_poly1305.rs");

include!("src/crypto_pwhash_scryptsalsa208sha256.rs");

include!("src/crypto_scalarmult_curve25519.rs");
include!("src/crypto_secretbox_xsalsa20poly1305.rs");
include!("src/crypto_shorthash_siphash24.rs");
include!("src/crypto_sign_ed25519.rs");
include!("src/crypto_sign_edwards25519sha512batch.rs");

include!("src/crypto_stream.rs");
include!("src/crypto_stream_aes128ctr.rs");
include!("src/crypto_stream_chacha20.rs");
include!("src/crypto_stream_salsa20.rs");
include!("src/crypto_stream_salsa2012.rs");
include!("src/crypto_stream_salsa208.rs");
include!("src/crypto_stream_xsalsa20.rs");

include!("src/crypto_verify_16.rs");
include!("src/crypto_verify_32.rs");

include!("src/randombytes.rs");
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::RingBuf;
use std::rc::Rc;
use std::num::Int;

/// Common buffer object for the two tee halves
struct TeeBuffer<A, I>
{
    backlog: RingBuf<A>,
    iter: I,
    /// The owner field indicates which id should read from the backlog
    owner: bool,
}

/// One half of an iterator pair where both return the same elements.
pub struct Tee<I: Iterator>
{
    rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>,
    id: bool,
}

pub fn new<I: Iterator>(iter: I) -> (Tee<I>, Tee<I>)
{
    let buffer = TeeBuffer{backlog: RingBuf::new(), iter: iter, owner: false};
    let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true};
    let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false};
    (t1, t2)
}

impl<I: Iterator> Iterator for Tee<I> where
    I::Item: Clone,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item>
    {
        // .borrow_mut may fail here -- but only if the user has tied some kind of weird
        // knot where the iterator refers back to itself.
        //
        // Avoid panic!() in release code here for better code gen.
        let mut buffer = match self.rcbuffer.try_borrow_mut() {
            None => {
                debug_assert!(false, "Tee::next: Cycle in tee iterator.");
                return None;
            }
            Some(bufref) => bufref,
        };
        if buffer.owner == self.id {
            match buffer.backlog.pop_front() {
                None => {}
                some_elt => return some_elt,
            }
        }
        match buffer.iter.next() {
            None => None,
            Some(elt) => {
                buffer.backlog.push_back(elt.clone());
                buffer.owner = !self.id;
                Some(elt)
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let buffer = self.rcbuffer.borrow();
        let (mut lower, mut upper) = buffer.iter.size_hint();

        if buffer.owner == self.id {
            let log_len = buffer.backlog.len();
            lower = lower.saturating_add(log_len);
            upper = upper.and_then(|x| x.checked_add(log_len));
        }
        (lower, upper)
    }
}
<commit_msg>Update Tee for deprecation of RefCell::try_borrow_mut<commit_after>use std::cell::RefCell;
use std::collections::RingBuf;
use std::rc::Rc;
use std::num::Int;

/// Common buffer object for the two tee halves
struct TeeBuffer<A, I>
{
    backlog: RingBuf<A>,
    iter: I,
    /// The owner field indicates which id should read from the backlog
    owner: bool,
}

/// One half of an iterator pair where both return the same elements.
pub struct Tee<I: Iterator>
{
    rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>,
    id: bool,
}

pub fn new<I: Iterator>(iter: I) -> (Tee<I>, Tee<I>)
{
    let buffer = TeeBuffer{backlog: RingBuf::new(), iter: iter, owner: false};
    let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true};
    let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false};
    (t1, t2)
}

impl<I: Iterator> Iterator for Tee<I> where
    I::Item: Clone,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item>
    {
        // .borrow_mut may fail here -- but only if the user has tied some kind of weird
        // knot where the iterator refers back to itself.
        let mut buffer = self.rcbuffer.borrow_mut();
        if buffer.owner == self.id {
            match buffer.backlog.pop_front() {
                None => {}
                some_elt => return some_elt,
            }
        }
        match buffer.iter.next() {
            None => None,
            Some(elt) => {
                buffer.backlog.push_back(elt.clone());
                buffer.owner = !self.id;
                Some(elt)
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        let buffer = self.rcbuffer.borrow();
        let (mut lower, mut upper) = buffer.iter.size_hint();

        if buffer.owner == self.id {
            let log_len = buffer.backlog.len();
            lower = lower.saturating_add(log_len);
            upper = upper.and_then(|x| x.checked_add(log_len));
        }
        (lower, upper)
    }
}
<|endoftext|>


<commit_before>extern crate gl;

use color::Color4;
use sdl2::pixels::ll::{SDL_Color,SDL_PIXELFORMAT_ARGB8888};
use sdl2::surface::ll::SDL_Surface;
use sdl2::surface;

use std::path::Path;

#[allow(non_camel_case_types)]
#[allow(dead_code)]
pub mod ffi {
  extern crate libc;

  use sdl2::pixels::ll::SDL_Color;
  use sdl2::surface::ll::SDL_Surface;

  pub use self::libc::{c_int, c_char, c_void, c_long};

  pub type TTF_Font = c_void;

  pub type TTF_StyleFlag = c_int;
  pub static TTF_STYLE_NORMAL: TTF_StyleFlag = 0x00;
  pub static TTF_STYLE_BOLD: TTF_StyleFlag = 0x01;
  pub static TTF_STYLE_ITALIC: TTF_StyleFlag = 0x02;
  pub static TTF_STYLE_UNDERLINE: c_int = 0x04;
  pub static TTF_STYLE_STRIKETHROUGH: c_int = 0x08;

  pub type TTF_Hinting = c_int;
  pub static TTF_HINTING_NORMAL: TTF_Hinting = 0;
  pub static TTF_HINTING_LIGHT: TTF_Hinting = 1;
  pub static TTF_HINTING_MONO: TTF_Hinting = 2;
  pub static TTF_HINTING_NONE: TTF_Hinting = 3;

  #[link(name="SDL2_ttf")]
  extern "C" {
    pub fn TTF_Init() -> c_int;
    pub fn TTF_WasInit() -> c_int;
    pub fn TTF_Quit();
    pub fn TTF_OpenFont(file: *const c_char, ptsize: c_int) -> *mut TTF_Font;
    pub fn TTF_OpenFontIndex(file: *const c_char, ptsize: c_int, index: c_long) -> *mut TTF_Font;
    pub fn TTF_CloseFont(font: *mut TTF_Font);

    pub fn TTF_GetFontStyle(font: *const TTF_Font) -> TTF_StyleFlag;
    pub fn TTF_SetFontStyle(font: *mut TTF_Font, style: TTF_StyleFlag);
    pub fn TTF_GetFontOutline(font: *const TTF_Font) -> c_int;
    pub fn TTF_SetFontOutline(font: *mut TTF_Font, outline: c_int);
    pub fn TTF_GetFontHinting(font: *const TTF_Font) -> TTF_Hinting;
    pub fn TTF_SetFontHinting(font: *mut TTF_Font, hinting: TTF_Hinting);
    pub fn TTF_GetFontKerning(font: *const TTF_Font) -> c_int;
    pub fn TTF_SetFontKerning(font: *mut TTF_Font, kerning: c_int);
    pub fn TTF_FontHeight(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontAscent(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontDescent(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontLineSkip(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontFaces(font: *const TTF_Font) -> c_long;
    pub fn TTF_FontFaceIsFixedWidth(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontFaceFamilyName(font: *const TTF_Font) -> *const c_char;
    pub fn TTF_GlyphIsProvided(font: *const TTF_Font, glyph: u16) -> c_int;
    pub fn TTF_GlyphMetrics(font: *const TTF_Font, glyph: u16, minx: *mut c_int, maxx: *mut c_int, miny: *mut c_int, maxy: *mut c_int, advance: *mut c_int) -> c_int;
    pub fn TTF_SizeUTF8(font: *mut TTF_Font, text: *const c_char, w: *mut c_int, h: *mut c_int) -> c_int;

    pub fn TTF_RenderUTF8_Solid(font: *const TTF_Font, text: *const c_char, fg: SDL_Color) -> *mut SDL_Surface;
    pub fn TTF_RenderUTF8_Shaded(font:  *const TTF_Font, text: *const c_char, fg: SDL_Color, bg: SDL_Color) -> *mut SDL_Surface;
    pub fn TTF_RenderUTF8_Blended(font: *const TTF_Font, text: *const c_char, fg: SDL_Color)                -> *mut SDL_Surface;
  }
}

pub struct Font {
  p: *mut ffi::TTF_Font
}

fn ensure_init() {
  unsafe {
    if ffi::TTF_WasInit() == 0 {
      assert_eq!(ffi::TTF_Init(), 0);
    }
  }
}

impl Font {
  pub fn new(font: &Path, point_size: uint) -> Font {
    ensure_init();

    let c_path = font.to_c_str();
    let p = unsafe { ffi::TTF_OpenFont(c_path.as_ptr(), point_size as ffi::c_int) };

    assert!(p.is_not_null());

    Font { p: p }
  }

  /// Color is rgba
  pub fn render(&self, txt: &str, color: Color4<u8>) -> gl::types::GLuint {
    unsafe {
      let sdl_color = SDL_Color {
        r: color.r,
        g: color.g,
        b: color.b,
        a: color.a
      };

      let surface_ptr = txt.with_c_str(|c_txt| {
          ffi::TTF_RenderUTF8_Blended(self.p as *const ffi::c_void, c_txt, sdl_color)
        });

      let tex = surface_ptr.to_option().expect("Cannot render text.");

      assert!((*tex.format).format == SDL_PIXELFORMAT_ARGB8888, "pixel format was unexpected 0x{:x}", (*tex.format).format);

      let mut texture = 0;
      gl::GenTextures(1, &mut texture);
      gl::BindTexture(gl::TEXTURE_2D, texture);
      gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, tex.w, tex.h, 0, gl::BGRA, gl::UNSIGNED_INT_8_8_8_8_REV, tex.pixels);
      gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
      gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

      surface::ll::SDL_FreeSurface(surface_ptr as *const SDL_Surface);
      texture
    }
  }

  pub fn red(&self, txt: &str) -> gl::types::GLuint {
    self.render(txt, Color4::new(0xFF, 0x00, 0x00, 0xFF))
  }

  /// dark black #333
  pub fn dark(&self, txt: &str) -> gl::types::GLuint {
    self.render(txt, Color4::new(0x33, 0x33, 0x33, 0xFF))
  }

  /// light black #555
  pub fn light(&self, txt: &str) -> gl::types::GLuint {
    self.render(txt, Color4::new(0x55, 0x55, 0x55, 0xFF))
  }
}

impl Drop for Font {
  fn drop(&mut self) {
    unsafe { ffi::TTF_CloseFont(self.p) }
  }
}

#[test]
fn load_and_unload() {
  Font::new(&Path::new("fonts/Open_Sans/OpenSans-Regular.ttf"), 12);
}
<commit_msg>assert_eq<commit_after>extern crate gl;

use color::Color4;
use sdl2::pixels::ll::{SDL_Color,SDL_PIXELFORMAT_ARGB8888};
use sdl2::surface::ll::SDL_Surface;
use sdl2::surface;

use std::path::Path;

#[allow(non_camel_case_types)]
#[allow(dead_code)]
pub mod ffi {
  extern crate libc;

  use sdl2::pixels::ll::SDL_Color;
  use sdl2::surface::ll::SDL_Surface;

  pub use self::libc::{c_int, c_char, c_void, c_long};

  pub type TTF_Font = c_void;

  pub type TTF_StyleFlag = c_int;
  pub static TTF_STYLE_NORMAL: TTF_StyleFlag = 0x00;
  pub static TTF_STYLE_BOLD: TTF_StyleFlag = 0x01;
  pub static TTF_STYLE_ITALIC: TTF_StyleFlag = 0x02;
  pub static TTF_STYLE_UNDERLINE: c_int = 0x04;
  pub static TTF_STYLE_STRIKETHROUGH: c_int = 0x08;

  pub type TTF_Hinting = c_int;
  pub static TTF_HINTING_NORMAL: TTF_Hinting = 0;
  pub static TTF_HINTING_LIGHT: TTF_Hinting = 1;
  pub static TTF_HINTING_MONO: TTF_Hinting = 2;
  pub static TTF_HINTING_NONE: TTF_Hinting = 3;

  #[link(name="SDL2_ttf")]
  extern "C" {
    pub fn TTF_Init() -> c_int;
    pub fn TTF_WasInit() -> c_int;
    pub fn TTF_Quit();
    pub fn TTF_OpenFont(file: *const c_char, ptsize: c_int) -> *mut TTF_Font;
    pub fn TTF_OpenFontIndex(file: *const c_char, ptsize: c_int, index: c_long) -> *mut TTF_Font;
    pub fn TTF_CloseFont(font: *mut TTF_Font);

    pub fn TTF_GetFontStyle(font: *const TTF_Font) -> TTF_StyleFlag;
    pub fn TTF_SetFontStyle(font: *mut TTF_Font, style: TTF_StyleFlag);
    pub fn TTF_GetFontOutline(font: *const TTF_Font) -> c_int;
    pub fn TTF_SetFontOutline(font: *mut TTF_Font, outline: c_int);
    pub fn TTF_GetFontHinting(font: *const TTF_Font) -> TTF_Hinting;
    pub fn TTF_SetFontHinting(font: *mut TTF_Font, hinting: TTF_Hinting);
    pub fn TTF_GetFontKerning(font: *const TTF_Font) -> c_int;
    pub fn TTF_SetFontKerning(font: *mut TTF_Font, kerning: c_int);
    pub fn TTF_FontHeight(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontAscent(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontDescent(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontLineSkip(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontFaces(font: *const TTF_Font) -> c_long;
    pub fn TTF_FontFaceIsFixedWidth(font: *const TTF_Font) -> c_int;
    pub fn TTF_FontFaceFamilyName(font: *const TTF_Font) -> *const c_char;
    pub fn TTF_GlyphIsProvided(font: *const TTF_Font, glyph: u16) -> c_int;
    pub fn TTF_GlyphMetrics(font: *const TTF_Font, glyph: u16, minx: *mut c_int, maxx: *mut c_int, miny: *mut c_int, maxy: *mut c_int, advance: *mut c_int) -> c_int;
    pub fn TTF_SizeUTF8(font: *mut TTF_Font, text: *const c_char, w: *mut c_int, h: *mut c_int) -> c_int;

    pub fn TTF_RenderUTF8_Solid(font: *const TTF_Font, text: *const c_char, fg: SDL_Color) -> *mut SDL_Surface;
    pub fn TTF_RenderUTF8_Shaded(font:  *const TTF_Font, text: *const c_char, fg: SDL_Color, bg: SDL_Color) -> *mut SDL_Surface;
    pub fn TTF_RenderUTF8_Blended(font: *const TTF_Font, text: *const c_char, fg: SDL_Color)                -> *mut SDL_Surface;
  }
}

pub struct Font {
  p: *mut ffi::TTF_Font
}

fn ensure_init() {
  unsafe {
    if ffi::TTF_WasInit() == 0 {
      assert_eq!(ffi::TTF_Init(), 0);
    }
  }
}

impl Font {
  pub fn new(font: &Path, point_size: uint) -> Font {
    ensure_init();

    let c_path = font.to_c_str();
    let p = unsafe { ffi::TTF_OpenFont(c_path.as_ptr(), point_size as ffi::c_int) };

    assert!(p.is_not_null());

    Font { p: p }
  }

  /// Color is rgba
  pub fn render(&self, txt: &str, color: Color4<u8>) -> gl::types::GLuint {
    unsafe {
      let sdl_color = SDL_Color {
        r: color.r,
        g: color.g,
        b: color.b,
        a: color.a
      };

      let surface_ptr = txt.with_c_str(|c_txt| {
          ffi::TTF_RenderUTF8_Blended(self.p as *const ffi::c_void, c_txt, sdl_color)
        });

      let tex = surface_ptr.to_option().expect("Cannot render text.");

      assert_eq!((*tex.format).format, SDL_PIXELFORMAT_ARGB8888);

      let mut texture = 0;
      gl::GenTextures(1, &mut texture);
      gl::BindTexture(gl::TEXTURE_2D, texture);
      gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, tex.w, tex.h, 0, gl::BGRA, gl::UNSIGNED_INT_8_8_8_8_REV, tex.pixels);
      gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
      gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

      surface::ll::SDL_FreeSurface(surface_ptr as *const SDL_Surface);
      texture
    }
  }

  pub fn red(&self, txt: &str) -> gl::types::GLuint {
    self.render(txt, Color4::new(0xFF, 0x00, 0x00, 0xFF))
  }

  /// dark black #333
  pub fn dark(&self, txt: &str) -> gl::types::GLuint {
    self.render(txt, Color4::new(0x33, 0x33, 0x33, 0xFF))
  }

  /// light black #555
  pub fn light(&self, txt: &str) -> gl::types::GLuint {
    self.render(txt, Color4::new(0x55, 0x55, 0x55, 0xFF))
  }
}

impl Drop for Font {
  fn drop(&mut self) {
    unsafe { ffi::TTF_CloseFont(self.p) }
  }
}

#[test]
fn load_and_unload() {
  Font::new(&Path::new("fonts/Open_Sans/OpenSans-Regular.ttf"), 12);
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Eq, Debug)]
struct Age(u8);

struct Person<'a> {
    name: &'static str,
    parent: Option<&'a Person<'a>>,
}

impl<'a> Person<'a> {
    fn new(name: &'static str, parent: Option<&'a Person<'a>>) -> Person<'a> {
        Person{name: name, parent: parent}
    }

    fn parents_name(&self) -> Option<&'static str> {
        match self.parent {
            Some(p) => Some(p.name),
            None => None,
        }
    }
}

// This one can be elided.
fn first_five<'a>(value: &'a String) -> &'a str {
    &value[..5]
}

// This cannot be elided because Rust doesn't know to use lifetime of "a" or "b".
fn double_first_five<'a>(a: &'a String, b: &'a String) -> (&'a str, &'a str) {
    (&a[..5], &b[..5])
}

// Output borrows generally must have an input value from which it can borrow. The exception is
// the static lifetime.
// Couldn't Rust infer from the body of the function that the borrows are from the static lifetime?
//   - I feel that Rust favours explicitness over terseness. A functions behaviour should be
//   encoded directly into it's signature.
fn output_only<'a>() -> (&'static u8, &'static u8) {
    static X: u8 = 8;
    static Y: u8 = 9;

    (&X, &Y)
}

// Here we are promising Rust that all of the borrowed u8's
// live for the same scope.
// Q: Why do I need a lifetime here?
fn join_ages<'a, T: Iterator>(iters: T) -> Vec<&'a Age>
        where T::Item: IntoIterator<Item=&'a Age> {
    iters.flat_map(|b| b.into_iter())
         .collect()
}

// This is not really necessary here. Both a and b could use the same lifetime
// as Rust only cares that a and b are available for the scope of this function.
// This could also be elided.
fn multi_lifetimes<'a, 'b>(a: &'a u8, b: &'b u8) -> bool {
    (a + b) > 10
}

fn multiple_lifetimes() -> bool {
    let a = &9;

    {
        let b = &9;

        multi_lifetimes(a, b)
    }
}

#[test]
fn it_works() {
    let jane = Person::new("Jane", None);
    let tom = Person::new("Tom", Some(&jane));
    let name = "Andrew".to_owned();
    let another = "Timothy".to_owned();
    let a = 43;
    let vec_ages = vec![vec![Age(90), Age(80)],
                        vec![Age(2)]];

    let arr_ages = vec![[Age(90), Age(80)],
                        [Age(2), Age(45)]];

    assert_eq!(output_only(), (&8, &9));

    assert_eq!(first_five(&name), "Andre");
    assert_eq!(double_first_five(&name, &another), ("Andre", "Timot"));

    assert!(multiple_lifetimes());

    assert_eq!(tom.name, "Tom");
    assert_eq!(jane.name, "Jane");
    assert_eq!(tom.parent.unwrap().name, "Jane");
    assert_eq!(tom.parents_name(), Some("Jane"));
    assert_eq!(jane.parents_name(), None);

    assert_eq!(join_ages(vec_ages.iter()), vec![&Age(90), &Age(80), &Age(2)]);
    assert_eq!(join_ages(arr_ages.iter()), vec![&Age(90), &Age(80), &Age(2), &Age(45)]);
}

// - We are making a promise to the compiler that all of these things live for atleast the same scope.
// - We are not asking the compiler to "create a lifetime". We are just telling it to complain if we
//   don't do what we say we are doing.
// - Nor are you telling Rust to "allow" a binding to be available in a given named scope/lifetime.
// - Why? Because this allows Rust to ensure we cannot cause common memory allocation bugs. It does
//   this at compile time. It's a zero-cost abstraction because there is no runtime penalty.
// - It makes code look "uglier". But this is the wrong mindset for writing systems-level programs.
//   The emphasis here is on safety, not expressiveness.
// - When we say "'a", we are talking about a scope in the calling environment.
// - Question: Why can't Rust ensure/infer/elide the struct scenario? Surely any reference to a Parent
//   must *always* live for the same or a bigger scope???
//   - There is an open RFC for this
//   - It may be complex to implement and/or slow down compilation
//   - Eliding in more cases may prevent newcomer Rust programmers from ever encountering
//     lifetimes, which could have a negative impact in the long run. Pedagogy!
<commit_msg>Couple more experiments<commit_after>#[derive(PartialEq, Eq, Debug)]
struct Age(u8);

struct Person<'a> {
    name: &'static str,
    parent: Option<&'a Person<'a>>,
}

impl<'a> Person<'a> {
    fn new(name: &'static str, parent: Option<&'a Person<'a>>) -> Person<'a> {
        Person{name: name, parent: parent}
    }

    fn parents_name(&self) -> Option<&'static str> {
        match self.parent {
            Some(p) => Some(p.name),
            None => None,
        }
    }
}

// This one can be elided.
fn first_five<'a>(value: &'a String) -> &'a str {
    &value[..5]
}

// This cannot be elided because Rust doesn't know to use lifetime of "a" or "b".
fn double_first_five<'a>(a: &'a String, b: &'a String) -> (&'a str, &'a str) {
    (&a[..5], &b[..5])
}

// Output borrows generally must have an input value from which it can borrow. The exception is
// the static lifetime.
// Couldn't Rust infer from the body of the function that the borrows are from the static lifetime?
//   - I feel that Rust favours explicitness over terseness. A functions behaviour should be
//   encoded directly into it's signature.
fn output_only<'a>() -> (&'static u8, &'static u8) {
    static X: u8 = 8;
    static Y: u8 = 9;

    (&X, &Y)
}

// Here we are promising Rust that all of the borrowed u8's
// live for the same scope.
// Q: Why do I need a lifetime here?
fn join_ages<'a, T: Iterator>(iters: T) -> Vec<&'a Age>
        where T::Item: IntoIterator<Item=&'a Age> {
    iters.flat_map(|b| b.into_iter())
         .collect()
}

// This is not really necessary here. Both a and b could use the same lifetime
// as Rust only cares that a and b are available for the scope of this function.
// This could also be elided.
fn multi_lifetimes<'a, 'b>(a: &'a u8, b: &'b u8) -> bool {
    (a + b) > 10
}

fn multiple_lifetimes() -> bool {
    let a = &9;

    {
        let b = &9;

        multi_lifetimes(a, b)
    }
}

#[test]
fn it_works() {
    let jane = Person::new("Jane", None);
    let tom = Person::new("Tom", Some(&jane));
    let name = "Andrew".to_owned();
    let another = "Timothy".to_owned();
    let a = 43;
    let vec_ages = vec![vec![Age(90), Age(80)],
                        vec![Age(2)]];

    // Error: This cannot work because the lifetime of the borrow (Rob) is only valid for
    // the expression on the right-hand side. We must increase it's lifetime by giving it a name
    // via 'let'.
    //let bob = Person::new("Bob", Some(&Person::new("Rob", None)));

    // If we swap these two lines around then this will not compile because the lifetime of Mary
    // would be less than that of Bob.
    let mary = Person::new("Mary", None);
    let mut bob = Person::new("Bob", None);

    bob.parent = Some(&mary);

    let arr_ages = vec![[Age(90), Age(80)],
                        [Age(2), Age(45)]];

    assert_eq!(output_only(), (&8, &9));

    assert_eq!(first_five(&name), "Andre");
    assert_eq!(double_first_five(&name, &another), ("Andre", "Timot"));

    assert!(multiple_lifetimes());

    assert_eq!(tom.name, "Tom");
    assert_eq!(jane.name, "Jane");
    assert_eq!(tom.parent.unwrap().name, "Jane");
    assert_eq!(tom.parents_name(), Some("Jane"));
    assert_eq!(jane.parents_name(), None);

    assert_eq!(join_ages(vec_ages.iter()), vec![&Age(90), &Age(80), &Age(2)]);
    assert_eq!(join_ages(arr_ages.iter()), vec![&Age(90), &Age(80), &Age(2), &Age(45)]);
}

// - We are making a promise to the compiler that all of these things live for atleast the same scope.
// - We are not asking the compiler to "create a lifetime". We are just telling it to complain if we
//   don't do what we say we are doing.
// - Nor are you telling Rust to "allow" a binding to be available in a given named scope/lifetime.
// - Why? Because this allows Rust to ensure we cannot cause common memory allocation bugs. It does
//   this at compile time. It's a zero-cost abstraction because there is no runtime penalty.
// - It makes code look "uglier". But this is the wrong mindset for writing systems-level programs.
//   The emphasis here is on safety, not expressiveness.
// - When we say "'a", we are talking about a scope in the calling environment.
// - Question: Why can't Rust ensure/infer/elide the struct scenario? Surely any reference to a Parent
//   must *always* live for the same or a bigger scope???
//   - There is an open RFC for this
//   - It may be complex to implement and/or slow down compilation
//   - Eliding in more cases may prevent newcomer Rust programmers from ever encountering
//     lifetimes, which could have a negative impact in the long run. Pedagogy!
<|endoftext|>