<commit_before>use image;
use image::RgbaImage;

use glium::{DisplayBuild, VertexBuffer, Program, DrawParameters, Display, Surface};
use glium::{IndexBuffer, Frame, Blend};
use glium::index::PrimitiveType;
use glium::texture::{Texture2d, RawImage2d};
use glium::glutin::WindowBuilder;

use std::path::Path;
use std::ops::{Deref, DerefMut};

use super::{DrawResult, TextureResult};

#[derive(Copy, Clone)]
struct Vertex {
    position  : [f32; 2],
    tex_coords: [f32; 2]
}

implement_vertex!(Vertex, position, tex_coords);

impl Vertex{
    #[inline]
    fn new(position: [f32; 2], tex_coords: [f32; 2]) -> Self{
        Vertex{
            position  : position,
            tex_coords: tex_coords,
        }
    }
}

/// A 2D texture that is ready to be drawn
pub struct Texture{
    tex: Texture2d,
    vertex_buffer: VertexBuffer<Vertex>,
}

impl Texture {
    #[inline]
    /// Creates a `Texture` from a PNG-encoded byte slice
    pub fn from_png_bytes(display: &Display, bytes: &[u8]) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::load_from_memory_with_format(bytes, image::PNG)
            ).to_rgba()
        )
    }
    #[inline]
    /// Creates a `Texture` from a file
    pub fn from_file<P: AsRef<Path>>(display: &Display, path: P) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::open(path)
            ).to_rgba()
        )
    }

    /// Creates a `Texture` from an `image::RgbaImage`
    pub fn new(display: &Display, image: RgbaImage) -> TextureResult<Texture>{
        let (width, height) = image.dimensions();
        let image = RawImage2d::from_raw_rgba_reversed(image.into_raw(), (width, height));

        let (w, h) = (width as f32 / 2.0, height as f32 / 2.0);

        let vb = try!(VertexBuffer::new(display, &[
            Vertex::new([-w, -h], [0.0, 0.0]),
            Vertex::new([ w, -h], [1.0, 0.0]),
            Vertex::new([ w,  h], [1.0, 1.0]),
            Vertex::new([-w,  h], [0.0, 1.0])
        ]));

        Ok(Texture {
            tex: try!(Texture2d::new(display, image)),
            vertex_buffer: vb,
        })
    }
}

/// Loads a texture, by loading the bytes at compile-time
#[macro_export]
macro_rules! include_texture {
    ($graphics:expr, $texture:tt) => {
        $crate::Texture::from_png_bytes(&$graphics, include_bytes!($texture))
    };
}

/// Contains the display and handles most of the graphics
pub struct Graphics<'a> {
    display: Display,
    program: Program,
    h_size : (f32, f32),
    indices: IndexBuffer<u8>,
    params : DrawParameters<'a>
}

impl<'a> Graphics<'a> {
    /// Creates a new `Graphics` from a `Display` made using the arguments
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        Self::from_display(
            WindowBuilder::new()
                .with_title(title.to_string())
                .with_dimensions(width, height)
                .with_vsync()
                .build_glium().expect("Failed to build the window")
        )
    }

    /// Creates a new `Graphics` instance using the given display
    pub fn from_display(display: Display) -> Self {
        let (w, h) = display.get_window().unwrap().get_inner_size().unwrap();
        let (w, h) = (w as f32 / 2.0, h as f32 / 2.0);

        let params = DrawParameters{
            blend : Blend::alpha_blending(),
            .. Default::default()
        };

        let indices = IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u8, 1, 3, 2]).unwrap();

        Graphics{
            // Unwrap should be safe
            program: Program::from_source(&display, include_str!("shaders/texture.vs"), include_str!("shaders/texture.fs"), None).unwrap(),
            display: display,
            params : params,
            indices: indices,
            h_size : (w, h)
        }
    }

    #[inline]
    /// Returns half of the size of the window
    pub fn get_h_size(&self) -> (f32, f32){
        self.h_size
    }

    #[inline]
    /// Returns a `Texture` created from a PNG-encoded byte slice
    /// DEPRECATED: Use `Texture::from_png_bytes`
    pub fn load_texture_from_bytes(&self, bytes: &[u8]) -> TextureResult<Texture> {
        Texture::from_png_bytes(&self.display, bytes)
    }

    #[inline]
    /// Returns a `Texture` created from a file
    /// DEPRECATED: Use `Texture::from_file`
    pub fn load_texture_from_file<P: AsRef<Path>>(&self, path: P) -> TextureResult<Texture> {
        Texture::from_file(&self.display, path)
    }
}

#[inline(always)]
// This function is only used inside `FrameInfo` when Event::Resized occurs
pub fn resize(graphics: &mut Graphics, width: u32, height: u32){
    graphics.h_size = (width as f32 / 2.0, height as f32 / 2.0);
}

fn draw(target: &mut Frame, graphics: &Graphics, texture: &Texture, matrix: [[f32; 4]; 4]) -> DrawResult<()>{
    let uniforms = uniform! {
        h_size: graphics.h_size,
        tex   : &texture.tex,
        matrix: matrix
    };

    target.draw(&texture.vertex_buffer, &graphics.indices, &graphics.program, &uniforms, &graphics.params)
}

impl<'a> Deref for Graphics<'a>{
    type Target = Display;

    #[inline]
    fn deref(&self) -> &Display{
        &self.display
    }
}

/// Provides functionality for drawing.
/// Can also be dereferenced into a `glium::Frame`.
pub struct Drawer<'a>{
    target: Frame,
    /// Reference to the draw instance
    pub graphics: &'a Graphics<'a>
}

impl<'a> Drawer<'a>{
    #[inline]
    /// Creates a new `Drawer` to draw next frame
    pub fn new(graphics: &'a Graphics<'a>) -> Self{
        let target = graphics.draw();
        Drawer{
            target: target,
            graphics: graphics
        }
    }

    #[inline]
    /// Clears the screen with the specified colour
    pub fn clear(&mut self, red: f32, green: f32, blue: f32){
        self.clear_color(red, green, blue, 1.)
    }

    /// Draws a texture onto the screen
    pub fn draw_texture(&mut self, texture: &Texture, x: f32, y: f32, rotation: f32) -> DrawResult<()>{
        let (sin, cos)  = rotation.sin_cos();

        let matrix = [
            [ cos, sin, 0.0, 0.0],
            [-sin, cos, 0.0, 0.0],
            [ 0.0, 0.0, 1.0, 0.0],
            [   x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }

    /// Draws a texture onto the screen without rotation
    pub fn draw_texture_rigid(&mut self, texture: &Texture, x: f32, y: f32) -> DrawResult<()>{
        let matrix = [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [  x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }
}

impl<'a> Deref for Drawer<'a>{
    type Target = Frame;
    #[inline]
    fn deref(&self) -> &Frame{
        &self.target
    }
}

impl<'a> DerefMut for Drawer<'a>{
    #[inline]
    fn deref_mut(&mut self) -> &mut Frame{
        &mut self.target
    }
}

impl<'a> Drop for Drawer<'a>{
    #[inline]
    fn drop(&mut self){
        self.target.set_finish().unwrap()
    }
}

/// Descibes objects that can be drawn to the screen
pub trait Draw {
    /// Draws itself to the screen
    fn draw(&self, &mut Drawer) -> DrawResult<()>;
}
<commit_msg>Remove deprecated functions<commit_after>use image;
use image::RgbaImage;

use glium::{DisplayBuild, VertexBuffer, Program, DrawParameters, Display, Surface};
use glium::{IndexBuffer, Frame, Blend};
use glium::index::PrimitiveType;
use glium::texture::{Texture2d, RawImage2d};
use glium::glutin::WindowBuilder;

use std::path::Path;
use std::ops::{Deref, DerefMut};

use super::{DrawResult, TextureResult};

#[derive(Copy, Clone)]
struct Vertex {
    position  : [f32; 2],
    tex_coords: [f32; 2]
}

implement_vertex!(Vertex, position, tex_coords);

impl Vertex{
    #[inline]
    fn new(position: [f32; 2], tex_coords: [f32; 2]) -> Self{
        Vertex{
            position  : position,
            tex_coords: tex_coords,
        }
    }
}

/// A 2D texture that is ready to be drawn
pub struct Texture{
    tex: Texture2d,
    vertex_buffer: VertexBuffer<Vertex>,
}

impl Texture {
    #[inline]
    /// Creates a `Texture` from a PNG-encoded byte slice
    pub fn from_png_bytes(display: &Display, bytes: &[u8]) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::load_from_memory_with_format(bytes, image::PNG)
            ).to_rgba()
        )
    }
    #[inline]
    /// Creates a `Texture` from a file
    pub fn from_file<P: AsRef<Path>>(display: &Display, path: P) -> TextureResult<Texture>{
        Texture::new(display,
            try!(
                image::open(path)
            ).to_rgba()
        )
    }

    /// Creates a `Texture` from an `image::RgbaImage`
    pub fn new(display: &Display, image: RgbaImage) -> TextureResult<Texture>{
        let (width, height) = image.dimensions();
        let image = RawImage2d::from_raw_rgba_reversed(image.into_raw(), (width, height));

        let (w, h) = (width as f32 / 2.0, height as f32 / 2.0);

        let vb = try!(VertexBuffer::new(display, &[
            Vertex::new([-w, -h], [0.0, 0.0]),
            Vertex::new([ w, -h], [1.0, 0.0]),
            Vertex::new([ w,  h], [1.0, 1.0]),
            Vertex::new([-w,  h], [0.0, 1.0])
        ]));

        Ok(Texture {
            tex: try!(Texture2d::new(display, image)),
            vertex_buffer: vb,
        })
    }
}

/// Loads a texture, by loading the bytes at compile-time
#[macro_export]
macro_rules! include_texture {
    ($graphics:expr, $texture:tt) => {
        $crate::Texture::from_png_bytes(&$graphics, include_bytes!($texture))
    };
}

/// Contains the display and handles most of the graphics
pub struct Graphics<'a> {
    display: Display,
    program: Program,
    h_size : (f32, f32),
    indices: IndexBuffer<u8>,
    params : DrawParameters<'a>
}

impl<'a> Graphics<'a> {
    /// Creates a new `Graphics` from a `Display` made using the arguments
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        Self::from_display(
            WindowBuilder::new()
                .with_title(title.to_string())
                .with_dimensions(width, height)
                .with_vsync()
                .build_glium().expect("Failed to build the window")
        )
    }

    /// Creates a new `Graphics` instance using the given display
    pub fn from_display(display: Display) -> Self {
        let (w, h) = display.get_window().unwrap().get_inner_size().unwrap();
        let (w, h) = (w as f32 / 2.0, h as f32 / 2.0);

        let params = DrawParameters{
            blend : Blend::alpha_blending(),
            .. Default::default()
        };

        let indices = IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u8, 1, 3, 2]).unwrap();

        Graphics{
            // Unwrap should be safe
            program: Program::from_source(&display, include_str!("shaders/texture.vs"), include_str!("shaders/texture.fs"), None).unwrap(),
            display: display,
            params : params,
            indices: indices,
            h_size : (w, h)
        }
    }

    #[inline]
    /// Returns half of the size of the window
    pub fn get_h_size(&self) -> (f32, f32){
        self.h_size
    }
}

#[inline(always)]
// This function is only used inside `FrameInfo` when Event::Resized occurs
pub fn resize(graphics: &mut Graphics, width: u32, height: u32){
    graphics.h_size = (width as f32 / 2.0, height as f32 / 2.0);
}

fn draw(target: &mut Frame, graphics: &Graphics, texture: &Texture, matrix: [[f32; 4]; 4]) -> DrawResult<()>{
    let uniforms = uniform! {
        h_size: graphics.h_size,
        tex   : &texture.tex,
        matrix: matrix
    };

    target.draw(&texture.vertex_buffer, &graphics.indices, &graphics.program, &uniforms, &graphics.params)
}

impl<'a> Deref for Graphics<'a>{
    type Target = Display;

    #[inline]
    fn deref(&self) -> &Display{
        &self.display
    }
}

/// Provides functionality for drawing.
/// Can also be dereferenced into a `glium::Frame`.
pub struct Drawer<'a>{
    target: Frame,
    /// Reference to the draw instance
    pub graphics: &'a Graphics<'a>
}

impl<'a> Drawer<'a>{
    #[inline]
    /// Creates a new `Drawer` to draw next frame
    pub fn new(graphics: &'a Graphics<'a>) -> Self{
        let target = graphics.draw();
        Drawer{
            target: target,
            graphics: graphics
        }
    }

    #[inline]
    /// Clears the screen with the specified colour
    pub fn clear(&mut self, red: f32, green: f32, blue: f32){
        self.clear_color(red, green, blue, 1.)
    }

    /// Draws a texture onto the screen
    pub fn draw_texture(&mut self, texture: &Texture, x: f32, y: f32, rotation: f32) -> DrawResult<()>{
        let (sin, cos)  = rotation.sin_cos();

        let matrix = [
            [ cos, sin, 0.0, 0.0],
            [-sin, cos, 0.0, 0.0],
            [ 0.0, 0.0, 1.0, 0.0],
            [   x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }

    /// Draws a texture onto the screen without rotation
    pub fn draw_texture_rigid(&mut self, texture: &Texture, x: f32, y: f32) -> DrawResult<()>{
        let matrix = [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [  x,   y, 0.0, 1.0],
        ];

        draw(self, self.graphics, texture, matrix)
    }
}

impl<'a> Deref for Drawer<'a>{
    type Target = Frame;
    #[inline]
    fn deref(&self) -> &Frame{
        &self.target
    }
}

impl<'a> DerefMut for Drawer<'a>{
    #[inline]
    fn deref_mut(&mut self) -> &mut Frame{
        &mut self.target
    }
}

impl<'a> Drop for Drawer<'a>{
    #[inline]
    fn drop(&mut self){
        self.target.set_finish().unwrap()
    }
}

/// Descibes objects that can be drawn to the screen
pub trait Draw {
    /// Draws itself to the screen
    fn draw(&self, &mut Drawer) -> DrawResult<()>;
}
<|endoftext|>


<commit_before>use super::cell::*;
use super::fluid::*;
use itertools::Itertools;
use std::mem;
use rand::{Isaac64Rng, Rng};
use noise::{Brownian2, perlin2};

const SPAWN_RATE: f64 = 1.0;
const CONSUMPTION: f64 = 0.02;
const SURVIVAL_THRESHOLD: f64 = 0.1;
const INHALE_CAP: usize = 100;

#[derive(Debug, Clone)]
struct Mate {
    mate: (usize, usize),
    source: (usize, usize),
}

#[derive(Debug)]
struct Delta {
    movement_attempts: Vec<(usize, usize)>,
    mate_attempts: Vec<Mate>,
}

pub struct Hex {
    pub solution: Solution,
    pub cell: Option<Cell>,
    pub decision: Option<Decision>,
    delta: Delta,
}

impl Hex {
    pub fn color(&self) -> [f32; 4] {
        [0.25 * self.solution.fluids[1] as f32, 0.0, 0.25 * self.solution.fluids[0] as f32, 1.0]
    }
}

pub struct Grid {
    pub spawning: bool,
    pub width: usize,
    pub height: usize,
    tiles: Vec<Hex>,
}

impl Grid {
    pub fn new(width: usize, height: usize, rng: &mut Isaac64Rng) -> Self {
        Grid {
            spawning: true,
            width: width,
            height: height,
            tiles: randomizing_vec(width, height, rng),
        }
    }

    pub fn randomize(&mut self, rng: &mut Isaac64Rng) {
        self.tiles = randomizing_vec(self.width, self.height, rng);
    }

    pub fn hex(&self, x: usize, y: usize) -> &Hex {
        &self.tiles[x + y * self.width]
    }

    pub fn hex_mut(&mut self, x: usize, y: usize) -> &mut Hex {
        &mut self.tiles[x + y * self.width]
    }

    fn hex_and_neighbors(&mut self, x: usize, y: usize) -> (&mut Hex, [&Hex; 6]) {
        (unsafe { mem::transmute(self.hex_mut(x, y)) },
         if y % 2 == 0 {
            [// UpRight
             self.hex((x + self.width + 1) % self.width,
                      (y + self.height - 1) % self.height),
             // UpLeft
             self.hex(x, (y + self.height - 1) % self.height),
             // Left
             self.hex((x + self.width - 1) % self.width, y),
             // DownLeft
             self.hex(x, (y + self.height + 1) % self.height),
             // DownRight
             self.hex((x + self.width + 1) % self.width,
                      (y + self.height + 1) % self.height),
             // Right
             self.hex((x + self.width + 1) % self.width, y)]
        } else {
            [// UpRight
             self.hex(x, (y + self.height - 1) % self.height),
             // UpLeft
             self.hex((x + self.width - 1) % self.width,
                      (y + self.height - 1) % self.height),
             // Left
             self.hex((x + self.width - 1) % self.width, y),
             // DownLeft
             self.hex((x + self.width - 1) % self.width,
                      (y + self.height + 1) % self.height),
             // DownRight
             self.hex(x, (y + self.height + 1) % self.height),
             // Right
             self.hex((x + self.width + 1) % self.width, y)]
        })
    }

    pub fn cycle(&mut self, rng: &mut Isaac64Rng) {
        if self.spawning {
            self.cycle_spawn(rng);
        }
        self.cycle_cells();
        self.cycle_decisions(rng);
        self.cycle_fluids();
        self.cycle_death();
    }

    fn cycle_spawn(&mut self, rng: &mut Isaac64Rng) {
        if rng.next_f64() < SPAWN_RATE {
            self.tiles[rng.gen_range(0, self.width * self.height)].cell = Some(Cell::new(rng));
        }
    }

    fn cycle_cells(&mut self) {
        for x in 0..self.width {
            for y in 0..self.height {
                let (this, neighbors) = self.hex_and_neighbors(x, y);
                this.decision = if let Some(ref mut this_cell) = this.cell {
                    let neighbor_presents = [neighbors[0].cell.is_some(),
                                             neighbors[1].cell.is_some(),
                                             neighbors[2].cell.is_some(),
                                             neighbors[3].cell.is_some(),
                                             neighbors[4].cell.is_some(),
                                             neighbors[5].cell.is_some()];

                    Some(this_cell.decide([&this.solution.fluids,
                                           &neighbors[0].solution.fluids,
                                           &neighbors[1].solution.fluids,
                                           &neighbors[2].solution.fluids,
                                           &neighbors[3].solution.fluids,
                                           &neighbors[4].solution.fluids,
                                           &neighbors[5].solution.fluids],
                                          &neighbor_presents))
                } else {
                    None
                }
            }
        }
    }

    fn cycle_decisions(&mut self, rng: &mut Isaac64Rng) {
        // Compute the deltas resulting from the decision.
        for x in 0..self.width {
            for y in 0..self.height {
                let (width, height) = (self.width, self.height);
                let (this, neighbors) = self.hex_and_neighbors(x, y);
                // Clear the movements from the previous cycle.
                this.delta.movement_attempts.clear();
                this.delta.mate_attempts.clear();
                this.solution.coefficients = if let Some(ref decision) = this.decision {
                    decision.coefficients
                } else {
                    // Set the diffusion coefficients to the normal values.
                    [0.5, 1.0]
                };

                // Only add movements here if no cell is present.
                if this.cell.is_none() {
                    // Add any neighbor movements to the movement_attempts vector.
                    for (n, &facing) in neighbors.iter().zip(&[Direction::DownLeft,
                                                               Direction::DownRight,
                                                               Direction::Right,
                                                               Direction::UpRight,
                                                               Direction::UpLeft,
                                                               Direction::Left]) {
                        match n.decision {
                            Some(Decision { choice: Choice::Move(direction), .. }) => {
                                // It attempted to move into this hex cell.
                                if facing == direction {
                                    this.delta
                                        .movement_attempts
                                        .push(in_direction(x, y, width, height, facing.flip()));

                                    // No need to continue if we reach 2 attempts.
                                    if this.delta.movement_attempts.len() == 2 {
                                        break;
                                    }
                                }
                            }
                            Some(Decision { choice: Choice::Divide { mate, spawn }, .. }) => {
                                // It attempted to spawn into this hex cell.
                                if facing == spawn {
                                    let source = in_direction(x, y, width, height, facing.flip());;
                                    this.delta
                                        .mate_attempts
                                        .push(Mate {
                                            mate: in_direction(source.0,
                                                               source.1,
                                                               width,
                                                               height,
                                                               mate),
                                            source: source,
                                        });

                                    // No need to continue if we reach 2 attempts.
                                    if this.delta.mate_attempts.len() == 2 {
                                        break;
                                    }
                                }
                            }
                            _ => {}
                        }
                    }
                }
            }
        }

        // Perform the deltas.
        for x in 0..self.width {
            for y in 0..self.height {
                // Handle movement.
                if self.hex(x, y).delta.movement_attempts.len() == 1 {
                    let from_coord = self.hex(x, y).delta.movement_attempts[0];
                    self.hex_mut(x, y).cell = self.hex_mut(from_coord.0, from_coord.1).cell.take();
                    // Handle mating.
                } else if self.hex(x, y).delta.mate_attempts.len() == 1 {
                    let mate = self.hex(x, y).delta.mate_attempts[0].clone();
                    self.hex_mut(x, y).cell = if mate.mate == (x, y) {
                        Some(self.hex(mate.source.0, mate.source.1)
                            .cell
                            .as_ref()
                            .unwrap()
                            .divide(rng))
                    } else {
                        if self.hex(mate.mate.0, mate.mate.1).cell.is_some() {
                            Some(self.hex(mate.source.0, mate.source.1)
                                .cell
                                .as_ref()
                                .unwrap()
                                .mate(&self.hex(mate.mate.0, mate.mate.1)
                                          .cell
                                          .as_ref()
                                          .unwrap(),
                                      rng))
                        } else {
                            None
                        }
                    };
                }

                // Clear the decisions.
                self.hex_mut(x, y).decision = None;
            }
        }
    }

    fn cycle_fluids(&mut self) {
        // Then update diffusion.
        for x in 0..self.width {
            for y in 0..self.height {
                let (this, neighbors) = self.hex_and_neighbors(x, y);

                for n in &neighbors {
                    this.solution.diffuse_from(&n.solution);
                }
            }
        }

        // Finish the cycle.
        for hex in &mut self.tiles {
            hex.solution.end_cycle();
        }
    }

    fn cycle_death(&mut self) {
        // Finish the cycle.
        for hex in &mut self.tiles {
            if hex.cell.is_some() {
                if hex.solution.fluids[0] <= CONSUMPTION {
                    if hex.cell.as_ref().unwrap().inhale != 0 {
                        hex.cell.as_mut().unwrap().inhale -= 1;
                    } else {
                        hex.cell = None;
                    }
                } else {
                    hex.solution.fluids[0] -= CONSUMPTION;
                    if hex.solution.fluids[0] < SURVIVAL_THRESHOLD {
                        if hex.cell.as_ref().unwrap().inhale != 0 {
                            hex.cell.as_mut().unwrap().inhale -= 1;
                        } else {
                            hex.cell = None;
                        }
                    } else {
                        if hex.cell.as_ref().unwrap().inhale < INHALE_CAP {
                            hex.cell.as_mut().unwrap().inhale += 1;
                        }
                    }
                }
            }
        }
    }
}

fn randomizing_vec(width: usize, height: usize, rng: &mut Isaac64Rng) -> Vec<Hex> {
    let seeds = [rng.gen(), rng.gen()];
    let noise = Brownian2::new(perlin2, 4).wavelength(32.0);
    (0..height)
        .cartesian_product((0..width))
        .map(|(x, y)| {
            Hex {
                solution: Solution::new([noise.apply(&seeds[0], &[x as f64, y as f64]), 1.0],
                                        [0.5, 1.0]),
                cell: None,
                decision: None,
                delta: Delta {
                    movement_attempts: Vec::with_capacity(6),
                    mate_attempts: Vec::with_capacity(6),
                },
            }
        })
        .collect_vec()
}

fn in_direction(x: usize,
                y: usize,
                width: usize,
                height: usize,
                direction: Direction)
                -> (usize, usize) {
    let diff = direction.delta(y % 2 == 0);
    (((width + x) as isize + diff.0) as usize % width,
     ((height + y) as isize + diff.1) as usize % height)
}
<commit_msg>increase difficulty level<commit_after>use super::cell::*;
use super::fluid::*;
use itertools::Itertools;
use std::mem;
use rand::{Isaac64Rng, Rng};
use noise::{Brownian2, perlin2};

const SPAWN_RATE: f64 = 0.2;
const CONSUMPTION: f64 = 0.03;
const SURVIVAL_THRESHOLD: f64 = 0.05;
const INHALE_CAP: usize = 10;

#[derive(Debug, Clone)]
struct Mate {
    mate: (usize, usize),
    source: (usize, usize),
}

#[derive(Debug)]
struct Delta {
    movement_attempts: Vec<(usize, usize)>,
    mate_attempts: Vec<Mate>,
}

pub struct Hex {
    pub solution: Solution,
    pub cell: Option<Cell>,
    pub decision: Option<Decision>,
    delta: Delta,
}

impl Hex {
    pub fn color(&self) -> [f32; 4] {
        [0.25 * self.solution.fluids[1] as f32, 0.0, 0.25 * self.solution.fluids[0] as f32, 1.0]
    }
}

pub struct Grid {
    pub spawning: bool,
    pub width: usize,
    pub height: usize,
    tiles: Vec<Hex>,
}

impl Grid {
    pub fn new(width: usize, height: usize, rng: &mut Isaac64Rng) -> Self {
        Grid {
            spawning: true,
            width: width,
            height: height,
            tiles: randomizing_vec(width, height, rng),
        }
    }

    pub fn randomize(&mut self, rng: &mut Isaac64Rng) {
        self.tiles = randomizing_vec(self.width, self.height, rng);
    }

    pub fn hex(&self, x: usize, y: usize) -> &Hex {
        &self.tiles[x + y * self.width]
    }

    pub fn hex_mut(&mut self, x: usize, y: usize) -> &mut Hex {
        &mut self.tiles[x + y * self.width]
    }

    fn hex_and_neighbors(&mut self, x: usize, y: usize) -> (&mut Hex, [&Hex; 6]) {
        (unsafe { mem::transmute(self.hex_mut(x, y)) },
         if y % 2 == 0 {
            [// UpRight
             self.hex((x + self.width + 1) % self.width,
                      (y + self.height - 1) % self.height),
             // UpLeft
             self.hex(x, (y + self.height - 1) % self.height),
             // Left
             self.hex((x + self.width - 1) % self.width, y),
             // DownLeft
             self.hex(x, (y + self.height + 1) % self.height),
             // DownRight
             self.hex((x + self.width + 1) % self.width,
                      (y + self.height + 1) % self.height),
             // Right
             self.hex((x + self.width + 1) % self.width, y)]
        } else {
            [// UpRight
             self.hex(x, (y + self.height - 1) % self.height),
             // UpLeft
             self.hex((x + self.width - 1) % self.width,
                      (y + self.height - 1) % self.height),
             // Left
             self.hex((x + self.width - 1) % self.width, y),
             // DownLeft
             self.hex((x + self.width - 1) % self.width,
                      (y + self.height + 1) % self.height),
             // DownRight
             self.hex(x, (y + self.height + 1) % self.height),
             // Right
             self.hex((x + self.width + 1) % self.width, y)]
        })
    }

    pub fn cycle(&mut self, rng: &mut Isaac64Rng) {
        if self.spawning {
            self.cycle_spawn(rng);
        }
        self.cycle_cells();
        self.cycle_decisions(rng);
        self.cycle_fluids();
        self.cycle_death();
    }

    fn cycle_spawn(&mut self, rng: &mut Isaac64Rng) {
        if rng.next_f64() < SPAWN_RATE {
            self.tiles[rng.gen_range(0, self.width * self.height)].cell = Some(Cell::new(rng));
        }
    }

    fn cycle_cells(&mut self) {
        for x in 0..self.width {
            for y in 0..self.height {
                let (this, neighbors) = self.hex_and_neighbors(x, y);
                this.decision = if let Some(ref mut this_cell) = this.cell {
                    let neighbor_presents = [neighbors[0].cell.is_some(),
                                             neighbors[1].cell.is_some(),
                                             neighbors[2].cell.is_some(),
                                             neighbors[3].cell.is_some(),
                                             neighbors[4].cell.is_some(),
                                             neighbors[5].cell.is_some()];

                    Some(this_cell.decide([&this.solution.fluids,
                                           &neighbors[0].solution.fluids,
                                           &neighbors[1].solution.fluids,
                                           &neighbors[2].solution.fluids,
                                           &neighbors[3].solution.fluids,
                                           &neighbors[4].solution.fluids,
                                           &neighbors[5].solution.fluids],
                                          &neighbor_presents))
                } else {
                    None
                }
            }
        }
    }

    fn cycle_decisions(&mut self, rng: &mut Isaac64Rng) {
        // Compute the deltas resulting from the decision.
        for x in 0..self.width {
            for y in 0..self.height {
                let (width, height) = (self.width, self.height);
                let (this, neighbors) = self.hex_and_neighbors(x, y);
                // Clear the movements from the previous cycle.
                this.delta.movement_attempts.clear();
                this.delta.mate_attempts.clear();
                this.solution.coefficients = if let Some(ref decision) = this.decision {
                    decision.coefficients
                } else {
                    // Set the diffusion coefficients to the normal values.
                    [0.5, 1.0]
                };

                // Only add movements here if no cell is present.
                if this.cell.is_none() {
                    // Add any neighbor movements to the movement_attempts vector.
                    for (n, &facing) in neighbors.iter().zip(&[Direction::DownLeft,
                                                               Direction::DownRight,
                                                               Direction::Right,
                                                               Direction::UpRight,
                                                               Direction::UpLeft,
                                                               Direction::Left]) {
                        match n.decision {
                            Some(Decision { choice: Choice::Move(direction), .. }) => {
                                // It attempted to move into this hex cell.
                                if facing == direction {
                                    this.delta
                                        .movement_attempts
                                        .push(in_direction(x, y, width, height, facing.flip()));

                                    // No need to continue if we reach 2 attempts.
                                    if this.delta.movement_attempts.len() == 2 {
                                        break;
                                    }
                                }
                            }
                            Some(Decision { choice: Choice::Divide { mate, spawn }, .. }) => {
                                // It attempted to spawn into this hex cell.
                                if facing == spawn {
                                    let source = in_direction(x, y, width, height, facing.flip());;
                                    this.delta
                                        .mate_attempts
                                        .push(Mate {
                                            mate: in_direction(source.0,
                                                               source.1,
                                                               width,
                                                               height,
                                                               mate),
                                            source: source,
                                        });

                                    // No need to continue if we reach 2 attempts.
                                    if this.delta.mate_attempts.len() == 2 {
                                        break;
                                    }
                                }
                            }
                            _ => {}
                        }
                    }
                }
            }
        }

        // Perform the deltas.
        for x in 0..self.width {
            for y in 0..self.height {
                // Handle movement.
                if self.hex(x, y).delta.movement_attempts.len() == 1 {
                    let from_coord = self.hex(x, y).delta.movement_attempts[0];
                    self.hex_mut(x, y).cell = self.hex_mut(from_coord.0, from_coord.1).cell.take();
                    // Handle mating.
                } else if self.hex(x, y).delta.mate_attempts.len() == 1 {
                    let mate = self.hex(x, y).delta.mate_attempts[0].clone();
                    self.hex_mut(x, y).cell = if mate.mate == (x, y) {
                        Some(self.hex(mate.source.0, mate.source.1)
                            .cell
                            .as_ref()
                            .unwrap()
                            .divide(rng))
                    } else {
                        if self.hex(mate.mate.0, mate.mate.1).cell.is_some() {
                            Some(self.hex(mate.source.0, mate.source.1)
                                .cell
                                .as_ref()
                                .unwrap()
                                .mate(&self.hex(mate.mate.0, mate.mate.1)
                                          .cell
                                          .as_ref()
                                          .unwrap(),
                                      rng))
                        } else {
                            None
                        }
                    };
                }

                // Clear the decisions.
                self.hex_mut(x, y).decision = None;
            }
        }
    }

    fn cycle_fluids(&mut self) {
        // Then update diffusion.
        for x in 0..self.width {
            for y in 0..self.height {
                let (this, neighbors) = self.hex_and_neighbors(x, y);

                for n in &neighbors {
                    this.solution.diffuse_from(&n.solution);
                }
            }
        }

        // Finish the cycle.
        for hex in &mut self.tiles {
            hex.solution.end_cycle();
        }
    }

    fn cycle_death(&mut self) {
        // Finish the cycle.
        for hex in &mut self.tiles {
            if hex.cell.is_some() {
                if hex.solution.fluids[0] <= CONSUMPTION {
                    if hex.cell.as_ref().unwrap().inhale != 0 {
                        hex.cell.as_mut().unwrap().inhale -= 1;
                    } else {
                        hex.cell = None;
                    }
                } else {
                    hex.solution.fluids[0] -= CONSUMPTION;
                    if hex.solution.fluids[0] < SURVIVAL_THRESHOLD {
                        if hex.cell.as_ref().unwrap().inhale != 0 {
                            hex.cell.as_mut().unwrap().inhale -= 1;
                        } else {
                            hex.cell = None;
                        }
                    } else {
                        if hex.cell.as_ref().unwrap().inhale < INHALE_CAP {
                            hex.cell.as_mut().unwrap().inhale += 1;
                        }
                    }
                }
            }
        }
    }
}

fn randomizing_vec(width: usize, height: usize, rng: &mut Isaac64Rng) -> Vec<Hex> {
    let seeds = [rng.gen(), rng.gen()];
    let noise = Brownian2::new(perlin2, 4).wavelength(32.0);
    (0..height)
        .cartesian_product((0..width))
        .map(|(x, y)| {
            Hex {
                solution: Solution::new([noise.apply(&seeds[0], &[x as f64, y as f64]), 1.0],
                                        [0.5, 1.0]),
                cell: None,
                decision: None,
                delta: Delta {
                    movement_attempts: Vec::with_capacity(6),
                    mate_attempts: Vec::with_capacity(6),
                },
            }
        })
        .collect_vec()
}

fn in_direction(x: usize,
                y: usize,
                width: usize,
                height: usize,
                direction: Direction)
                -> (usize, usize) {
    let diff = direction.delta(y % 2 == 0);
    (((width + x) as isize + diff.0) as usize % width,
     ((height + y) as isize + diff.1) as usize % height)
}
<|endoftext|>


<commit_before>use std::{
    error::Error,
    fmt::{self, Display},
    ops::{Index, IndexMut},
    str::FromStr,
};

use cell::Cell;

mod cell;

/// An error returned when parsing a [`Grid`] from a string failed.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ParseGridError {
    /// The grid is empty.
    Empty,
    /// The grid is not rectangular.
    NotRectangular {
        /// Line on which the error occured.
        line: usize,
        /// Number of cells found.
        found: usize,
        /// Number of cells expected.
        expected: usize,
    },
}

impl Error for ParseGridError {}

impl Display for ParseGridError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseGridError::Empty => "grid is empty".fmt(f),
            ParseGridError::NotRectangular { line, found, expected } => {
                write!(f, "grid is not rectangular (line {line}, expected {expected} cells, found {found})")
            }
        }
    }
}

/// A rectangular grid of [`Cell`]s for the Game of Life.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Grid {
    /// Array storing the cells in row-major order.
    cells: Box<[Cell]>,
    /// Number of rows in the grid.
    nrow: usize,
    /// Number of columns in the grid.
    ncol: usize,
}

impl FromStr for Grid {
    type Err = ParseGridError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use ParseGridError::{Empty, NotRectangular};

        let mut nrow = 0;
        let mut ncol = 0;
        let mut cells = Vec::with_capacity(s.len());
        for line in s.lines() {
            nrow += 1;
            let mut ncell = 0;
            for c in line.chars().filter(|c| !c.is_whitespace()) {
                ncell += 1;
                cells.push(match c {
                    '·' => Cell::new_dead(),
                    _ => Cell::new_alive(),
                });
            }
            if nrow == 1 {
                ncol = ncell;
            } else if ncell != ncol {
                return Err(NotRectangular { line: nrow, found: ncell, expected: ncol });
            }
        }
        if cells.is_empty() {
            return Err(Empty);
        }
        Ok(Self::from_parts(cells, (nrow, ncol)))
    }
}

impl Index<(usize, usize)> for Grid {
    type Output = Cell;

    fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
        &self.cells[i * self.ncol + j]
    }
}

impl IndexMut<(usize, usize)> for Grid {
    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut Self::Output {
        &mut self.cells[i * self.ncol + j]
    }
}

impl Display for Grid {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for row in self.cells.chunks(self.ncol) {
            for cell in row {
                if cell.alive {
                    write!(f, " X")?;
                } else {
                    write!(f, " ·")?;
                }
            }
            writeln!(f)?;
        }
        Ok(())
    }
}

impl Grid {
    /// Returns the vertical and horizontal dimensions of the grid.
    #[must_use]
    pub const fn dim(&self) -> (usize, usize) {
        (self.nrow, self.ncol)
    }

    /// Increments the time by one tick.
    ///
    /// Births and deaths happen simultaneously according to the rules
    /// of Conway's Game of Life, after which the grid contains
    /// the next generation.
    pub fn tick(&mut self) {
        for i in 0..self.nrow {
            for j in 0..self.ncol {
                let live_neighbours = self.live_neighbours((i, j));
                let cell = &mut self[(i, j)];
                if !cell.alive {
                    if live_neighbours == 3 {
                        cell.lives = true;
                    }
                } else if live_neighbours != 2 && live_neighbours != 3 {
                    cell.lives = false;
                }
            }
        }
        for cell in &mut *self.cells {
            cell.alive = cell.lives;
        }
    }
}

impl Grid {
    /// Creates a `Grid` from a vector of `Cell`s and a pair of dimensions.
    ///
    /// # Panics
    ///
    /// Panics if the number of cells is not `nrow * ncol`.
    #[must_use]
    fn from_parts(cells: Vec<Cell>, (nrow, ncol): (usize, usize)) -> Self {
        assert_eq!(cells.len(), nrow * ncol);
        Self { cells: cells.into_boxed_slice(), nrow, ncol }
    }

    /// Returns the number of living neighbours for a cell.
    #[must_use]
    fn live_neighbours(&self, (i, j): (usize, usize)) -> u8 {
        use std::cmp::min;

        let mut live_neighbours = 0_u8;
        for m in i.saturating_sub(1)..min(i + 2, self.nrow) {
            for n in j.saturating_sub(1)..min(j + 2, self.ncol) {
                if self[(m, n)].alive && (m != i || n != j) {
                    live_neighbours += 1;
                }
            }
        }
        live_neighbours
    }
}
<commit_msg>Rename `neighbours` to `neighbors`<commit_after>use std::{
    error::Error,
    fmt::{self, Display},
    ops::{Index, IndexMut},
    str::FromStr,
};

use cell::Cell;

mod cell;

/// An error returned when parsing a [`Grid`] from a string failed.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ParseGridError {
    /// The grid is empty.
    Empty,
    /// The grid is not rectangular.
    NotRectangular {
        /// Line on which the error occured.
        line: usize,
        /// Number of cells found.
        found: usize,
        /// Number of cells expected.
        expected: usize,
    },
}

impl Error for ParseGridError {}

impl Display for ParseGridError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseGridError::Empty => "grid is empty".fmt(f),
            ParseGridError::NotRectangular { line, found, expected } => {
                write!(f, "grid is not rectangular (line {line}, expected {expected} cells, found {found})")
            }
        }
    }
}

/// A rectangular grid of [`Cell`]s for the Game of Life.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Grid {
    /// Array storing the cells in row-major order.
    cells: Box<[Cell]>,
    /// Number of rows in the grid.
    nrow: usize,
    /// Number of columns in the grid.
    ncol: usize,
}

impl FromStr for Grid {
    type Err = ParseGridError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use ParseGridError::{Empty, NotRectangular};

        let mut nrow = 0;
        let mut ncol = 0;
        let mut cells = Vec::with_capacity(s.len());
        for line in s.lines() {
            nrow += 1;
            let mut ncell = 0;
            for c in line.chars().filter(|c| !c.is_whitespace()) {
                ncell += 1;
                cells.push(match c {
                    '·' => Cell::new_dead(),
                    _ => Cell::new_alive(),
                });
            }
            if nrow == 1 {
                ncol = ncell;
            } else if ncell != ncol {
                return Err(NotRectangular { line: nrow, found: ncell, expected: ncol });
            }
        }
        if cells.is_empty() {
            return Err(Empty);
        }
        Ok(Self::from_parts(cells, (nrow, ncol)))
    }
}

impl Index<(usize, usize)> for Grid {
    type Output = Cell;

    fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
        &self.cells[i * self.ncol + j]
    }
}

impl IndexMut<(usize, usize)> for Grid {
    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut Self::Output {
        &mut self.cells[i * self.ncol + j]
    }
}

impl Display for Grid {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for row in self.cells.chunks(self.ncol) {
            for cell in row {
                if cell.alive {
                    write!(f, " X")?;
                } else {
                    write!(f, " ·")?;
                }
            }
            writeln!(f)?;
        }
        Ok(())
    }
}

impl Grid {
    /// Returns the vertical and horizontal dimensions of the grid.
    #[must_use]
    pub const fn dim(&self) -> (usize, usize) {
        (self.nrow, self.ncol)
    }

    /// Increments the time by one tick.
    ///
    /// Births and deaths happen simultaneously according to the rules
    /// of Conway's Game of Life, after which the grid contains
    /// the next generation.
    pub fn tick(&mut self) {
        for i in 0..self.nrow {
            for j in 0..self.ncol {
                let live_neighbors = self.live_neighbors((i, j));
                let cell = &mut self[(i, j)];
                if !cell.alive {
                    if live_neighbors == 3 {
                        cell.lives = true;
                    }
                } else if live_neighbors != 2 && live_neighbors != 3 {
                    cell.lives = false;
                }
            }
        }
        for cell in &mut *self.cells {
            cell.alive = cell.lives;
        }
    }
}

impl Grid {
    /// Creates a `Grid` from a vector of `Cell`s and a pair of dimensions.
    ///
    /// # Panics
    ///
    /// Panics if the number of cells is not `nrow * ncol`.
    #[must_use]
    fn from_parts(cells: Vec<Cell>, (nrow, ncol): (usize, usize)) -> Self {
        assert_eq!(cells.len(), nrow * ncol);
        Self { cells: cells.into_boxed_slice(), nrow, ncol }
    }

    /// Returns the number of living neighbors for a cell.
    #[must_use]
    fn live_neighbors(&self, (i, j): (usize, usize)) -> u8 {
        use std::cmp::min;

        let mut live_neighbors = 0_u8;
        for m in i.saturating_sub(1)..min(i + 2, self.nrow) {
            for n in j.saturating_sub(1)..min(j + 2, self.ncol) {
                if self[(m, n)].alive && (m != i || n != j) {
                    live_neighbors += 1;
                }
            }
        }
        live_neighbors
    }
}
<|endoftext|>


<commit_before>extern crate config;
use self::config::types::{Config, ScalarValue, Value};

use std::env::home_dir;
use std::process::Command;

/// A command with arguments.
pub struct CommandLine {
    program: String,
    args: Vec<String>,
}

fn expand_home(path: &String) -> String {
    if path.starts_with("~/") {
        match home_dir() {
            Some(home) => format!("{}/{}", home.display(), &path[2..]),
            _ => path.clone(),
        }
    } else {
        path.clone()
    }
}

fn make_command_vec(vec: &Vec<Value>) -> Result<CommandLine, String> {
    if vec.is_empty() {
        return Err(format!("empty execution vector"));
    }

    let mut prog_args = vec![];
    for v in vec {
        match *v {
            Value::Svalue(ref sv) =>
                match *sv {
                    ScalarValue::Str(ref s) => prog_args.push(s),
                    _ => return Err(format!("non-string program value")),
                },
            _ => return Err(format!("non-string program value")),
        }
    }

    let (prog, args) = prog_args.split_at(1);
    Ok(CommandLine {
        program: expand_home(prog[0]),
        // XXX: Why does .cloned() not work?
        args: args.iter().map(|&arg| (*arg).clone()).collect(),
    })
}

fn make_command_str(string: &String) -> Result<CommandLine, String> {
    if string.is_empty() {
        Err(format!("empty execution string"))
    } else {
        Ok(CommandLine {
            program: expand_home(string),
            args: vec![],
        })
    }
}

/// Reads a command line from the configuration with the given configuration key.
///
/// If the configuration is a string, it is interpreted as a program with no arguments. A list of
/// strings is taken to be a program with arguments. The program supports expanding the `~/` token
/// to be the home directory of the current user.
///
/// All other configuration types are ignored.
pub fn read_command_line_from_config(conf: &Config, path: &str) -> Option<CommandLine> {
    conf.lookup(path).and_then(|val| {
        let cmd_line = match *val {
            Value::Array(ref a) => make_command_vec(a),
            Value::Svalue(ref sv) =>
                match *sv {
                    ScalarValue::Str(ref s) => make_command_str(s),
                    _ => Err(format!("unsupported type for {}", path)),
                },
            _ => Err(format!("unsupported type for {}", path)),
        };

        cmd_line.map_err(|err| {
            println!("Failed to make a command line for '{}': {:?}", path, err);
        }).ok()
    })
}

/// Runs a command line.
pub fn run_command_line(cmd_line: &CommandLine) -> Result<(), String> {
    let cmd = Command::new(&cmd_line.program)
                .args(&cmd_line.args)
                .output();

    match cmd {
        Ok(output) =>
            if output.status.success() {
                Ok(())
            } else {
                Err(format!("failed to execute process ({:?}):\noutput:\n{}\nerror:{}",
                            output.status.code(),
                            String::from_utf8_lossy(&output.stdout),
                            String::from_utf8_lossy(&output.stderr)))
            },
        _ => Err(format!("failed to execute process")),
    }
}
<commit_msg>exec: minor cleanup of expand_home<commit_after>extern crate config;
use self::config::types::{Config, ScalarValue, Value};

use std::env::home_dir;
use std::process::Command;

/// A command with arguments.
pub struct CommandLine {
    program: String,
    args: Vec<String>,
}

fn expand_home(path: &String) -> String {
    if path.starts_with("~/") {
        if let Some(home) = home_dir() {
            return format!("{}/{}", home.display(), &path[2..])
        }
    }

    path.clone()
}

fn make_command_vec(vec: &Vec<Value>) -> Result<CommandLine, String> {
    if vec.is_empty() {
        return Err(format!("empty execution vector"));
    }

    let mut prog_args = vec![];
    for v in vec {
        match *v {
            Value::Svalue(ref sv) =>
                match *sv {
                    ScalarValue::Str(ref s) => prog_args.push(s),
                    _ => return Err(format!("non-string program value")),
                },
            _ => return Err(format!("non-string program value")),
        }
    }

    let (prog, args) = prog_args.split_at(1);
    Ok(CommandLine {
        program: expand_home(prog[0]),
        // XXX: Why does .cloned() not work?
        args: args.iter().map(|&arg| (*arg).clone()).collect(),
    })
}

fn make_command_str(string: &String) -> Result<CommandLine, String> {
    if string.is_empty() {
        Err(format!("empty execution string"))
    } else {
        Ok(CommandLine {
            program: expand_home(string),
            args: vec![],
        })
    }
}

/// Reads a command line from the configuration with the given configuration key.
///
/// If the configuration is a string, it is interpreted as a program with no arguments. A list of
/// strings is taken to be a program with arguments. The program supports expanding the `~/` token
/// to be the home directory of the current user.
///
/// All other configuration types are ignored.
pub fn read_command_line_from_config(conf: &Config, path: &str) -> Option<CommandLine> {
    conf.lookup(path).and_then(|val| {
        let cmd_line = match *val {
            Value::Array(ref a) => make_command_vec(a),
            Value::Svalue(ref sv) =>
                match *sv {
                    ScalarValue::Str(ref s) => make_command_str(s),
                    _ => Err(format!("unsupported type for {}", path)),
                },
            _ => Err(format!("unsupported type for {}", path)),
        };

        cmd_line.map_err(|err| {
            println!("Failed to make a command line for '{}': {:?}", path, err);
        }).ok()
    })
}

/// Runs a command line.
pub fn run_command_line(cmd_line: &CommandLine) -> Result<(), String> {
    let cmd = Command::new(&cmd_line.program)
                .args(&cmd_line.args)
                .output();

    match cmd {
        Ok(output) =>
            if output.status.success() {
                Ok(())
            } else {
                Err(format!("failed to execute process ({:?}):\noutput:\n{}\nerror:{}",
                            output.status.code(),
                            String::from_utf8_lossy(&output.stdout),
                            String::from_utf8_lossy(&output.stderr)))
            },
        _ => Err(format!("failed to execute process")),
    }
}
<|endoftext|>


<commit_before>//! Hints (suggestions at the right of the prompt as you type).

use crate::history::Direction;
use crate::Context;

/// Hints provider
pub trait Hinter {
    /// Takes the currently edited `line` with the cursor `pos`ition and
    /// returns the string that should be displayed or `None`
    /// if no hint is available for the text the user currently typed.
    // TODO Validate: called while editing line but not while moving cursor.
    fn hint(&self, line: &str, pos: usize, ctx: &Context) -> Option<String>;
}

impl Hinter for () {
    fn hint(&self, _line: &str, _pos: usize, _ctx: &Context) -> Option<String> {
        None
    }
}

pub struct HistoryHinter {}

impl Hinter for HistoryHinter {
    fn hint(&self, line: &str, pos: usize, ctx: &Context) -> Option<String> {
        let start = if ctx.history_index() == ctx.history().len() {
            ctx.history_index() - 1
        } else {
            ctx.history_index()
        };
        if let Some(history_index) =
            ctx.history
                .starts_with(&line[..pos], start, Direction::Reverse)
        {
            let entry = ctx.history.get(history_index);
            if let Some(entry) = entry {
                if entry == line || entry == &line[..pos] {
                    return None;
                }
            }
            return entry.map(|s| s[pos..].to_owned());
        }
        None
    }
}
<commit_msg>Fix bug in `HistoryHinter` when `ctx.history_index()` is 0<commit_after>//! Hints (suggestions at the right of the prompt as you type).

use crate::history::Direction;
use crate::Context;

/// Hints provider
pub trait Hinter {
    /// Takes the currently edited `line` with the cursor `pos`ition and
    /// returns the string that should be displayed or `None`
    /// if no hint is available for the text the user currently typed.
    // TODO Validate: called while editing line but not while moving cursor.
    fn hint(&self, line: &str, pos: usize, ctx: &Context) -> Option<String>;
}

impl Hinter for () {
    fn hint(&self, _line: &str, _pos: usize, _ctx: &Context) -> Option<String> {
        None
    }
}

pub struct HistoryHinter {}

impl Hinter for HistoryHinter {
    fn hint(&self, line: &str, pos: usize, ctx: &Context) -> Option<String> {
        let start = if ctx.history_index() == ctx.history().len() {
            ctx.history_index().saturating_sub(1)
        } else {
            ctx.history_index()
        };
        if let Some(history_index) =
            ctx.history
                .starts_with(&line[..pos], start, Direction::Reverse)
        {
            let entry = ctx.history.get(history_index);
            if let Some(entry) = entry {
                if entry == line || entry == &line[..pos] {
                    return None;
                }
            }
            return entry.map(|s| s[pos..].to_owned());
        }
        None
    }
}
<|endoftext|>


<commit_before>

// A range is a range of characters:
// 0-9 -- numeral
// a-z -- lowercase alphabetic
// A-Z -- uppercase alphabetic
enum Range {
    Numeral,
    Lowercase,
    Uppercase
}
<commit_msg>Add expression logic and tests<commit_after>use tokenizer::Token;
use std::boxed::Box;

#[derive(Debug, PartialEq, Clone)]
pub enum Expression {
    Char(char),
    Numeral,
    Lowercase,
    Uppercase,
    Wildcard,

    // Any of the expressions will match
    Any(Vec<Expression>),

    // Any of the expressions will cause it to fail
    None(Vec<Expression>),

    // All of the expressions must match in order
    All(Vec<Expression>),

    // Modifiers:
    NoneOrMore(Box<Expression>),
    OneOrMore(Box<Expression>),
    NoneOrOne(Box<Expression>),
}

fn build_expression(tokens: Vec<Token>, within_brackets: bool,
                    allow_brackets: bool) -> Result<Expression, &'static str> {
    let mut itr = tokens.iter();

    // We use this as a stack.
    let mut exprs: Vec<Expression> = Vec::new();

    loop {

        // If there are no more tokens, return what we have
        let next_token: Token = match itr.next() {
            None => return Ok(Expression::All(exprs)),
            Some(t) => t.clone()
        };

        // Deal with the next token...
        match next_token {
            Token::Wildcard => exprs.push(Expression::Wildcard),
            Token::NoneOrMore => {
                // Pop the last expression off the stack -- if none
                // exists, ignore this character...
                if let Some(last_expr) = exprs.pop() {
                    let can_multiply = last_expr.is_multiplyable();
                    if can_multiply && !within_brackets {
                        exprs.push(Expression::NoneOrMore(
                            Box::new(last_expr)))
                    } else {
                        exprs.push(last_expr); // If not, put it back
                    }
                }
            }

            Token::OneOrMore => {
                // Pop the last expression off the stack -- if none
                // exists, ignore this character...
                if let Some(last_expr) = exprs.pop() {
                    let can_multiply = last_expr.is_multiplyable();
                    if can_multiply && !within_brackets {
                        exprs.push(Expression::OneOrMore(
                            Box::new(last_expr)))
                    } else {
                        exprs.push(last_expr); // If not, put it back
                    }
                }
            }

            Token::NoneOrOne => {
                // Pop the last expression off the stack -- if none
                // exists, ignore this character...
                if let Some(last_expr) = exprs.pop() {
                    let can_multiply = last_expr.is_multiplyable();
                    if can_multiply && !within_brackets {
                        exprs.push(Expression::NoneOrOne(
                            Box::new(last_expr)))
                    } else {
                        exprs.push(last_expr); // If not, put it back
                    }
                }
            }

            Token::NumeralRange => {
                if within_brackets {
                    exprs.push(Expression::Numeral);
                } else {
                    exprs.push(Expression::Char('0'));
                    exprs.push(Expression::Char('-'));
                    exprs.push(Expression::Char('9'));
                }
            },

            Token::LowercaseRange => {
                if within_brackets {
                    exprs.push(Expression::Lowercase);
                } else {
                    exprs.push(Expression::Char('a'));
                    exprs.push(Expression::Char('-'));
                    exprs.push(Expression::Char('z'));
                }
            },

            Token::UppercaseRange => {
                if within_brackets {
                    exprs.push(Expression::Uppercase);
                } else {
                    exprs.push(Expression::Char('A'));
                    exprs.push(Expression::Char('-'));
                    exprs.push(Expression::Char('Z'));
                }
            },

            Token::OpenBracket => {
                if !allow_brackets {
                    return Err("Nested brackets!");
                }

                // Search for a closing bracket -- if none is found,
                // then our regex is malformed and report it as such
                let bracketed: Vec<Token> = itr
                    .clone()
                    .take_while(|&t: &&Token| *t != Token::ClosedBracket)
                    .map(|t: &Token| t.clone())
                    .collect();

                // Advance the iterator past the tokens inside the brackets...
                for _ in 0..(bracketed.len()) { itr.next(); }

                if let Some(&Token::ClosedBracket) = itr.next() {
                    // If they begin with an inversion operator, then we want
                    // none-of the sub expressions, otherwise we want any of them...
                    if !bracketed.is_empty() && bracketed[0] == Token::BracketInversion {
                        let btns = bracketed[1..].to_vec();
                        match build_expression(btns, true, false) {
                            Err(s) => return Err(s),
                            Ok(Expression::All(e)) => exprs.push(Expression::None(e)),
                            Ok(e) => exprs.push(Expression::None(vec![e]))
                        }
                    } else {
                        match build_expression(bracketed, true, false) {
                            Err(s) => return Err(s),
                            Ok(Expression::All(e)) => exprs.push(Expression::Any(e)),
                            Ok(e) => exprs.push(Expression::Any(vec![e]))
                        }
                    }
                } else {
                    return Err("Bracket never closed!");
                }
            }

            Token::OpenParen => {
                // Search for a closing parenthesis -- if none is found,
                // then our regex is malformed
                let mut depth = 1;
                let grouped: Vec<Token> = itr
                    .clone()
                    .take_while(|&t: &&Token| {
                        if *t == Token::ClosedParen {
                            depth -= 1;
                        } else if *t == Token::OpenParen {
                            depth += 1;
                        }
                        depth > 0
                    })
                    .map(|t: &Token| t.clone())
                    .collect();

                // Skip the ones that we grouped together...
                for _ in 0..(grouped.len()) { itr.next(); }

                // Consume the closed parenthesis and keep going
                if let Some(&Token::ClosedParen) = itr.next() {
                    // We're just grouping everything as one expression...
                    let e = try!(build_expression(grouped, false, allow_brackets));
                    exprs.push(e)
                } else {
                    return Err("Parenthesis never closed!");
                }
            }

            // We should never encounter a closed parenthesis, bracket inversion, or closed bracket...
            Token::ClosedBracket => return Err("Unexpected closing bracket!"),
            Token::ClosedParen => return Err("Unexpected closing parenthesis!"),

            // This should really never happen
            // !FIXME! Maybe this should panic?
            Token::BracketInversion => return Err("Internal error: Unexpected bracket inversion!"),

            Token::Char(c) => exprs.push(Expression::Char(c)),
        }
    }
}

impl Expression {
    pub fn new(tokens: Vec<Token>) -> Result<Expression, &'static str> {
        build_expression(tokens, false, true)
    }

    // Returns true if the expression can be multiplied by the
    // operators: +, ?, and *
    // Effectively the answer is that they can't be used on each other,
    // so you should place parentheses around something if you want to
    // combine them.
    fn is_multiplyable(&self) -> bool {
        match *self {
            Expression::NoneOrMore(_) => false,
            Expression::OneOrMore(_) => false,
            Expression::NoneOrOne(_) => false,
            _ => true
        }
    }
}

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

    #[test]
    fn it_can_make_an_empty_expr() {
        assert_eq!(Expression::new(unsafe_parse("")).unwrap(),
                   Expression::All(vec![]));
    }

    #[test]
    fn it_can_make_a_simple_expr() {
        assert_eq!(Expression::new(unsafe_parse("hello")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('h'),
                       Expression::Char('e'),
                       Expression::Char('l'),
                       Expression::Char('l'),
                       Expression::Char('o')]));
    }

    #[test]
    fn it_can_make_a_wildcard_expr() {
        assert_eq!(Expression::new(unsafe_parse("h.llo")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('h'),
                       Expression::Wildcard,
                       Expression::Char('l'),
                       Expression::Char('l'),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse(".*")).unwrap(),
                   Expression::All(vec![
                       Expression::NoneOrMore(
                           Box::new(Expression::Wildcard))]));
    }

    #[test]
    fn it_can_make_a_multiplying_expr() {
        assert_eq!(Expression::new(unsafe_parse("+ello")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('e'),
                       Expression::Char('l'),
                       Expression::Char('l'),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("h?l*o")).unwrap(),
                   Expression::All(vec![
                       Expression::NoneOrOne(
                           Box::new(Expression::Char('h'))),
                       Expression::NoneOrMore(
                           Box::new(Expression::Char('l'))),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("h+l++o")).unwrap(),
                   Expression::All(vec![
                       Expression::OneOrMore(
                           Box::new(Expression::Char('h'))),
                       Expression::OneOrMore(
                           Box::new(Expression::Char('l'))),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("h+l*+o")).unwrap(),
                   Expression::All(vec![
                       Expression::OneOrMore(
                           Box::new(Expression::Char('h'))),
                       Expression::NoneOrMore(
                           Box::new(Expression::Char('l'))),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("+*?+*+*???*+")).unwrap(),
                   Expression::All(vec![]));

        assert_eq!(Expression::new(unsafe_parse("+*?+*+a*???*+")).unwrap(),
                   Expression::All(vec![
                       Expression::NoneOrMore(
                           Box::new(Expression::Char('a')))]));
    }

    #[test]
    fn it_groups_parenthesized_expressions() {
        assert_eq!(Expression::new(unsafe_parse("()")).unwrap(),
                   Expression::All(vec![
                       Expression::All(vec![])]));

        assert_eq!(Expression::new(unsafe_parse("((((()))))")).unwrap(),
                   Expression::All(vec![
                       Expression::All(vec![
                           Expression::All(vec![
                               Expression::All(vec![
                                   Expression::All(vec![
                                       Expression::All(vec![])])])])])]));

        assert_eq!(Expression::new(unsafe_parse("()()")).unwrap(),
                   Expression::All(vec![
                       Expression::All(vec![]),
                       Expression::All(vec![])]));

        assert!(Expression::new(unsafe_parse(")(")).is_err());
        assert!(Expression::new(unsafe_parse("(")).is_err());
        assert!(Expression::new(unsafe_parse(")")).is_err());
        assert!(Expression::new(unsafe_parse("(()")).is_err());
        assert!(Expression::new(unsafe_parse("()(()")).is_err());
        assert!(Expression::new(unsafe_parse(")()")).is_err());

        assert_eq!(Expression::new(unsafe_parse("(\\)\\()")).unwrap(),
                   Expression::All(vec![
                       Expression::All(vec![
                           Expression::Char(')'),
                           Expression::Char('(')])]));

        assert_eq!(Expression::new(unsafe_parse("a(\\)\\()b")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('a'),
                       Expression::All(vec![
                           Expression::Char(')'),
                           Expression::Char('(')]),
                       Expression::Char('b')]));
    }

    #[test]
    fn it_prevents_non_bracket_range_exprs() {
        assert_eq!(Expression::new(unsafe_parse("ea-zlo")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('e'),
                       Expression::Char('a'),
                       Expression::Char('-'),
                       Expression::Char('z'),
                       Expression::Char('l'),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("a-Zo")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('a'),
                       Expression::Char('-'),
                       Expression::Char('Z'),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("0-9(A-Z)lo")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('0'),
                       Expression::Char('-'),
                       Expression::Char('9'),
                       Expression::All(vec![
                           Expression::Char('A'),
                           Expression::Char('-'),
                           Expression::Char('Z')]),
                       Expression::Char('l'),
                       Expression::Char('o')]));

        assert_eq!(Expression::new(unsafe_parse("0-9")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('0'),
                       Expression::Char('-'),
                       Expression::Char('9')]));
    }

    #[test]
    fn it_allows_bracket_exprs() {
        assert_eq!(Expression::new(unsafe_parse("[0-9]")).unwrap(),
                   Expression::All(vec![
                       Expression::Any(vec![Expression::Numeral])]));

        assert_eq!(Expression::new(unsafe_parse("[0-9a-z]")).unwrap(),
                   Expression::All(vec![
                       Expression::Any(vec![
                           Expression::Numeral,
                           Expression::Lowercase])]));

        assert_eq!(Expression::new(unsafe_parse("[^abc]")).unwrap(),
                   Expression::All(vec![
                       Expression::None(vec![
                           Expression::Char('a'),
                           Expression::Char('b'),
                           Expression::Char('c')])]));

        // Don't worry about duplicates in brackets, they are
        // redundant and serve no functional difference.
        assert_eq!(Expression::new(unsafe_parse("[lol]")).unwrap(),
                   Expression::All(vec![
                       Expression::Any(vec![
                           Expression::Char('l'),
                           Expression::Char('o'),
                           Expression::Char('l')])]));

        // Multipliers in brackets make no sense, but they aren't
        // ambiguous so we can just ignore them.
        assert_eq!(Expression::new(unsafe_parse("[l+ol*]")).unwrap(),
                   Expression::All(vec![
                       Expression::Any(vec![
                           Expression::Char('l'),
                           Expression::Char('o'),
                           Expression::Char('l')])]));

        assert_eq!(Expression::new(unsafe_parse("(.[(0-9)])")).unwrap(),
                   Expression::All(vec![
                       Expression::All(vec![
                           Expression::Wildcard,
                           Expression::Any(vec![
                               Expression::All(vec![
                                   Expression::Char('0'),
                                   Expression::Char('-'),
                                   Expression::Char('9')])])])]));
    }

    #[test]
    fn it_properly_checks_for_nested_brackets() {
        // Multipliers in brackets make no sense, but they aren't
        // ambiguous so we can just ignore them.
        assert!(Expression::new(unsafe_parse("[[lol]]")).is_err());
        assert!(Expression::new(unsafe_parse("[lo[l]]")).is_err());
        assert!(Expression::new(unsafe_parse("([)]")).is_err());
        assert!(Expression::new(unsafe_parse("(.[0-9)]")).is_err());
    }

    #[test]
    fn it_allows_mixed_parentheses_and_brackets() {
        assert_eq!(Expression::new(unsafe_parse("()[]")).unwrap(),
                   Expression::All(vec![
                       Expression::All(vec![]),
                       Expression::Any(vec![])]));

        assert_eq!(Expression::new(unsafe_parse("[]()")).unwrap(),
                   Expression::All(vec![
                       Expression::Any(vec![]),
                       Expression::All(vec![])]));

        assert_eq!(Expression::new(unsafe_parse("l[(o)]l")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('l'),
                       Expression::Any(vec![
                           Expression::All(vec![
                               Expression::Char('o')])]),
                       Expression::Char('l')]));

        assert_eq!(Expression::new(unsafe_parse("l[0-9(o)]l")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('l'),
                       Expression::Any(vec![
                           Expression::Numeral,
                           Expression::All(vec![
                               Expression::Char('o')])]),
                       Expression::Char('l')]));

        assert_eq!(Expression::new(unsafe_parse("l[^0-9(o)]l")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('l'),
                       Expression::None(vec![
                           Expression::Numeral,
                           Expression::All(vec![
                               Expression::Char('o')])]),
                       Expression::Char('l')]));

        assert_eq!(Expression::new(unsafe_parse("l[0-9^(o)](.)")).unwrap(),
                   Expression::All(vec![
                       Expression::Char('l'),
                       Expression::Any(vec![
                           Expression::Numeral,
                           Expression::Char('^'),
                           Expression::All(vec![
                               Expression::Char('o')])]),
                       Expression::All(vec![
                           Expression::Wildcard])]));
    }
}
<|endoftext|>


<commit_before>use std;
use std::num::FromPrimitive;
use std::ffi::CStr;
use std::str;
use std::borrow::ToOwned;
use ffi;
use {
    FtResult,
    GlyphSlot,
    Matrix,
    Vector,
};

#[repr(u32)]
#[derive(Copy)]
pub enum KerningMode {
    KerningDefault = ffi::FT_KERNING_DEFAULT,
    KerningUnfitted = ffi::FT_KERNING_UNFITTED,
    KerningUnscaled = ffi::FT_KERNING_UNSCALED
}

bitflags!(
flags LoadFlag: i32 {
    const DEFAULT                    = ffi::FT_LOAD_DEFAULT,
    const NO_SCALE                   = ffi::FT_LOAD_NO_SCALE,
    const NO_HINTING                 = ffi::FT_LOAD_NO_HINTING,
    const RENDER                     = ffi::FT_LOAD_RENDER,
    const NO_BITMAP                  = ffi::FT_LOAD_NO_BITMAP,
    const VERTICAL_LAYOUT            = ffi::FT_LOAD_VERTICAL_LAYOUT,
    const FORCE_AUTOHINT             = ffi::FT_LOAD_FORCE_AUTOHINT,
    const CROP_BITMAP                = ffi::FT_LOAD_CROP_BITMAP,
    const PEDANTIC                   = ffi::FT_LOAD_PEDANTIC,
    const IGNORE_GLOBAL_ADVANCE_WITH = ffi::FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH,
    const NO_RECURSE                 = ffi::FT_LOAD_NO_RECURSE,
    const IGNORE_TRANSFORM           = ffi::FT_LOAD_IGNORE_TRANSFORM,
    const MONOCHROME                 = ffi::FT_LOAD_MONOCHROME,
    const LINEAR_DESIGN              = ffi::FT_LOAD_LINEAR_DESIGN,
    const NO_AUTOHINT                = ffi::FT_LOAD_NO_AUTOHINT,
    const TARGET_NORMAL              = ffi::FT_LOAD_TARGET_NORMAL,
    const TARGET_LIGHT               = ffi::FT_LOAD_TARGET_LIGHT,
    const TARGET_MONO                = ffi::FT_LOAD_TARGET_MONO,
    const TARGET_LCD                 = ffi::FT_LOAD_TARGET_LCD,
    const TARGET_LCD_V               = ffi::FT_LOAD_TARGET_LCD_V,
    const COLOR                      = ffi::FT_LOAD_COLOR
});

#[derive(Eq, PartialEq, Hash)]
pub struct Face {
    library_raw: ffi::FT_Library,
    raw: ffi::FT_Face,
    glyph: GlyphSlot,
}

impl Face {
    pub fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Face) -> Face {
        unsafe {
            ffi::FT_Reference_Library(library_raw);
        }

        Face {
            library_raw: library_raw,
            raw: raw,
            glyph: unsafe { GlyphSlot::from_raw(library_raw, (*raw).glyph) },
        }
    }

    pub fn attach_file(&self, filepathname: &str) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Attach_File(self.raw, filepathname.as_slice().as_ptr() as *const i8);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn reference(&self) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Reference_Face(self.raw);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_char_size(&self, char_width: isize, char_height: isize, horz_resolution: u32, vert_resolution: u32) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Char_Size(self.raw, char_width as ffi::FT_F26Dot6,
                                            char_height as ffi::FT_F26Dot6, horz_resolution,
                                            vert_resolution);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_pixel_sizes(&self, pixel_width: u32, pixel_height: u32) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Pixel_Sizes(self.raw, pixel_width, pixel_height);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_glyph(&self, glyph_index: u32, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Glyph(self.raw, glyph_index, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_char(&self, char_code: usize, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Char(self.raw, char_code as ffi::FT_ULong, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_transform(&self, matrix: &Matrix, delta: &Vector) {
        unsafe {
            ffi::FT_Set_Transform(self.raw, matrix, delta);
        }
    }

    pub fn get_char_index(&self, charcode: usize) -> u32 {
        unsafe {
            ffi::FT_Get_Char_Index(self.raw, charcode as ffi::FT_ULong)
        }
    }

    pub fn get_kerning(&self, left_char_index: u32, right_char_index: u32, kern_mode: KerningMode)
        -> FtResult<Vector> {

        let vec = Vector { x: 0, y: 0 };

        let err_code = unsafe {
            ffi::FT_Get_Kerning(self.raw, left_char_index, right_char_index,
                                kern_mode as u32, std::mem::transmute(&vec))
        };

        if err_code == ffi::FT_Err_Ok {
            Ok(vec)
        } else {
            Err(FromPrimitive::from_i32(err_code).unwrap())
        }
    }

    // According to FreeType doc, each time you load a new glyph image,
    // the previous one is erased from the glyph slot.
    #[inline(always)]
    pub fn glyph(&self) -> &GlyphSlot {
        &self.glyph
    }

    #[inline(always)]
    pub fn has_horizontal(&self) -> bool {
        ffi::FT_HAS_HORIZONTAL(self.raw)
    }

    #[inline(always)]
    pub fn has_vertical(&self) -> bool {
        ffi::FT_HAS_VERTICAL(self.raw)
    }

    #[inline(always)]
    pub fn has_kerning(&self) -> bool {
        ffi::FT_HAS_KERNING(self.raw)
    }

    #[inline(always)]
    pub fn is_scalable(&self) -> bool {
        ffi::FT_IS_SCALABLE(self.raw)
    }

    #[inline(always)]
    pub fn is_sfnt(&self) -> bool {
        ffi::FT_IS_SFNT(self.raw)
    }

    #[inline(always)]
    pub fn is_fixed_width(&self) -> bool {
        ffi::FT_IS_FIXED_WIDTH(self.raw)
    }

    #[inline(always)]
    pub fn has_fixed_sizes(&self) -> bool {
        ffi::FT_HAS_FIXED_SIZES(self.raw)
    }

    #[inline(always)]
    pub fn has_glyph_names(&self) -> bool {
        ffi::FT_HAS_GLYPH_NAMES(self.raw)
    }

    #[inline(always)]
    pub fn is_cid_keyed(&self) -> bool {
        ffi::FT_IS_CID_KEYED(self.raw)
    }

    #[inline(always)]
    pub fn is_tricky(&self) -> bool {
        ffi::FT_IS_TRICKY(self.raw)
    }

    #[inline(always)]
    pub fn has_color(&self) -> bool {
        ffi::FT_HAS_COLOR(self.raw)
    }

    #[inline(always)]
    pub fn raw(&self) -> &ffi::FT_FaceRec {
        unsafe {
            &*self.raw
        }
    }

    #[inline(always)]
    pub fn ascender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).ascender
        }
    }

    #[inline(always)]
    pub fn descender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).descender
        }
    }

    #[inline(always)]
    pub fn height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).height
        }
    }

    #[inline(always)]
    pub fn max_advance_width(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_width
        }
    }

    #[inline(always)]
    pub fn max_advance_height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_height
        }
    }

    #[inline(always)]
    pub fn underline_position(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_position
        }
    }

    #[inline(always)]
    pub fn underline_thickness(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_thickness
        }
    }

    pub fn family_name(&self) -> Option<String> {

        let family_name_ptr = unsafe { (*self.raw).family_name };

        if family_name_ptr.is_null() {
            None
        } else {
            let family_name = unsafe { CStr::from_ptr(family_name_ptr).to_bytes() };
            match str::from_utf8(family_name) {
                Ok(string)  => Some(string.to_owned()),
                _           => None
            }
        }
    }

    pub fn style_name(&self) -> Option<String> {

        let style_name_ptr = unsafe { (*self.raw).style_name };

        if style_name_ptr.is_null() {
            None
        } else {
            let style_name = unsafe { CStr::from_ptr(style_name_ptr).to_bytes() };
            match str::from_utf8(style_name) {
                Ok(string)  => Some(string.to_owned()),
                _           => None
            }
        }
    }
}

impl Drop for Face {
    fn drop(&mut self) {
        unsafe {
            match ffi::FT_Done_Face(self.raw) {
                ffi::FT_Err_Ok => {
                    if ffi::FT_Done_Library(self.library_raw) != ffi::FT_Err_Ok {
                        panic!("Failed to deref library");
                    }
                },
                _ => panic!("Failed to drop face"),
            }
        }
    }
}
<commit_msg>Added `Clone` for `Face`<commit_after>use std;
use std::num::FromPrimitive;
use std::ffi::CStr;
use std::str;
use std::borrow::ToOwned;
use ffi;
use {
    FtResult,
    GlyphSlot,
    Matrix,
    Vector,
};

#[repr(u32)]
#[derive(Copy)]
pub enum KerningMode {
    KerningDefault = ffi::FT_KERNING_DEFAULT,
    KerningUnfitted = ffi::FT_KERNING_UNFITTED,
    KerningUnscaled = ffi::FT_KERNING_UNSCALED
}

bitflags!(
flags LoadFlag: i32 {
    const DEFAULT                    = ffi::FT_LOAD_DEFAULT,
    const NO_SCALE                   = ffi::FT_LOAD_NO_SCALE,
    const NO_HINTING                 = ffi::FT_LOAD_NO_HINTING,
    const RENDER                     = ffi::FT_LOAD_RENDER,
    const NO_BITMAP                  = ffi::FT_LOAD_NO_BITMAP,
    const VERTICAL_LAYOUT            = ffi::FT_LOAD_VERTICAL_LAYOUT,
    const FORCE_AUTOHINT             = ffi::FT_LOAD_FORCE_AUTOHINT,
    const CROP_BITMAP                = ffi::FT_LOAD_CROP_BITMAP,
    const PEDANTIC                   = ffi::FT_LOAD_PEDANTIC,
    const IGNORE_GLOBAL_ADVANCE_WITH = ffi::FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH,
    const NO_RECURSE                 = ffi::FT_LOAD_NO_RECURSE,
    const IGNORE_TRANSFORM           = ffi::FT_LOAD_IGNORE_TRANSFORM,
    const MONOCHROME                 = ffi::FT_LOAD_MONOCHROME,
    const LINEAR_DESIGN              = ffi::FT_LOAD_LINEAR_DESIGN,
    const NO_AUTOHINT                = ffi::FT_LOAD_NO_AUTOHINT,
    const TARGET_NORMAL              = ffi::FT_LOAD_TARGET_NORMAL,
    const TARGET_LIGHT               = ffi::FT_LOAD_TARGET_LIGHT,
    const TARGET_MONO                = ffi::FT_LOAD_TARGET_MONO,
    const TARGET_LCD                 = ffi::FT_LOAD_TARGET_LCD,
    const TARGET_LCD_V               = ffi::FT_LOAD_TARGET_LCD_V,
    const COLOR                      = ffi::FT_LOAD_COLOR
});

#[derive(Eq, PartialEq, Hash)]
pub struct Face {
    library_raw: ffi::FT_Library,
    raw: ffi::FT_Face,
    glyph: GlyphSlot,
}

impl Clone for Face {
    fn clone(&self) -> Face {
        unsafe {
            ffi::FT_Reference_Library(self.library_raw);
            ffi::FT_Reference_Face(self.raw);
        }
        Face { ..*self }
    }
}

impl Face {
    pub fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Face) -> Face {
        unsafe {
            ffi::FT_Reference_Library(library_raw);
        }

        Face {
            library_raw: library_raw,
            raw: raw,
            glyph: unsafe { GlyphSlot::from_raw(library_raw, (*raw).glyph) },
        }
    }

    pub fn attach_file(&self, filepathname: &str) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Attach_File(self.raw, filepathname.as_slice().as_ptr() as *const i8);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn reference(&self) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Reference_Face(self.raw);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_char_size(&self, char_width: isize, char_height: isize, horz_resolution: u32, vert_resolution: u32) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Char_Size(self.raw, char_width as ffi::FT_F26Dot6,
                                            char_height as ffi::FT_F26Dot6, horz_resolution,
                                            vert_resolution);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_pixel_sizes(&self, pixel_width: u32, pixel_height: u32) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Pixel_Sizes(self.raw, pixel_width, pixel_height);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_glyph(&self, glyph_index: u32, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Glyph(self.raw, glyph_index, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_char(&self, char_code: usize, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Char(self.raw, char_code as ffi::FT_ULong, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_transform(&self, matrix: &Matrix, delta: &Vector) {
        unsafe {
            ffi::FT_Set_Transform(self.raw, matrix, delta);
        }
    }

    pub fn get_char_index(&self, charcode: usize) -> u32 {
        unsafe {
            ffi::FT_Get_Char_Index(self.raw, charcode as ffi::FT_ULong)
        }
    }

    pub fn get_kerning(&self, left_char_index: u32, right_char_index: u32, kern_mode: KerningMode)
        -> FtResult<Vector> {

        let vec = Vector { x: 0, y: 0 };

        let err_code = unsafe {
            ffi::FT_Get_Kerning(self.raw, left_char_index, right_char_index,
                                kern_mode as u32, std::mem::transmute(&vec))
        };

        if err_code == ffi::FT_Err_Ok {
            Ok(vec)
        } else {
            Err(FromPrimitive::from_i32(err_code).unwrap())
        }
    }

    // According to FreeType doc, each time you load a new glyph image,
    // the previous one is erased from the glyph slot.
    #[inline(always)]
    pub fn glyph(&self) -> &GlyphSlot {
        &self.glyph
    }

    #[inline(always)]
    pub fn has_horizontal(&self) -> bool {
        ffi::FT_HAS_HORIZONTAL(self.raw)
    }

    #[inline(always)]
    pub fn has_vertical(&self) -> bool {
        ffi::FT_HAS_VERTICAL(self.raw)
    }

    #[inline(always)]
    pub fn has_kerning(&self) -> bool {
        ffi::FT_HAS_KERNING(self.raw)
    }

    #[inline(always)]
    pub fn is_scalable(&self) -> bool {
        ffi::FT_IS_SCALABLE(self.raw)
    }

    #[inline(always)]
    pub fn is_sfnt(&self) -> bool {
        ffi::FT_IS_SFNT(self.raw)
    }

    #[inline(always)]
    pub fn is_fixed_width(&self) -> bool {
        ffi::FT_IS_FIXED_WIDTH(self.raw)
    }

    #[inline(always)]
    pub fn has_fixed_sizes(&self) -> bool {
        ffi::FT_HAS_FIXED_SIZES(self.raw)
    }

    #[inline(always)]
    pub fn has_glyph_names(&self) -> bool {
        ffi::FT_HAS_GLYPH_NAMES(self.raw)
    }

    #[inline(always)]
    pub fn is_cid_keyed(&self) -> bool {
        ffi::FT_IS_CID_KEYED(self.raw)
    }

    #[inline(always)]
    pub fn is_tricky(&self) -> bool {
        ffi::FT_IS_TRICKY(self.raw)
    }

    #[inline(always)]
    pub fn has_color(&self) -> bool {
        ffi::FT_HAS_COLOR(self.raw)
    }

    #[inline(always)]
    pub fn raw(&self) -> &ffi::FT_FaceRec {
        unsafe {
            &*self.raw
        }
    }

    #[inline(always)]
    pub fn ascender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).ascender
        }
    }

    #[inline(always)]
    pub fn descender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).descender
        }
    }

    #[inline(always)]
    pub fn height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).height
        }
    }

    #[inline(always)]
    pub fn max_advance_width(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_width
        }
    }

    #[inline(always)]
    pub fn max_advance_height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_height
        }
    }

    #[inline(always)]
    pub fn underline_position(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_position
        }
    }

    #[inline(always)]
    pub fn underline_thickness(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_thickness
        }
    }

    pub fn family_name(&self) -> Option<String> {

        let family_name_ptr = unsafe { (*self.raw).family_name };

        if family_name_ptr.is_null() {
            None
        } else {
            let family_name = unsafe { CStr::from_ptr(family_name_ptr).to_bytes() };
            match str::from_utf8(family_name) {
                Ok(string)  => Some(string.to_owned()),
                _           => None
            }
        }
    }

    pub fn style_name(&self) -> Option<String> {

        let style_name_ptr = unsafe { (*self.raw).style_name };

        if style_name_ptr.is_null() {
            None
        } else {
            let style_name = unsafe { CStr::from_ptr(style_name_ptr).to_bytes() };
            match str::from_utf8(style_name) {
                Ok(string)  => Some(string.to_owned()),
                _           => None
            }
        }
    }
}

impl Drop for Face {
    fn drop(&mut self) {
        unsafe {
            match ffi::FT_Done_Face(self.raw) {
                ffi::FT_Err_Ok => {
                    if ffi::FT_Done_Library(self.library_raw) != ffi::FT_Err_Ok {
                        panic!("Failed to deref library");
                    }
                },
                _ => panic!("Failed to drop face"),
            }
        }
    }
}
<|endoftext|>