<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

//! Complex type
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::f64;

use types::{Zero, One};

#[derive(Debug, Clone, Copy, PartialEq, Default)]
/// Complex number, with double precision real and imaginary parts.
pub struct Complex {
    /// Real part of the complex
    real: f64,
    /// Imaginary part of the complex
    imag: f64,
}

impl Complex {
    /// Create a new `Complex` from a norm `r` and a phase `phi` in radians.
    pub fn polar(r: f64, phi: f64) -> Complex {
        Complex{
            real: r * f64::cos(phi),
            imag: r * f64::sin(phi)
        }
    }

    /// Create a complex from cartesian coordinates
    pub fn cartesian(x: f64, y: f64) -> Complex {
        Complex{
            real: x,
            imag: y,
        }
    }

    /// Get the real part of the complex
    #[inline]
    pub fn real(&self) -> f64 {
        self.real
    }

    /// Get the imaginary part of the complex
    #[inline]
    pub fn imag(&self) -> f64 {
        self.imag
    }

    /// Get the phase of the complex in the [-π, π) interval
    #[inline]
    pub fn phase(&self) -> f64 {
        f64::atan2(self.imag, self.real)
    }

    /// Get the norm of the complex
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }

    /// Get the square of the norm if this complex
    #[inline]
    pub fn norm2(&self) -> f64 {
        self.real * self.real + self.imag * self.imag
    }

    /// Get the conjugate of the complex
    #[inline]
    pub fn conj(&self) -> Complex {
        Complex {
            real: self.real,
            imag: -self.imag
        }
    }
}

impl Add<Complex> for Complex {
    type Output = Complex;
    fn add(self, other: Complex) -> Complex {
        let x = self.real() + other.real();
        let y = self.imag() + other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Sub<Complex> for Complex {
    type Output = Complex;
    fn sub(self, other: Complex) -> Complex {
        let x = self.real() - other.real();
        let y = self.imag() - other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Neg for Complex {
    type Output = Complex;
    fn neg(self) -> Complex {
        Complex{
            real: -self.real,
            imag: -self.imag,
        }
    }
}

impl Mul<Complex> for Complex {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        let x = self.real() * other.real() - self.imag() * other.imag();
        let y = self.real() * other.imag() + self.imag() * other.real();
        Complex::cartesian(x, y)
    }
}

impl Mul<f64> for Complex {
    type Output = Complex;
    fn mul(self, other: f64) -> Complex {
        Complex::cartesian(self.real() * other, self.imag() * other)
    }
}

impl Mul<Complex> for f64 {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        Complex::cartesian(self * other.real(), self * other.imag())
    }
}

impl Div<Complex> for Complex {
    type Output = Complex;
    fn div(self, other: Complex) -> Complex {
        let r = other.norm2();
        let x = self.real() * other.real() + self.imag() * other.imag();
        let y = - self.real() * other.imag() + self.imag() * other.real();

        Complex::cartesian(x / r, y / r)
    }
}

impl Div<f64> for Complex {
    type Output = Complex;
    fn div(self, other: f64) -> Complex {
        let norm = self.norm() / other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

impl Zero for Complex {
    fn zero() -> Complex {
        Complex::cartesian(0.0, 0.0)
    }

    fn is_zero(&self) -> bool {
        self.norm2() == 0.0
    }
}

impl One for Complex {
    fn one() -> Complex {
        Complex::cartesian(1.0, 0.0)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::f64::consts;

    #[test]
    fn norm() {
        let c = Complex::polar(3.0, 5.0);
        assert_approx_eq!(c.norm(), 3.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_approx_eq!(c.norm(), 3.0);
    }

    #[test]
    fn phase() {
        // Phase is between 0 and 2π
        for &phase in &[-consts::PI, -3.1, -1.5, 0.0, 0.1, 2.0, 3.1] {
            let c = Complex::polar(1.0, phase);
            assert_approx_eq!(c.phase(), phase);
        }

        let c = Complex::polar(1.0, -8.0);
        assert_approx_eq!(c.phase(), -8.0 + 2.0 * consts::PI);

        let c = Complex::polar(1.0, 12.0);
        assert_approx_eq!(c.phase(), 12.0 - 4.0 * consts::PI);

        let c = Complex::polar(1.0, consts::PI);
        assert_eq!(c.phase(), consts::PI);
        let c = Complex::polar(1.0, -consts::PI);
        assert_eq!(c.phase(), -consts::PI);

        let c = Complex::polar(3.0, 0.0);
        assert_eq!(c.phase(), 0.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_eq!(c.phase(), -consts::PI);
    }

    #[test]
    fn conj() {
        let c = Complex::cartesian(3.0, 5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, -5.0));

        let c = Complex::cartesian(3.0, -5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 5.0));

        let c = Complex::cartesian(3.0, 0.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 0.0));
    }

    #[test]
    fn cartesian() {
        let c = Complex::polar(1.0, 0.0);
        assert_approx_eq!(c.real(), 1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::PI);
        assert_approx_eq!(c.real(), -1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_2);
        assert_approx_eq!(c.real(), 0.0);
        assert_approx_eq!(c.imag(), 1.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_4);
        assert_approx_eq!(c.real(), consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.imag(), consts::FRAC_1_SQRT_2);

        let c = Complex::cartesian(consts::FRAC_1_SQRT_2, consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.norm(), 1.0);
        assert_approx_eq!(c.phase(), consts::FRAC_PI_4);
    }

    #[test]
    fn add() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a + b;

        assert_eq!(c.real(), a.real() + b.real());
        assert_eq!(c.imag(), a.imag() + b.imag());
    }

    #[test]
    fn sub() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a - b;

        assert_eq!(c.real(), a.real() - b.real());
        assert_eq!(c.imag(), a.imag() - b.imag());
    }

    #[test]
    fn neg() {
        let a = Complex::polar(2.0, 0.2);
        let c = -a;

        assert_approx_eq!(c.norm(), a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);

        assert_approx_eq!(c.real(), - a.real());
        assert_approx_eq!(c.imag(), - a.imag());
    }

    #[test]
    fn mul() {
        let a = Complex::polar(2.0, 1.4);
        let b = Complex::polar(1.0, 0.5);
        let c = a * b;

        assert_eq!(c.norm(), a.norm() * b.norm());
        assert_eq!(c.phase(), a.phase() + b.phase());

        let c = 3.0 * a;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = a * 3.0;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = -2.0 * a;
        assert_eq!(c.norm(), 2.0 * a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }

    #[test]
    fn div() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a / b;

        assert_eq!(c.norm(), a.norm() / b.norm());
        assert_eq!(c.phase(), a.phase() - b.phase());

        let c = a / 3.0;
        assert_eq!(c.norm(), a.norm()/3.0);
        assert_approx_eq!(c.phase(), a.phase());

        let c = a / (-2.0);
        assert_eq!(c.norm(), a.norm()/2.0);
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }
}
<commit_msg>[doc] Add examples to all Complex functions<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

//! Complex type
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::f64;

use types::{Zero, One};

#[derive(Debug, Clone, Copy, PartialEq, Default)]
/// Complex number, with double precision real and imaginary parts.
///
/// `Complex` implements all the usual arithmetics operations:
///
/// ```
/// # use lumol::Complex;
///
/// let w = Complex::cartesian(-1.0, 0.5);
/// let z = Complex::cartesian(4.0, 2.0);
///
/// // Addition
/// let c = w + z;
/// assert_eq!(c, Complex::cartesian(3.0, 2.5));
///
/// // Subtraction
/// let c = w - z;
/// assert_eq!(c, Complex::cartesian(-5.0, -1.5));
///
/// // Multiplication
/// let c = w * z;
/// assert_eq!(c, Complex::cartesian(-5.0, 0.0));
///
/// let c = 42.0 * w;
/// assert_eq!(c, Complex::cartesian(-42.0, 21.0));
///
/// // Division
/// let c = z / 2.0;
/// assert_eq!(c, Complex::cartesian(2.0, 1.0));
/// ```
pub struct Complex {
    /// Real part of the complex
    real: f64,
    /// Imaginary part of the complex
    imag: f64,
}

impl Complex {
    /// Create a new `Complex` from a norm `r` and a phase `phi` in radians.
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// # use std::f64;
    /// let z = Complex::polar(3.0, f64::consts::PI);
    /// assert_eq!(z.norm(), 3.0);
    /// ```
    pub fn polar(r: f64, phi: f64) -> Complex {
        Complex{
            real: r * f64::cos(phi),
            imag: r * f64::sin(phi)
        }
    }

    /// Create a complex from cartesian coordinates
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.real(), 3.0);
    /// assert_eq!(z.imag(), -2.0);
    /// ```
    pub fn cartesian(x: f64, y: f64) -> Complex {
        Complex{
            real: x,
            imag: y,
        }
    }

    /// Get the real part of the complex
    /// Create a complex from cartesian coordinates
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.real(), 3.0);
    /// ```
    #[inline]
    pub fn real(&self) -> f64 {
        self.real
    }

    /// Get the imaginary part of the complex
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.imag(), -2.0);
    /// ```
    #[inline]
    pub fn imag(&self) -> f64 {
        self.imag
    }

    /// Get the phase of the complex in the [-π, π) interval
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// let z = Complex::polar(2.0, 0.3);
    /// assert_eq!(z.phase(), 0.3);
    /// ```
    #[inline]
    pub fn phase(&self) -> f64 {
        f64::atan2(self.imag, self.real)
    }

    /// Get the norm of the complex
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// # use std::f64;
    /// let z = Complex::polar(2.0, 0.3);
    /// assert_eq!(z.norm(), 2.0);
    ///
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.norm(), f64::sqrt(5.0));
    /// ```
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }

    /// Get the square of the norm if this complex
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.norm2(), 5.0);
    /// ```
    #[inline]
    pub fn norm2(&self) -> f64 {
        self.real * self.real + self.imag * self.imag
    }

    /// Get the conjugate of the complex
    /// # Examples
    /// ```
    /// # use lumol::Complex;
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.conj(), Complex::cartesian(2.0, -1.0));
    /// ```
    #[inline]
    pub fn conj(&self) -> Complex {
        Complex {
            real: self.real,
            imag: -self.imag
        }
    }
}

impl Add<Complex> for Complex {
    type Output = Complex;
    fn add(self, other: Complex) -> Complex {
        let x = self.real() + other.real();
        let y = self.imag() + other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Sub<Complex> for Complex {
    type Output = Complex;
    fn sub(self, other: Complex) -> Complex {
        let x = self.real() - other.real();
        let y = self.imag() - other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Neg for Complex {
    type Output = Complex;
    fn neg(self) -> Complex {
        Complex{
            real: -self.real,
            imag: -self.imag,
        }
    }
}

impl Mul<Complex> for Complex {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        let x = self.real() * other.real() - self.imag() * other.imag();
        let y = self.real() * other.imag() + self.imag() * other.real();
        Complex::cartesian(x, y)
    }
}

impl Mul<f64> for Complex {
    type Output = Complex;
    fn mul(self, other: f64) -> Complex {
        Complex::cartesian(self.real() * other, self.imag() * other)
    }
}

impl Mul<Complex> for f64 {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        Complex::cartesian(self * other.real(), self * other.imag())
    }
}

impl Div<Complex> for Complex {
    type Output = Complex;
    fn div(self, other: Complex) -> Complex {
        let r = other.norm2();
        let x = self.real() * other.real() + self.imag() * other.imag();
        let y = - self.real() * other.imag() + self.imag() * other.real();

        Complex::cartesian(x / r, y / r)
    }
}

impl Div<f64> for Complex {
    type Output = Complex;
    fn div(self, other: f64) -> Complex {
        let norm = self.norm() / other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

impl Zero for Complex {
    fn zero() -> Complex {
        Complex::cartesian(0.0, 0.0)
    }

    fn is_zero(&self) -> bool {
        self.norm2() == 0.0
    }
}

impl One for Complex {
    fn one() -> Complex {
        Complex::cartesian(1.0, 0.0)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::f64::consts;

    #[test]
    fn norm() {
        let c = Complex::polar(3.0, 5.0);
        assert_approx_eq!(c.norm(), 3.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_approx_eq!(c.norm(), 3.0);
    }

    #[test]
    fn phase() {
        // Phase is between 0 and 2π
        for &phase in &[-consts::PI, -3.1, -1.5, 0.0, 0.1, 2.0, 3.1] {
            let c = Complex::polar(1.0, phase);
            assert_approx_eq!(c.phase(), phase);
        }

        let c = Complex::polar(1.0, -8.0);
        assert_approx_eq!(c.phase(), -8.0 + 2.0 * consts::PI);

        let c = Complex::polar(1.0, 12.0);
        assert_approx_eq!(c.phase(), 12.0 - 4.0 * consts::PI);

        let c = Complex::polar(1.0, consts::PI);
        assert_eq!(c.phase(), consts::PI);
        let c = Complex::polar(1.0, -consts::PI);
        assert_eq!(c.phase(), -consts::PI);

        let c = Complex::polar(3.0, 0.0);
        assert_eq!(c.phase(), 0.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_eq!(c.phase(), -consts::PI);
    }

    #[test]
    fn conj() {
        let c = Complex::cartesian(3.0, 5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, -5.0));

        let c = Complex::cartesian(3.0, -5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 5.0));

        let c = Complex::cartesian(3.0, 0.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 0.0));
    }

    #[test]
    fn cartesian() {
        let c = Complex::polar(1.0, 0.0);
        assert_approx_eq!(c.real(), 1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::PI);
        assert_approx_eq!(c.real(), -1.0);
        assert_approx_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_2);
        assert_approx_eq!(c.real(), 0.0);
        assert_approx_eq!(c.imag(), 1.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_4);
        assert_approx_eq!(c.real(), consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.imag(), consts::FRAC_1_SQRT_2);

        let c = Complex::cartesian(consts::FRAC_1_SQRT_2, consts::FRAC_1_SQRT_2);
        assert_approx_eq!(c.norm(), 1.0);
        assert_approx_eq!(c.phase(), consts::FRAC_PI_4);
    }

    #[test]
    fn add() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a + b;

        assert_eq!(c.real(), a.real() + b.real());
        assert_eq!(c.imag(), a.imag() + b.imag());
    }

    #[test]
    fn sub() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a - b;

        assert_eq!(c.real(), a.real() - b.real());
        assert_eq!(c.imag(), a.imag() - b.imag());
    }

    #[test]
    fn neg() {
        let a = Complex::polar(2.0, 0.2);
        let c = -a;

        assert_approx_eq!(c.norm(), a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);

        assert_approx_eq!(c.real(), - a.real());
        assert_approx_eq!(c.imag(), - a.imag());
    }

    #[test]
    fn mul() {
        let a = Complex::polar(2.0, 1.4);
        let b = Complex::polar(1.0, 0.5);
        let c = a * b;

        assert_eq!(c.norm(), a.norm() * b.norm());
        assert_eq!(c.phase(), a.phase() + b.phase());

        let c = 3.0 * a;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = a * 3.0;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = -2.0 * a;
        assert_eq!(c.norm(), 2.0 * a.norm());
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }

    #[test]
    fn div() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a / b;

        assert_eq!(c.norm(), a.norm() / b.norm());
        assert_eq!(c.phase(), a.phase() - b.phase());

        let c = a / 3.0;
        assert_eq!(c.norm(), a.norm()/3.0);
        assert_approx_eq!(c.phase(), a.phase());

        let c = a / (-2.0);
        assert_eq!(c.norm(), a.norm()/2.0);
        assert_approx_eq!(c.phase(), a.phase() - consts::PI);
    }
}
<|endoftext|>


<commit_before>
//! Glyph caching

use error::Error;
use freetype::ffi;
use freetype;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use graphics;

use Texture;

/// The type alias for the font size.
pub type FontSize = u32;

/// The type alias for font characters.
pub type Character = graphics::character::Character<Texture>;

/// A struct used for caching rendered font.
pub struct GlyphCache {
    /// The font face.
    pub face: freetype::Face,
    data: HashMap<FontSize, HashMap<char, Character>>,
}

impl GlyphCache {

    /// Constructor for a GlyphCache.
    pub fn new(font: &Path) -> Result<GlyphCache, Error> {
        let freetype = match freetype::Library::init() {
            Ok(freetype) => freetype,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        let face = match freetype.new_face(font, 0) {
            Ok(face) => face,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        Ok(GlyphCache {
            face: face,
            data: HashMap::new(),
        })
    }

    /// Load a `Character` from a given `FontSize` and `char`.
    fn load_character(&mut self, size: FontSize, ch: char) {
        // Don't load glyph twice
        if self.data.get(&size)
            .map(|entry| entry.contains_key(&ch))
            .unwrap_or(false) { return; }

        self.face.set_pixel_sizes(0, size).unwrap();
        self.face.load_char(ch as ffi::FT_ULong, freetype::face::DEFAULT).unwrap();
        let glyph = self.face.glyph().get_glyph().unwrap();
        let bitmap_glyph = glyph.to_bitmap(freetype::render_mode::RenderMode::Normal, None)
            .unwrap();
        let bitmap = bitmap_glyph.bitmap();
        let texture = Texture::from_memory_alpha(bitmap.buffer(),
                                                 bitmap.width() as u32,
                                                 bitmap.rows() as u32).unwrap();
        let glyph_size = glyph.advance();
        self.data[size].insert(ch, Character {
            offset: [
                    bitmap_glyph.left() as f64,
                    bitmap_glyph.top() as f64
                ],
            size: [
                    (glyph_size.x >> 16) as f64,
                    (glyph_size.y >> 16) as f64
                ],
            texture: texture,
        });
    }

    /// Load all characters in the `chars` iterator for `size`
    pub fn preload_chars<I: Iterator<Item = char>>(&mut self, size: FontSize, mut chars: I) {
        for ch in chars {
            self.load_character(size, ch);
        }
    }

    /// Load all the printable ASCII characters for `size`. Includes space.
    pub fn preload_printable_ascii(&mut self, size: FontSize) {
        // [0x20, 0x7F) contains all printable ASCII characters ([' ', '~'])
        self.preload_chars(size, range(0x20u8, 0x7F).map(|ch| ch as char));
    }

    /// Return `ch` for `size` if it's already cached. Don't load.
    /// See the `preload_*` functions.
    pub fn opt_character(&self, size: FontSize, ch: char) -> Option<&Character> {
        self.data.get(&size).and_then(|entry| entry.get(&ch))
    }
}

impl graphics::character::CharacterCache for GlyphCache {
    type Texture = Texture;

    fn character(&mut self, size: FontSize, ch: char) -> &Character {
        match {
            match self.data.entry(size) {
                Vacant(entry) => entry.insert(HashMap::new()),
                Occupied(entry) => entry.into_mut(),
            }
        }.contains_key(&ch) {
            true => &self.data[size][ch],
            false => { self.load_character(size, ch); &self.data[size][ch] }
        }
    }
}
<commit_msg>Fix integer type from ffi::FT_ULong to usize<commit_after>
//! Glyph caching

use error::Error;
use freetype;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use graphics;

use Texture;

/// The type alias for the font size.
pub type FontSize = u32;

/// The type alias for font characters.
pub type Character = graphics::character::Character<Texture>;

/// A struct used for caching rendered font.
pub struct GlyphCache {
    /// The font face.
    pub face: freetype::Face,
    data: HashMap<FontSize, HashMap<char, Character>>,
}

impl GlyphCache {

    /// Constructor for a GlyphCache.
    pub fn new(font: &Path) -> Result<GlyphCache, Error> {
        let freetype = match freetype::Library::init() {
            Ok(freetype) => freetype,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        let face = match freetype.new_face(font, 0) {
            Ok(face) => face,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        Ok(GlyphCache {
            face: face,
            data: HashMap::new(),
        })
    }

    /// Load a `Character` from a given `FontSize` and `char`.
    fn load_character(&mut self, size: FontSize, ch: char) {
        // Don't load glyph twice
        if self.data.get(&size)
            .map(|entry| entry.contains_key(&ch))
            .unwrap_or(false) { return; }

        self.face.set_pixel_sizes(0, size).unwrap();
        self.face.load_char(ch as usize, freetype::face::DEFAULT).unwrap();
        let glyph = self.face.glyph().get_glyph().unwrap();
        let bitmap_glyph = glyph.to_bitmap(freetype::render_mode::RenderMode::Normal, None)
            .unwrap();
        let bitmap = bitmap_glyph.bitmap();
        let texture = Texture::from_memory_alpha(bitmap.buffer(),
                                                 bitmap.width() as u32,
                                                 bitmap.rows() as u32).unwrap();
        let glyph_size = glyph.advance();
        self.data[size].insert(ch, Character {
            offset: [
                    bitmap_glyph.left() as f64,
                    bitmap_glyph.top() as f64
                ],
            size: [
                    (glyph_size.x >> 16) as f64,
                    (glyph_size.y >> 16) as f64
                ],
            texture: texture,
        });
    }

    /// Load all characters in the `chars` iterator for `size`
    pub fn preload_chars<I: Iterator<Item = char>>(&mut self, size: FontSize, mut chars: I) {
        for ch in chars {
            self.load_character(size, ch);
        }
    }

    /// Load all the printable ASCII characters for `size`. Includes space.
    pub fn preload_printable_ascii(&mut self, size: FontSize) {
        // [0x20, 0x7F) contains all printable ASCII characters ([' ', '~'])
        self.preload_chars(size, range(0x20u8, 0x7F).map(|ch| ch as char));
    }

    /// Return `ch` for `size` if it's already cached. Don't load.
    /// See the `preload_*` functions.
    pub fn opt_character(&self, size: FontSize, ch: char) -> Option<&Character> {
        self.data.get(&size).and_then(|entry| entry.get(&ch))
    }
}

impl graphics::character::CharacterCache for GlyphCache {
    type Texture = Texture;

    fn character(&mut self, size: FontSize, ch: char) -> &Character {
        match {
            match self.data.entry(size) {
                Vacant(entry) => entry.insert(HashMap::new()),
                Occupied(entry) => entry.into_mut(),
            }
        }.contains_key(&ch) {
            true => &self.data[size][ch],
            false => { self.load_character(size, ch); &self.data[size][ch] }
        }
    }
}
<|endoftext|>


<commit_before>use sdl2;
use sdl2_ttf;

static SCREEN_WIDTH : isize = 800;
static SCREEN_HEIGHT : isize = 600;

// fail when error
macro_rules! trying(
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("failed: {}", e) })
);

// hadle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        sdl2::rect::Rect::new($x as i32, $y as i32, $w as i32, $h as i32)
    )
);

pub fn main(filename: &Path) {
    sdl2::init(sdl2::INIT_VIDEO);
    sdl2_ttf::init();

    let window = trying!(sdl2::video::Window::new(
            "rust-sdl2 demo: Video", sdl2::video::WindowPos::PosCentered,
            sdl2::video::WindowPos::PosCentered, SCREEN_WIDTH, SCREEN_HEIGHT, sdl2::video::OPENGL));

    let renderer = trying!(sdl2::render::Renderer::from_window(
            window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED));

    // Load a font
    let font = trying!(sdl2_ttf::Font::from_file(filename, 128));

    // render a surface, and convert it to a texture bound to the renderer
    let surface = trying!(font.render_str_blended("Hello Rust!", sdl2::pixels::Color::RGBA(255, 0, 0, 255)));
    let texture = trying!(renderer.create_texture_from_surface(&surface));

    renderer.set_draw_color(sdl2::pixels::Color::RGBA(195, 217, 255, 255));
    renderer.clear();

    let (w, h) = match texture.query() {
        Ok(q) => (q.width, q.height),
        Err(err) => panic!(format!("Failed to query texture: {}", err))
    };
    renderer.copy(&texture, None, Some(rect!((SCREEN_WIDTH - w)/ 2, (SCREEN_HEIGHT - h)/ 2, w, h)));

    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::Event::Quit(_) => break 'main,
                sdl2::event::Event::KeyDown(_, _, key, _, _, _) => {
                    if key == sdl2::keycode::KeyCode::Escape {
                        break 'main
                    }
                }
                _ => {}
            }
        }
    }
    sdl2_ttf::quit();
    sdl2::quit();
}
<commit_msg>Update demo, use drawer<commit_after>use sdl2;
use sdl2_ttf;

static SCREEN_WIDTH : isize = 800;
static SCREEN_HEIGHT : isize = 600;

// fail when error
macro_rules! trying(
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("failed: {}", e) })
);

// hadle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        sdl2::rect::Rect::new($x as i32, $y as i32, $w as i32, $h as i32)
    )
);

pub fn main(filename: &Path) {
    sdl2::init(sdl2::INIT_VIDEO);
    sdl2_ttf::init();

    let window = trying!(sdl2::video::Window::new(
            "rust-sdl2 demo: Video", sdl2::video::WindowPos::PosCentered,
            sdl2::video::WindowPos::PosCentered, SCREEN_WIDTH, SCREEN_HEIGHT, sdl2::video::OPENGL));

    let renderer = trying!(sdl2::render::Renderer::from_window(
            window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED));

    // Load a font
    let font = trying!(sdl2_ttf::Font::from_file(filename, 128));

    // render a surface, and convert it to a texture bound to the renderer
    let surface = trying!(font.render_str_blended("Hello Rust!", sdl2::pixels::Color::RGBA(255, 0, 0, 255)));
    let mut texture = trying!(renderer.create_texture_from_surface(&surface));

    let mut drawer = renderer.drawer();
    drawer.set_draw_color(sdl2::pixels::Color::RGBA(195, 217, 255, 255));
    drawer.clear();

    let (w, h) = match texture.query() {
        Ok(q) => (q.width, q.height),
        Err(err) => panic!(format!("Failed to query texture: {}", err))
    };
    drawer.copy(&mut texture, None, Some(rect!((SCREEN_WIDTH - w)/ 2, (SCREEN_HEIGHT - h)/ 2, w, h)));

    drawer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::Event::Quit(_) => break 'main,
                sdl2::event::Event::KeyDown(_, _, key, _, _, _) => {
                    if key == sdl2::keycode::KeyCode::Escape {
                        break 'main
                    }
                }
                _ => {}
            }
        }
    }
    sdl2_ttf::quit();
    sdl2::quit();
}
<|endoftext|>


<commit_before>use super::prelude::*;

use conduit_cookie::RequestSession;
use diesel::prelude::*;

use crate::db::RequestTransaction;
use crate::util::errors::{std_error, CargoResult, ChainError, Unauthorized};

use crate::models::User;
use crate::schema::users;

#[derive(Debug, Clone, Copy)]
pub struct CurrentUser;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum AuthenticationSource {
    SessionCookie,
    ApiToken,
}

impl Middleware for CurrentUser {
    fn before(&self, req: &mut dyn Request) -> Result<(), Box<dyn Error + Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = {
            req.session()
                .get("user_id")
                .and_then(|s| s.parse::<i32>().ok())
        };

        let conn = req.db_conn().map_err(std_error)?;

        if let Some(id) = id {
            // If it did, look for a user in the database with the given `user_id`
            let maybe_user = users::table.find(id).first::<User>(&*conn);
            if let Ok(user) = maybe_user {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions()
                    .insert(AuthenticationSource::SessionCookie);
            }
        } else {
            // Otherwise, look for an `Authorization` header on the request
            // and try to find a user in the database with a matching API token
            let user = if let Some(headers) = req.headers().find("Authorization") {
                User::find_by_api_token(&conn, headers[0]).ok()
            } else {
                None
            };
            if let Some(user) = user {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions().insert(AuthenticationSource::ApiToken);
            }
        }

        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
    fn authentication_source(&self) -> CargoResult<AuthenticationSource>;
}

impl<'a> RequestUser for dyn Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions()
            .find::<User>()
            .chain_error(|| Unauthorized)
    }

    fn authentication_source(&self) -> CargoResult<AuthenticationSource> {
        self.extensions()
            .find::<AuthenticationSource>()
            .cloned()
            .chain_error(|| Unauthorized)
    }
}
<commit_msg>Hold onto authorization header with ApiToken source<commit_after>use super::prelude::*;

use conduit_cookie::RequestSession;
use diesel::prelude::*;

use crate::db::RequestTransaction;
use crate::util::errors::{std_error, CargoResult, ChainError, Unauthorized};

use crate::models::User;
use crate::schema::users;

#[derive(Debug, Clone, Copy)]
pub struct CurrentUser;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum AuthenticationSource {
    SessionCookie,
    ApiToken { auth_header: String },
}

impl Middleware for CurrentUser {
    fn before(&self, req: &mut dyn Request) -> Result<(), Box<dyn Error + Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = {
            req.session()
                .get("user_id")
                .and_then(|s| s.parse::<i32>().ok())
        };

        let conn = req.db_conn().map_err(std_error)?;

        if let Some(id) = id {
            // If it did, look for a user in the database with the given `user_id`
            let maybe_user = users::table.find(id).first::<User>(&*conn);
            if let Ok(user) = maybe_user {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions()
                    .insert(AuthenticationSource::SessionCookie);
            }
        } else {
            // Otherwise, look for an `Authorization` header on the request
            // and try to find a user in the database with a matching API token
            let user_auth = req.headers().find("Authorization").and_then(|headers| {
                let auth_header = headers[0].to_string();

                User::find_by_api_token(&conn, &auth_header)
                    .ok()
                    .map(|user| (AuthenticationSource::ApiToken { auth_header }, user))
            });

            if let Some((api_token, user)) = user_auth {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions().insert(api_token);
            }
        }

        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
    fn authentication_source(&self) -> CargoResult<AuthenticationSource>;
}

impl<'a> RequestUser for dyn Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions()
            .find::<User>()
            .chain_error(|| Unauthorized)
    }

    fn authentication_source(&self) -> CargoResult<AuthenticationSource> {
        self.extensions()
            .find::<AuthenticationSource>()
            .cloned()
            .chain_error(|| Unauthorized)
    }
}
<|endoftext|>


<commit_before>import std::vec;
import std::str;
import std::option;
import std::option::some;
import std::option::none;
import std::map::hashmap;

import driver::session;
import ast::ident;
import front::parser::parser;
import front::parser::spanned;
import front::parser::new_parser;
import front::parser::parse_mod_items;
import util::common;
import util::common::filename;
import util::common::span;
import util::common::new_str_hash;

// Simple dynamic-typed value type for eval_expr.
tag val {
    val_bool(bool);
    val_int(int);
    val_str(str);
}

tag eval_mode {
    mode_depend;
    mode_parse;
}

type env = vec[tup(ident, val)];
type ctx = @rec(parser p,
                eval_mode mode,
                mutable vec[str] deps,
                session::session sess,
                mutable uint chpos,
                mutable uint next_ann);

fn mk_env() -> env {
    let env e = [];
    ret e;
}

fn val_is_bool(val v) -> bool {
    alt (v) {
        case (val_bool(_)) { ret true; }
        case (_) { }
    }
    ret false;
}

fn val_is_int(val v) -> bool {
    alt (v) {
        case (val_int(_)) { ret true; }
        case (_) { }
    }
    ret false;
}

fn val_is_str(val v) -> bool {
    alt (v) {
        case (val_str(_)) { ret true; }
        case (_) { }
    }
    ret false;
}

fn val_as_bool(val v) -> bool {
    alt (v) {
        case (val_bool(?b)) { ret b; }
        case (_) { }
    }
    fail;
}

fn val_as_int(val v) -> int {
    alt (v) {
        case (val_int(?i)) { ret i; }
        case (_) { }
    }
    fail;
}

fn val_as_str(val v) -> str {
    alt (v) {
        case (val_str(?s)) { ret s; }
        case (_) { }
    }
    fail;
}

fn lookup(session::session sess, env e, span sp, ident i) -> val {
    for (tup(ident, val) pair in e) {
        if (str::eq(i, pair._0)) {
            ret pair._1;
        }
    }
    sess.span_err(sp, "unknown variable: " + i);
    fail;
}

fn eval_lit(ctx cx, span sp, @ast::lit lit) -> val {
    alt (lit.node) {
        case (ast::lit_bool(?b)) { ret val_bool(b); }
        case (ast::lit_int(?i)) { ret val_int(i); }
        case (ast::lit_str(?s,_)) { ret val_str(s); }
        case (_) {
            cx.sess.span_err(sp, "evaluating unsupported literal");
        }
    }
    fail;
}

fn eval_expr(ctx cx, env e, @ast::expr x) -> val {
    alt (x.node) {
        case (ast::expr_path(?pth, _)) {
            if (vec::len[ident](pth.node.idents) == 1u &&
                vec::len[@ast::ty](pth.node.types) == 0u) {
                ret lookup(cx.sess, e, x.span, pth.node.idents.(0));
            }
            cx.sess.span_err(x.span, "evaluating structured path-name");
        }

        case (ast::expr_lit(?lit, _)) {
            ret eval_lit(cx, x.span, lit);
        }

        case (ast::expr_unary(?op, ?a, _)) {
            auto av = eval_expr(cx, e, a);
            alt (op) {
                case (ast::not) {
                    if (val_is_bool(av)) {
                        ret val_bool(!val_as_bool(av));
                    }
                    cx.sess.span_err(x.span, "bad types in '!' expression");
                }
                case (_) {
                    cx.sess.span_err(x.span, "evaluating unsupported unop");
                }
            }
        }

        case (ast::expr_binary(?op, ?a, ?b, _)) {
            auto av = eval_expr(cx, e, a);
            auto bv = eval_expr(cx, e, b);
            alt (op) {
                case (ast::add) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) + val_as_int(bv));
                    }
                    if (val_is_str(av) && val_is_str(bv)) {
                        ret val_str(val_as_str(av) + val_as_str(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '+' expression");
                }

                case (ast::sub) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) - val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '-' expression");
                }

                case (ast::mul) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) * val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '*' expression");
                }

                case (ast::div) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) / val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '/' expression");
                }

                case (ast::rem) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) % val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '%' expression");
                }

                case (ast::and) {
                    if (val_is_bool(av) && val_is_bool(bv)) {
                        ret val_bool(val_as_bool(av) && val_as_bool(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '&&' expression");
                }

                case (ast::or) {
                    if (val_is_bool(av) && val_is_bool(bv)) {
                        ret val_bool(val_as_bool(av) || val_as_bool(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '||' expression");
                }

                case (ast::eq) {
                    ret val_bool(val_eq(cx.sess, x.span, av, bv));
                }

                case (ast::ne) {
                    ret val_bool(! val_eq(cx.sess, x.span, av, bv));
                }

                case (_) {
                    cx.sess.span_err(x.span, "evaluating unsupported binop");
                }
            }
        }
        case (_) {
            cx.sess.span_err(x.span, "evaluating unsupported expression");
        }
    }
    fail;
}

fn val_eq(session::session sess, span sp, val av, val bv) -> bool {
    if (val_is_bool(av) && val_is_bool(bv)) {
        ret val_as_bool(av) == val_as_bool(bv);
    }
    if (val_is_int(av) && val_is_int(bv)) {
        ret val_as_int(av) == val_as_int(bv);
    }
    if (val_is_str(av) && val_is_str(bv)) {
        ret str::eq(val_as_str(av),
                    val_as_str(bv));
    }
    sess.span_err(sp, "bad types in comparison");
    fail;
}

fn eval_crate_directives(ctx cx,
                                env e,
                                vec[@ast::crate_directive] cdirs,
                                str prefix,
                                &mutable vec[@ast::view_item] view_items,
                                &mutable vec[@ast::item] items) {

    for (@ast::crate_directive sub_cdir in cdirs) {
        eval_crate_directive(cx, e, sub_cdir, prefix,
                             view_items, items);
    }
}

fn eval_crate_directives_to_mod(ctx cx, env e,
                                       vec[@ast::crate_directive] cdirs,
                                       str prefix) -> ast::_mod {
    let vec[@ast::view_item] view_items = [];
    let vec[@ast::item] items = [];

    eval_crate_directives(cx, e, cdirs, prefix,
                          view_items, items);

    ret rec(view_items=view_items, items=items);
}

fn eval_crate_directive_block(ctx cx,
                                     env e,
                                     &ast::block blk,
                                     str prefix,
                                     &mutable vec[@ast::view_item] view_items,
                                     &mutable vec[@ast::item] items) {

    for (@ast::stmt s in blk.node.stmts) {
        alt (s.node) {
            case (ast::stmt_crate_directive(?cdir)) {
                eval_crate_directive(cx, e, cdir, prefix,
                                     view_items, items);
            }
            case (_) {
                cx.sess.span_err(s.span,
                                 "unsupported stmt in crate-directive block");
            }
        }
    }
}

fn eval_crate_directive_expr(ctx cx,
                                    env e,
                                    @ast::expr x,
                                    str prefix,
                                    &mutable vec[@ast::view_item] view_items,
                                    &mutable vec[@ast::item] items) {
    alt (x.node) {

        case (ast::expr_if(?cond, ?thn, ?elopt, _)) {
            auto cv = eval_expr(cx, e, cond);
            if (!val_is_bool(cv)) {
                cx.sess.span_err(x.span, "bad cond type in 'if'");
            }

            if (val_as_bool(cv)) {
                ret eval_crate_directive_block(cx, e, thn, prefix,
                                               view_items, items);
            }

            alt (elopt) {
                case (some(?els)) {
                    ret eval_crate_directive_expr(cx, e, els, prefix,
                                                  view_items, items);
                }
                case (_) {
                    // Absent-else is ok.
                }
            }
        }

        case (ast::expr_alt(?v, ?arms, _)) {
            auto vv = eval_expr(cx, e, v);
            for (ast::arm arm in arms) {
                alt (arm.pat.node) {
                    case (ast::pat_lit(?lit, _)) {
                        auto pv = eval_lit(cx, arm.pat.span, lit);
                        if (val_eq(cx.sess, arm.pat.span, vv, pv)) {
                            ret eval_crate_directive_block
                                (cx, e, arm.block, prefix, view_items, items);
                        }
                    }
                    case (ast::pat_wild(_)) {
                        ret eval_crate_directive_block
                            (cx, e, arm.block, prefix,
                             view_items, items);
                    }
                    case (_) {
                        cx.sess.span_err(arm.pat.span,
                                         "bad pattern type in 'alt'");
                    }
                }
            }
            cx.sess.span_err(x.span, "no cases matched in 'alt'");
        }

        case (ast::expr_block(?block, _)) {
            ret eval_crate_directive_block(cx, e, block, prefix,
                                           view_items, items);
        }

        case (_) {
            cx.sess.span_err(x.span, "unsupported expr type");
        }
    }
}

fn eval_crate_directive(ctx cx,
                               env e,
                               @ast::crate_directive cdir,
                               str prefix,
                               &mutable vec[@ast::view_item] view_items,
                               &mutable vec[@ast::item] items) {
    alt (cdir.node) {

        case (ast::cdir_let(?id, ?x, ?cdirs)) {
            auto v = eval_expr(cx, e, x);
            auto e0 = [tup(id, v)] + e;
            eval_crate_directives(cx, e0, cdirs, prefix,
                                  view_items, items);
        }

        case (ast::cdir_expr(?x)) {
            eval_crate_directive_expr(cx, e, x, prefix,
                                      view_items, items);
        }

        case (ast::cdir_src_mod(?id, ?file_opt)) {

            auto file_path = id + ".rs";
            alt (file_opt) {
                case (some(?f)) {
                    file_path = f;
                }
                case (none) {}
            }

            auto full_path = prefix + std::fs::path_sep() + file_path;

            if (cx.mode == mode_depend) {
                cx.deps += [full_path];
                ret;
            }

            auto start_id = cx.p.next_def_id();
            auto p0 = new_parser(cx.sess, e, start_id, full_path, cx.chpos,
                                 cx.next_ann);
            auto m0 = parse_mod_items(p0, token::EOF);
            auto next_id = p0.next_def_id();
            // Thread defids and chpos through the parsers
            cx.p.set_def(next_id._1);
            cx.chpos = p0.get_chpos();
            cx.next_ann = p0.next_ann_num();
            auto im = ast::item_mod(id, m0, next_id);
            auto i = @spanned(cdir.span.lo, cdir.span.hi, im);
            vec::push[@ast::item](items, i);
        }

        case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs)) {

            auto path = id;
            alt (dir_opt) {
                case (some(?d)) {
                    path = d;
                }
                case (none) {}
            }

            auto full_path = prefix + std::fs::path_sep() + path;
            auto m0 = eval_crate_directives_to_mod(cx, e, cdirs, full_path);
            auto im = ast::item_mod(id, m0, cx.p.next_def_id());
            auto i = @spanned(cdir.span.lo, cdir.span.hi, im);
            vec::push[@ast::item](items, i);
        }

        case (ast::cdir_view_item(?vi)) {
            vec::push[@ast::view_item](view_items, vi);
        }

        case (ast::cdir_meta(?vi, ?mi)) {
            if (vi == ast::export_meta) {
                cx.sess.add_metadata(mi);
            }
        }

        case (ast::cdir_syntax(?pth)) {}
        case (ast::cdir_auth(?pth, ?eff)) {}
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>rustc: Modernize front::eval<commit_after>import std::vec;
import std::str;
import std::option;
import std::option::some;
import std::option::none;
import std::map::hashmap;

import driver::session;
import ast::ident;
import front::parser::parser;
import front::parser::spanned;
import front::parser::new_parser;
import front::parser::parse_mod_items;
import util::common;
import util::common::filename;
import util::common::span;
import util::common::new_str_hash;

// Simple dynamic-typed value type for eval_expr.
tag val {
    val_bool(bool);
    val_int(int);
    val_str(str);
}

tag eval_mode {
    mode_depend;
    mode_parse;
}

type env = vec[tup(ident, val)];
type ctx = @rec(parser p,
                eval_mode mode,
                mutable vec[str] deps,
                session::session sess,
                mutable uint chpos,
                mutable uint next_ann);

fn mk_env() -> env {
    ret [];
}

fn val_is_bool(val v) -> bool {
    alt (v) {
        case (val_bool(_)) { true }
        case (_) { false }
    }
}

fn val_is_int(val v) -> bool {
    alt (v) {
        case (val_int(_)) { true }
        case (_) { false }
    }
}

fn val_is_str(val v) -> bool {
    alt (v) {
        case (val_str(_)) { true }
        case (_) { false }
    }
}

fn val_as_bool(val v) -> bool {
    alt (v) {
        case (val_bool(?b)) { b }
        case (_) { fail }
    }
}

fn val_as_int(val v) -> int {
    alt (v) {
        case (val_int(?i)) { i }
        case (_) { fail }
    }
}

fn val_as_str(val v) -> str {
    alt (v) {
        case (val_str(?s)) { s }
        case (_) { fail }
    }
}

fn lookup(session::session sess, env e, span sp, ident i) -> val {
    for (tup(ident, val) pair in e) {
        if (str::eq(i, pair._0)) {
            ret pair._1;
        }
    }
    sess.span_err(sp, "unknown variable: " + i)
}

fn eval_lit(ctx cx, span sp, @ast::lit lit) -> val {
    alt (lit.node) {
        case (ast::lit_bool(?b)) { val_bool(b) }
        case (ast::lit_int(?i)) { val_int(i) }
        case (ast::lit_str(?s,_)) { val_str(s) }
        case (_) {
            cx.sess.span_err(sp, "evaluating unsupported literal")
        }
    }
}

fn eval_expr(ctx cx, env e, @ast::expr x) -> val {
    alt (x.node) {
        case (ast::expr_path(?pth, _)) {
            if (vec::len[ident](pth.node.idents) == 1u &&
                vec::len[@ast::ty](pth.node.types) == 0u) {
                ret lookup(cx.sess, e, x.span, pth.node.idents.(0));
            }
            cx.sess.span_err(x.span, "evaluating structured path-name");
        }

        case (ast::expr_lit(?lit, _)) {
            ret eval_lit(cx, x.span, lit);
        }

        case (ast::expr_unary(?op, ?a, _)) {
            auto av = eval_expr(cx, e, a);
            alt (op) {
                case (ast::not) {
                    if (val_is_bool(av)) {
                        ret val_bool(!val_as_bool(av));
                    }
                    cx.sess.span_err(x.span, "bad types in '!' expression");
                }
                case (_) {
                    cx.sess.span_err(x.span, "evaluating unsupported unop");
                }
            }
        }

        case (ast::expr_binary(?op, ?a, ?b, _)) {
            auto av = eval_expr(cx, e, a);
            auto bv = eval_expr(cx, e, b);
            alt (op) {
                case (ast::add) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) + val_as_int(bv));
                    }
                    if (val_is_str(av) && val_is_str(bv)) {
                        ret val_str(val_as_str(av) + val_as_str(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '+' expression");
                }

                case (ast::sub) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) - val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '-' expression");
                }

                case (ast::mul) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) * val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '*' expression");
                }

                case (ast::div) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) / val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '/' expression");
                }

                case (ast::rem) {
                    if (val_is_int(av) && val_is_int(bv)) {
                        ret val_int(val_as_int(av) % val_as_int(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '%' expression");
                }

                case (ast::and) {
                    if (val_is_bool(av) && val_is_bool(bv)) {
                        ret val_bool(val_as_bool(av) && val_as_bool(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '&&' expression");
                }

                case (ast::or) {
                    if (val_is_bool(av) && val_is_bool(bv)) {
                        ret val_bool(val_as_bool(av) || val_as_bool(bv));
                    }
                    cx.sess.span_err(x.span, "bad types in '||' expression");
                }

                case (ast::eq) {
                    ret val_bool(val_eq(cx.sess, x.span, av, bv));
                }

                case (ast::ne) {
                    ret val_bool(! val_eq(cx.sess, x.span, av, bv));
                }

                case (_) {
                    cx.sess.span_err(x.span, "evaluating unsupported binop");
                }
            }
        }
        case (_) {
            cx.sess.span_err(x.span, "evaluating unsupported expression");
        }
    }
    fail;
}

fn val_eq(session::session sess, span sp, val av, val bv) -> bool {
    if (val_is_bool(av) && val_is_bool(bv)) {
        val_as_bool(av) == val_as_bool(bv)
    } else if (val_is_int(av) && val_is_int(bv)) {
        val_as_int(av) == val_as_int(bv)
    } else if (val_is_str(av) && val_is_str(bv)) {
        str::eq(val_as_str(av),
                val_as_str(bv))
    } else {
        sess.span_err(sp, "bad types in comparison")
    }
}

fn eval_crate_directives(ctx cx,
                                env e,
                                vec[@ast::crate_directive] cdirs,
                                str prefix,
                                &mutable vec[@ast::view_item] view_items,
                                &mutable vec[@ast::item] items) {

    for (@ast::crate_directive sub_cdir in cdirs) {
        eval_crate_directive(cx, e, sub_cdir, prefix,
                             view_items, items);
    }
}

fn eval_crate_directives_to_mod(ctx cx, env e,
                                       vec[@ast::crate_directive] cdirs,
                                       str prefix) -> ast::_mod {
    let vec[@ast::view_item] view_items = [];
    let vec[@ast::item] items = [];

    eval_crate_directives(cx, e, cdirs, prefix,
                          view_items, items);

    ret rec(view_items=view_items, items=items);
}

fn eval_crate_directive_block(ctx cx,
                                     env e,
                                     &ast::block blk,
                                     str prefix,
                                     &mutable vec[@ast::view_item] view_items,
                                     &mutable vec[@ast::item] items) {

    for (@ast::stmt s in blk.node.stmts) {
        alt (s.node) {
            case (ast::stmt_crate_directive(?cdir)) {
                eval_crate_directive(cx, e, cdir, prefix,
                                     view_items, items);
            }
            case (_) {
                cx.sess.span_err(s.span,
                                 "unsupported stmt in crate-directive block");
            }
        }
    }
}

fn eval_crate_directive_expr(ctx cx,
                                    env e,
                                    @ast::expr x,
                                    str prefix,
                                    &mutable vec[@ast::view_item] view_items,
                                    &mutable vec[@ast::item] items) {
    alt (x.node) {

        case (ast::expr_if(?cond, ?thn, ?elopt, _)) {
            auto cv = eval_expr(cx, e, cond);
            if (!val_is_bool(cv)) {
                cx.sess.span_err(x.span, "bad cond type in 'if'");
            }

            if (val_as_bool(cv)) {
                ret eval_crate_directive_block(cx, e, thn, prefix,
                                               view_items, items);
            }

            alt (elopt) {
                case (some(?els)) {
                    ret eval_crate_directive_expr(cx, e, els, prefix,
                                                  view_items, items);
                }
                case (_) {
                    // Absent-else is ok.
                }
            }
        }

        case (ast::expr_alt(?v, ?arms, _)) {
            auto vv = eval_expr(cx, e, v);
            for (ast::arm arm in arms) {
                alt (arm.pat.node) {
                    case (ast::pat_lit(?lit, _)) {
                        auto pv = eval_lit(cx, arm.pat.span, lit);
                        if (val_eq(cx.sess, arm.pat.span, vv, pv)) {
                            ret eval_crate_directive_block
                                (cx, e, arm.block, prefix, view_items, items);
                        }
                    }
                    case (ast::pat_wild(_)) {
                        ret eval_crate_directive_block
                            (cx, e, arm.block, prefix,
                             view_items, items);
                    }
                    case (_) {
                        cx.sess.span_err(arm.pat.span,
                                         "bad pattern type in 'alt'");
                    }
                }
            }
            cx.sess.span_err(x.span, "no cases matched in 'alt'");
        }

        case (ast::expr_block(?block, _)) {
            ret eval_crate_directive_block(cx, e, block, prefix,
                                           view_items, items);
        }

        case (_) {
            cx.sess.span_err(x.span, "unsupported expr type");
        }
    }
}

fn eval_crate_directive(ctx cx,
                               env e,
                               @ast::crate_directive cdir,
                               str prefix,
                               &mutable vec[@ast::view_item] view_items,
                               &mutable vec[@ast::item] items) {
    alt (cdir.node) {

        case (ast::cdir_let(?id, ?x, ?cdirs)) {
            auto v = eval_expr(cx, e, x);
            auto e0 = [tup(id, v)] + e;
            eval_crate_directives(cx, e0, cdirs, prefix,
                                  view_items, items);
        }

        case (ast::cdir_expr(?x)) {
            eval_crate_directive_expr(cx, e, x, prefix,
                                      view_items, items);
        }

        case (ast::cdir_src_mod(?id, ?file_opt)) {

            auto file_path = id + ".rs";
            alt (file_opt) {
                case (some(?f)) {
                    file_path = f;
                }
                case (none) {}
            }

            auto full_path = prefix + std::fs::path_sep() + file_path;

            if (cx.mode == mode_depend) {
                cx.deps += [full_path];
                ret;
            }

            auto start_id = cx.p.next_def_id();
            auto p0 = new_parser(cx.sess, e, start_id, full_path, cx.chpos,
                                 cx.next_ann);
            auto m0 = parse_mod_items(p0, token::EOF);
            auto next_id = p0.next_def_id();
            // Thread defids and chpos through the parsers
            cx.p.set_def(next_id._1);
            cx.chpos = p0.get_chpos();
            cx.next_ann = p0.next_ann_num();
            auto im = ast::item_mod(id, m0, next_id);
            auto i = @spanned(cdir.span.lo, cdir.span.hi, im);
            vec::push[@ast::item](items, i);
        }

        case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs)) {

            auto path = id;
            alt (dir_opt) {
                case (some(?d)) {
                    path = d;
                }
                case (none) {}
            }

            auto full_path = prefix + std::fs::path_sep() + path;
            auto m0 = eval_crate_directives_to_mod(cx, e, cdirs, full_path);
            auto im = ast::item_mod(id, m0, cx.p.next_def_id());
            auto i = @spanned(cdir.span.lo, cdir.span.hi, im);
            vec::push[@ast::item](items, i);
        }

        case (ast::cdir_view_item(?vi)) {
            vec::push[@ast::view_item](view_items, vi);
        }

        case (ast::cdir_meta(?vi, ?mi)) {
            if (vi == ast::export_meta) {
                cx.sess.add_metadata(mi);
            }
        }

        case (ast::cdir_syntax(?pth)) {}
        case (ast::cdir_auth(?pth, ?eff)) {}
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>// TODO: get num cols of terminal dynamically

use super::{Report, ReportKind, RemarkKind};
use code::{FileMap, LineIdx};
use term_painter::{ToStyle, Attr};
use term_painter::Color::*;
use std::default::Default;

/// Options for printing
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PrintOptions {
    /// Use of unicode allowed?
    pub unicode: bool,
    /// Use of colors allowed?
    pub color: bool,
    /// Is line wrapping allowed?
    pub line_wrap: bool,
}

impl Default for PrintOptions {
    fn default() -> Self {
        PrintOptions {
            unicode: true,
            color: true,
            line_wrap: true,
        }
    }
}

pub fn print(rep: &Report, src: &FileMap, _: PrintOptions) {
    // print header
    let title = match rep.kind {
        ReportKind::Error => White.bold().bg(Red).paint("ERROR"),
        ReportKind::Warning => Attr::Bold.bg(Yellow).paint("WARNING"),
    };

    let start = src.get_loc(rep.span.lo);
    let end = src.get_loc(rep.span.hi);
    let line = if start.line != end.line {
        format!("{}-{}", start.line.0, end.line.0)
    } else {
        start.line.0.to_string()
    };

    println!("+---- {} in {} : {} ----+",
        title,
        src.filename(),
        Blue.paint(line)
    );

    for rem in &rep.remarks {
        // print message
        let (title, title_len) = match rem.kind {
            RemarkKind::Error => (Red.paint("error:"), 6),
            RemarkKind::Warning => (Yellow.paint("warning:"), 8),
            RemarkKind::Note => (Green.paint("note:"), 5),
        };

        print!("      =====>  {} ", title);
        // spaces + big arrow + spaces + title + space
        let indent = 6 + 6 + 2 + title_len + 1;
        let block_width = 80 - indent;

        let mut col = 0;
        for word in rem.desc.split_whitespace() {
            let word_len = word.chars().count();
            if col + word_len >= block_width && col != 0 {
                println!("");
                print!("           >  {0:>1$} ", " ", title_len);
                col = 0;
            }
            print!("{} ", White.paint(word));
            col += word_len + 1;
        }
        println!("");

        // print code snippet
        if let Some(span) = rem.span {
            let start = src.get_loc(span.lo);
            let end = src.get_loc(span.hi);

            if start.line == end.line {
                if let Some(line) = src.get_line(start.line) {
                    println!("{:>#4} {} {}",
                        Magenta.bold().paint(start.line),
                        Magenta.bold().paint("|"),
                        line
                    );

                    Yellow.with(|| {
                        println!("       {: <2$}{:-<3$}",
                            " ", "^",
                            start.col.0 as usize,
                            (end.col.0 - start.col.0) as usize
                        );
                    });
                }
            } else {
                for line_idx in start.line.0..end.line.0 + 1 {
                    let line_idx = LineIdx(line_idx);
                    if let Some(line) = src.get_line(line_idx) {
                        println!("{:>#4} {} {}",
                            Magenta.bold().paint(line_idx),
                            Magenta.bold().paint("|"),
                            line
                        );
                    }
                }
            }
            println!("");
        }

    }
    println!("");
}
<commit_msg>Improve readability of error printing a bit by changing colors<commit_after>// TODO: get num cols of terminal dynamically

use super::{Report, ReportKind, RemarkKind};
use code::{FileMap, LineIdx};
use term_painter::{ToStyle, Attr};
use term_painter::Color::*;
use std::default::Default;

/// Options for printing
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PrintOptions {
    /// Use of unicode allowed?
    pub unicode: bool,
    /// Use of colors allowed?
    pub color: bool,
    /// Is line wrapping allowed?
    pub line_wrap: bool,
}

impl Default for PrintOptions {
    fn default() -> Self {
        PrintOptions {
            unicode: true,
            color: true,
            line_wrap: true,
        }
    }
}

pub fn print(rep: &Report, src: &FileMap, _: PrintOptions) {
    // print header
    let title = match rep.kind {
        ReportKind::Error => White.bold().bg(Red).paint("ERROR"),
        ReportKind::Warning => White.bold().bg(Yellow).paint("WARNING"),
    };

    let start = src.get_loc(rep.span.lo);
    let end = src.get_loc(rep.span.hi);
    let line = if start.line != end.line {
        format!("{}-{}", start.line.0, end.line.0)
    } else {
        start.line.0.to_string()
    };

    println!("+---- {} in {} : {} ----+",
        title,
        src.filename(),
        Blue.paint(line)
    );

    for rem in &rep.remarks {
        // print message
        let (title, title_len) = match rem.kind {
            RemarkKind::Error => (Red.paint("error:"), 6),
            RemarkKind::Warning => (Yellow.paint("warning:"), 8),
            RemarkKind::Note => (Green.paint("note:"), 5),
        };

        print!("      =====>  {} ", title);
        // spaces + big arrow + spaces + title + space
        let indent = 6 + 6 + 2 + title_len + 1;
        let block_width = 80 - indent;

        let mut col = 0;
        for word in rem.desc.split_whitespace() {
            let word_len = word.chars().count();
            if col + word_len >= block_width && col != 0 {
                println!("");
                print!("           >  {0:>1$} ", " ", title_len);
                col = 0;
            }
            print!("{} ", White.bold().paint(word));
            col += word_len + 1;
        }
        println!("");

        // print code snippet
        if let Some(span) = rem.span {
            let start = src.get_loc(span.lo);
            let end = src.get_loc(span.hi);

            if start.line == end.line {
                if let Some(line) = src.get_line(start.line) {
                    println!("{:>#4} {} {}",
                        Magenta.bold().paint(start.line),
                        Magenta.bold().paint("|"),
                        line
                    );

                    Yellow.with(|| {
                        println!("       {: <2$}{:-<3$}",
                            " ", "^",
                            start.col.0 as usize,
                            (end.col.0 - start.col.0) as usize
                        );
                    });
                }
            } else {
                for line_idx in start.line.0..end.line.0 + 1 {
                    let line_idx = LineIdx(line_idx);
                    if let Some(line) = src.get_line(line_idx) {
                        println!("{:>#4} {} {}",
                            Magenta.bold().paint(line_idx),
                            Magenta.bold().paint("|"),
                            line
                        );
                    }
                }
            }
            println!("");
        }

    }
    println!("");
}
<|endoftext|>


<commit_before>use super::builder::Builder;
use ast::HeadingLevel;

///
/// HTML generation might need to be customized to invividual use.
/// A `Format` allows to customize output generation (e.g. custom tags, classes, ...)
/// TODO: I need some feedback on the name `Format`
/// TODO: API is only a draft
///
pub trait Format {
    fn heading(&self, builder: &mut Builder, level: HeadingLevel, content: String);
}

pub struct DefaultFormat;

impl Format for DefaultFormat {
    fn heading(&self, builder: &mut Builder, level: HeadingLevel, content: String) {
        let tag = match level {
            HeadingLevel::Level1 => "h1",
            HeadingLevel::Level2 => "h2",
            HeadingLevel::Level3 => "h3",
            HeadingLevel::__NonExhaustive => unreachable!(),
        };

        builder.text_tag(tag, content);
    }
}

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

    #[test]
    fn default_heading() {
        let format = DefaultFormat;
        let mut builder = Builder::new();

        format.heading(
            &mut builder,
            HeadingLevel::Level1,
            "hello world".to_string(),
        );

        assert_eq!("
hello world
", format!("{}", builder.consume()));
    }
}<commit_msg>Add tests for all heading levels<commit_after>use super::builder::Builder;
use ast::HeadingLevel;

///
/// HTML generation might need to be customized to invividual use.
/// A `Format` allows to customize output generation (e.g. custom tags, classes, ...)
/// TODO: I need some feedback on the name `Format`
/// TODO: API is only a draft
///
pub trait Format {
    fn heading(&self, builder: &mut Builder, level: HeadingLevel, content: String);
}

pub struct DefaultFormat;

impl Format for DefaultFormat {
    fn heading(&self, builder: &mut Builder, level: HeadingLevel, content: String) {
        let tag = match level {
            HeadingLevel::Level1 => "h1",
            HeadingLevel::Level2 => "h2",
            HeadingLevel::Level3 => "h3",
            HeadingLevel::__NonExhaustive => unreachable!(),
        };

        builder.text_tag(tag, content);
    }
}

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

    #[test]
    fn default_heading() {
        let format = DefaultFormat;
        let mut builder = Builder::new();

        format.heading(
            &mut builder,
            HeadingLevel::Level1,
            "hello world".to_string(),
        );

        format.heading(&mut builder, HeadingLevel::Level2, "level 2".to_string());
        format.heading(&mut builder, HeadingLevel::Level3, "level 3".to_string());

        assert_eq!("
hello world

level 2

level 3
", format!("{}", builder.consume()));
    }
}<|endoftext|>


<commit_before>use image::{DynamicImage, GenericImage, Rgba};
use colors;
use ops;

pub struct Interpreter {
    pub codel_chooser: CodelChooser,
    pub direction_pointer: Direction,
    image: DynamicImage,
    current_color: Rgba<u8>,
    pub current_size: u32,
    pub stack: Vec<i32>,
}

#[derive(Debug, PartialEq)]
pub enum Direction{
    Left,
    Right,
    Down,
    Up,
}

impl Direction {
    pub fn step(&mut self) {
        *self = match *self {
            Direction::Left => Direction::Up,
            Direction::Right => Direction::Down,
            Direction::Down => Direction::Left,
            Direction::Up => Direction::Right,
        }
    }

    pub fn step_counter(&mut self) {
        *self = match *self {
            Direction::Left => Direction::Down,
            Direction::Right => Direction::Up,
            Direction::Down => Direction::Right,
            Direction::Up => Direction::Left,
        }
    }
}

#[derive(Debug)]
pub enum CodelChooser {
    Right,
    Left,
}

impl CodelChooser {
    pub fn toggle(&mut self) {
        *self = match *self {
            CodelChooser::Right => CodelChooser::Left,
            CodelChooser::Left => CodelChooser::Right,
        };
    }
}

impl Interpreter {
    pub fn new(image: DynamicImage) -> Interpreter {
        Interpreter {
            codel_chooser: CodelChooser::Left,
            direction_pointer: Direction::Right,
            current_color: image.get_pixel(0, 0),
            current_size: 0,
            image: image,
            stack: Vec::new(),
        }
    }

    pub fn run(&mut self) {
        let mut failed_attempts = 0;
        let mut failed_white_attempts = 0;

        // These are here for debugging purposes
        let mut x = 0;
        let mut y = 0;

        loop {
            // If white just sail through until we hit another color
            if self.current_color_code() == 1 {
                let (x_next, y_next) = self.move_step(x, y);
                // If in white and hit boundary or black then step through dp
                if self.restricted(x_next, y_next) {
                    self.codel_chooser.toggle();
                    self.direction_pointer.step();
                    failed_white_attempts += 1;
                } else {
                    x = x_next;
                    y = y_next;
                    self.current_color = self.pixel_at(x, y);
                    failed_attempts = 0;
                    failed_white_attempts = 0;
                }

                if failed_white_attempts == 4 {
                    break;
                }
            } else {
                let (x_next, y_next, size) = self.next_block(x, y);
                // If we are hitting the edge or a black codel try another direction
                if self.restricted(x_next, y_next) {
                    self.update_movement(failed_attempts);
                    failed_attempts += 1;
                } else {
                    // here we move into the next color block after processing the action
                    x = x_next;
                    y = y_next;

                    let next_color = self.pixel_at(x, y);
                    self.current_size = size;
                    self.process_action(&next_color);
                    self.current_color = next_color;
                    failed_attempts = 0;
                    failed_white_attempts = 0;
                }

                if failed_attempts == 8 {
                    break;
                }
            }
        }
    }

    fn process_action(&mut self, next_color: &Rgba<u8>) {
        let color_code = colors::color_code(next_color).unwrap();
        if color_code != 1 {
            let curr_color = self.current_color_code();
            let shade_diff = colors::shade_difference(curr_color, color_code);
            let hue_diff = colors::hue_difference(curr_color, color_code);
            ops::call_op(self, (hue_diff, shade_diff));
        }
    }

    // Based on the number of attempts this either toggles the CC back and forth
    // or updates the current direction of the DP
    fn update_movement(&mut self, attempts: i32) {
        if attempts % 2 == 0 {
            self.codel_chooser.toggle();
        } else {
            self.direction_pointer.step();
        }
    }

    // This method sets the current size after finding the next block
    fn next_block(&mut self, x: i32, y: i32) -> (i32, i32, u32) {
        let marked_size = self.image.width() * self.image.height();
        let mut marked = vec![false; marked_size as usize];
        let mut size = 0;
        let mut mx = x;
        let mut my = y;
        self.block_walk_recursive(&mut size, x, y, &mut mx, &mut my, &mut marked);
        let (x, y) = self.move_step(mx, my);
        (x, y, size)
    }

    fn move_step(&self, x: i32, y: i32) -> (i32, i32) {
        match self.direction_pointer {
            Direction::Left => (x - 1, y),
            Direction::Up => (x, y - 1),
            Direction::Right => (x + 1, y),
            Direction::Down => (x, y + 1),
        }
    }

    // Check if the color at a given position is different
    // than the current color
    fn current_color_eq(&self, x: i32, y: i32) -> bool {
        self.current_color == self.pixel_at(x, y)
    }

    fn pixel_at(&self, x: i32, y: i32) -> Rgba<u8> {
        self.image.get_pixel(x as u32, y as u32)
    }

    fn current_color_code(&self) -> i32 {
        match colors::color_code(&self.current_color) {
            Some(color) => color,
            None => 0,
        }
    }

    fn color_at(&self, x: i32, y: i32) -> i32 {
        match colors::color_code(&self.pixel_at(x, y)) {
            Some(color) => color,
            None => 0,
        }
    }

    fn restricted(&self, x: i32, y: i32) -> bool {
        !self.image.in_bounds(x as u32, y as u32) || self.color_at(x, y) == 0
    }

    // block walk should count the size of the current block
    // and set it on the Interpreter
    fn block_walk_recursive(
        &self,
        size: &mut u32,
        x: i32,
        y: i32,
        mx: &mut i32,
        my: &mut i32,
        marked: &mut Vec<bool>,
    ) {
        // println!("mx: {:?}, my: {:?}", mx, my);
        // println!(" x: {:?},  y: {:?}", x, y);
        // println!("DP: {:?}, CC: {:?}", self.direction_pointer, self.codel_chooser);
        // println!("Size: {:?}", size);
        if self.image.in_bounds(x as u32, y as u32) {
            // println!(
            //  "curr: {:?},  step: {:?}\n",
            //  self.current_color_code(),
            //  self.color_at(x, y));
            let visit_index = self.marked_index(x, y) as usize;
            // println!("{:?}\n", visit_index);

            if self.current_color_eq(x, y) && !marked[visit_index] {
                *size += 1;
                marked[visit_index] = true;

                match self.direction_pointer {
                    Direction::Left => if x < *mx {
                        *mx = x;
                        *my = y;
                    } else if x == *mx {
                        match self.codel_chooser {
                            CodelChooser::Left => if y > *my {
                                *my = y;
                            },

                            CodelChooser::Right => if y < *my {
                                *my = y;
                            },
                        }
                    },
                    Direction::Right => if x > *mx {
                        *mx = x;
                        *my = y;
                    } else if x == *mx {
                        match self.codel_chooser {
                            CodelChooser::Left => if y < *my {
                                *my = y;
                            },

                            CodelChooser::Right => if y > *my {
                                *my = y;
                            },
                        }
                    },
                    Direction::Down => if y > *my {
                        *mx = x;
                        *my = y;
                    } else if y == *my {
                        match self.codel_chooser {
                            CodelChooser::Left => if x > *mx {
                                *mx = x;
                            },

                            CodelChooser::Right => if x < *mx {
                                *mx = x;
                            },
                        }
                    },
                    Direction::Up => if y < *my {
                        *mx = x;
                        *my = y;
                    } else if y == *my {
                        match self.codel_chooser {
                            CodelChooser::Left => if x < *mx {
                                *mx = x;
                            },

                            CodelChooser::Right => if x > *mx {
                                *mx = x;
                            },
                        }
                    },
                }

                self.block_walk_recursive(size, x + 1, y, mx, my, marked);
                self.block_walk_recursive(size, x - 1, y, mx, my, marked);
                self.block_walk_recursive(size, x, y + 1, mx, my, marked);
                self.block_walk_recursive(size, x, y - 1, mx, my, marked);
            }
        }
        // print!("\n");
    }

    fn marked_index(&self, x: i32, y: i32) -> i32 {
        if x == 0 && y == 0 {
            return 0;
        }

        if x == 0 {
            return y * self.image.width() as i32;
        }

        if y == 0 {
            return x;
        }

        y * self.image.width() as i32 + x
    }
}
<commit_msg>Cleanup marked index method code<commit_after>use image::{DynamicImage, GenericImage, Rgba};
use colors;
use ops;

pub struct Interpreter {
    pub codel_chooser: CodelChooser,
    pub direction_pointer: Direction,
    image: DynamicImage,
    current_color: Rgba<u8>,
    pub current_size: u32,
    pub stack: Vec<i32>,
}

#[derive(Debug, PartialEq)]
pub enum Direction{
    Left,
    Right,
    Down,
    Up,
}

impl Direction {
    pub fn step(&mut self) {
        *self = match *self {
            Direction::Left => Direction::Up,
            Direction::Right => Direction::Down,
            Direction::Down => Direction::Left,
            Direction::Up => Direction::Right,
        }
    }

    pub fn step_counter(&mut self) {
        *self = match *self {
            Direction::Left => Direction::Down,
            Direction::Right => Direction::Up,
            Direction::Down => Direction::Right,
            Direction::Up => Direction::Left,
        }
    }
}

#[derive(Debug)]
pub enum CodelChooser {
    Right,
    Left,
}

impl CodelChooser {
    pub fn toggle(&mut self) {
        *self = match *self {
            CodelChooser::Right => CodelChooser::Left,
            CodelChooser::Left => CodelChooser::Right,
        };
    }
}

impl Interpreter {
    pub fn new(image: DynamicImage) -> Interpreter {
        Interpreter {
            codel_chooser: CodelChooser::Left,
            direction_pointer: Direction::Right,
            current_color: image.get_pixel(0, 0),
            current_size: 0,
            image: image,
            stack: Vec::new(),
        }
    }

    pub fn run(&mut self) {
        let mut failed_attempts = 0;
        let mut failed_white_attempts = 0;

        // These are here for debugging purposes
        let mut x = 0;
        let mut y = 0;

        loop {
            // If white just sail through until we hit another color
            if self.current_color_code() == 1 {
                let (x_next, y_next) = self.move_step(x, y);
                // If in white and hit boundary or black then step through dp
                if self.restricted(x_next, y_next) {
                    self.codel_chooser.toggle();
                    self.direction_pointer.step();
                    failed_white_attempts += 1;
                } else {
                    x = x_next;
                    y = y_next;
                    self.current_color = self.pixel_at(x, y);
                    failed_attempts = 0;
                    failed_white_attempts = 0;
                }

                if failed_white_attempts == 4 {
                    break;
                }
            } else {
                let (x_next, y_next, size) = self.next_block(x, y);
                // If we are hitting the edge or a black codel try another direction
                if self.restricted(x_next, y_next) {
                    self.update_movement(failed_attempts);
                    failed_attempts += 1;
                } else {
                    // here we move into the next color block after processing the action
                    x = x_next;
                    y = y_next;

                    let next_color = self.pixel_at(x, y);
                    self.current_size = size;
                    self.process_action(&next_color);
                    self.current_color = next_color;
                    failed_attempts = 0;
                    failed_white_attempts = 0;
                }

                if failed_attempts == 8 {
                    break;
                }
            }
        }
    }

    fn process_action(&mut self, next_color: &Rgba<u8>) {
        let color_code = colors::color_code(next_color).unwrap();
        if color_code != 1 {
            let curr_color = self.current_color_code();
            let shade_diff = colors::shade_difference(curr_color, color_code);
            let hue_diff = colors::hue_difference(curr_color, color_code);
            ops::call_op(self, (hue_diff, shade_diff));
        }
    }

    // Based on the number of attempts this either toggles the CC back and forth
    // or updates the current direction of the DP
    fn update_movement(&mut self, attempts: i32) {
        if attempts % 2 == 0 {
            self.codel_chooser.toggle();
        } else {
            self.direction_pointer.step();
        }
    }

    // This method sets the current size after finding the next block
    fn next_block(&mut self, x: i32, y: i32) -> (i32, i32, u32) {
        let marked_size = self.image.width() * self.image.height();
        let mut marked = vec![false; marked_size as usize];
        let mut size = 0;
        let mut mx = x;
        let mut my = y;
        self.block_walk_recursive(&mut size, x, y, &mut mx, &mut my, &mut marked);
        let (x, y) = self.move_step(mx, my);
        (x, y, size)
    }

    fn move_step(&self, x: i32, y: i32) -> (i32, i32) {
        match self.direction_pointer {
            Direction::Left => (x - 1, y),
            Direction::Up => (x, y - 1),
            Direction::Right => (x + 1, y),
            Direction::Down => (x, y + 1),
        }
    }

    // Check if the color at a given position is different
    // than the current color
    fn current_color_eq(&self, x: i32, y: i32) -> bool {
        self.current_color == self.pixel_at(x, y)
    }

    fn pixel_at(&self, x: i32, y: i32) -> Rgba<u8> {
        self.image.get_pixel(x as u32, y as u32)
    }

    fn current_color_code(&self) -> i32 {
        match colors::color_code(&self.current_color) {
            Some(color) => color,
            None => 0,
        }
    }

    fn color_at(&self, x: i32, y: i32) -> i32 {
        match colors::color_code(&self.pixel_at(x, y)) {
            Some(color) => color,
            None => 0,
        }
    }

    fn restricted(&self, x: i32, y: i32) -> bool {
        !self.image.in_bounds(x as u32, y as u32) || self.color_at(x, y) == 0
    }

    // block walk should count the size of the current block
    // and set it on the Interpreter
    fn block_walk_recursive(
        &self,
        size: &mut u32,
        x: i32,
        y: i32,
        mx: &mut i32,
        my: &mut i32,
        marked: &mut Vec<bool>,
    ) {
        // println!("mx: {:?}, my: {:?}", mx, my);
        // println!(" x: {:?},  y: {:?}", x, y);
        // println!("DP: {:?}, CC: {:?}", self.direction_pointer, self.codel_chooser);
        // println!("Size: {:?}", size);
        if self.image.in_bounds(x as u32, y as u32) {
            // println!(
            //  "curr: {:?},  step: {:?}\n",
            //  self.current_color_code(),
            //  self.color_at(x, y));
            let visit_index = self.marked_index(x, y) as usize;
            // println!("{:?}\n", visit_index);

            if self.current_color_eq(x, y) && !marked[visit_index] {
                *size += 1;
                marked[visit_index] = true;

                match self.direction_pointer {
                    Direction::Left => if x < *mx {
                        *mx = x;
                        *my = y;
                    } else if x == *mx {
                        match self.codel_chooser {
                            CodelChooser::Left => if y > *my {
                                *my = y;
                            },

                            CodelChooser::Right => if y < *my {
                                *my = y;
                            },
                        }
                    },
                    Direction::Right => if x > *mx {
                        *mx = x;
                        *my = y;
                    } else if x == *mx {
                        match self.codel_chooser {
                            CodelChooser::Left => if y < *my {
                                *my = y;
                            },

                            CodelChooser::Right => if y > *my {
                                *my = y;
                            },
                        }
                    },
                    Direction::Down => if y > *my {
                        *mx = x;
                        *my = y;
                    } else if y == *my {
                        match self.codel_chooser {
                            CodelChooser::Left => if x > *mx {
                                *mx = x;
                            },

                            CodelChooser::Right => if x < *mx {
                                *mx = x;
                            },
                        }
                    },
                    Direction::Up => if y < *my {
                        *mx = x;
                        *my = y;
                    } else if y == *my {
                        match self.codel_chooser {
                            CodelChooser::Left => if x < *mx {
                                *mx = x;
                            },

                            CodelChooser::Right => if x > *mx {
                                *mx = x;
                            },
                        }
                    },
                }

                self.block_walk_recursive(size, x + 1, y, mx, my, marked);
                self.block_walk_recursive(size, x - 1, y, mx, my, marked);
                self.block_walk_recursive(size, x, y + 1, mx, my, marked);
                self.block_walk_recursive(size, x, y - 1, mx, my, marked);
            }
        }
        // print!("\n");
    }

    fn marked_index(&self, x: i32, y: i32) -> i32 {
        y * self.image.width() as i32 + x
    }
}
<|endoftext|>


<commit_before>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use std::mem::transmute;

use rustc_serialize::Encodable;
use rustc_serialize::json::{Json, ToJson, Encoder, encode, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError),
    /// Couldn't format Json server-side
    UnableToFormat(EncoderError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(unsafe { buffer.as_ptr() as *const u32 } as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

fn write_packet(stream: &mut Write, packet: &Json) -> Result<(), ResponseError> {
    let json_string = try!(encode(packet).map_err(ResponseError::UnableToFormat));
    trace!("Writing packet of length {}: {}", json_string.len(), json_string);
    if json_string.len() > ::std::u32::MAX as usize {
        panic!("Attempted to send reply too big for the channel!");
    }
    let _len = json_string.len() as u32;
    let len_bytes = unsafe { transmute::<_, [u8; 4]>(_len) };
    stream.write_all(&len_bytes);
    stream.write_all(json_string.as_bytes()).map_err(ResponseError::IO)
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<commit_msg>Remove unneeded unsafety<commit_after>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use std::mem::transmute;

use rustc_serialize::Encodable;
use rustc_serialize::json::{Json, ToJson, Encoder, encode, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError),
    /// Couldn't format Json server-side
    UnableToFormat(EncoderError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(buffer.as_ptr() as *const u32 as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

fn write_packet(stream: &mut Write, packet: &Json) -> Result<(), ResponseError> {
    let json_string = try!(encode(packet).map_err(ResponseError::UnableToFormat));
    trace!("Writing packet of length {}: {}", json_string.len(), json_string);
    if json_string.len() > ::std::u32::MAX as usize {
        panic!("Attempted to send reply too big for the channel!");
    }
    let _len = json_string.len() as u32;
    let len_bytes = unsafe { transmute::<_, [u8; 4]>(_len) };
    stream.write_all(&len_bytes);
    stream.write_all(json_string.as_bytes()).map_err(ResponseError::IO)
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<|endoftext|>


<commit_before>use token::Token;

use regex::Regex;
use context::ParseContext;

pub trait ESCharClasses {
    fn is_es_newline(self) -> bool;
    fn is_es_whitespace(self) -> bool;
}

impl ESCharClasses for char {
    fn is_es_newline(self) -> bool {
        match self {
            '\u{000a}' | '\u{000d}' | '\u{2028}' | '\u{2029}' => true,
            _ => false
        }
    }

    fn is_es_whitespace(self) -> bool {
        match self {
              '\u{0009}' | '\u{000b}' | '\u{000c}' | '\u{0020}' | '\u{00a0}'
            | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}'
            | '\u{2005}' | '\u{2006}' | '\u{2009}' | '\u{200a}' | '\u{202f}' | '\u{205f}'
            | '\u{3000}' | '\u{feff}' => true,
            _ => false
        }
    }
}

pub struct Lexer<'a, I, C> {
    chars: I,
    cx: &'a C
}

impl<'a, I, C> Lexer<'a, I, C> where I: Iterator<Item=char>, C: ParseContext {
    pub fn new(chars: I, cx: &'a C) -> Lexer<'a, I, C> {
        Lexer { chars: chars, cx: cx }
    }
}

impl<'a, I, C> Iterator for Lexer<'a, I, C> where I: Iterator<Item=char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        let char = self.chars.by_ref().find(|c| !c.is_es_whitespace() );

        char.map(|chr| {
            match chr {
                '1' => Token::DecimalInt(String::from_str("1")),
                '+' => Token::Plus,
                _ => Token::Error(chr)
            }
        })
    }
}
<commit_msg>src/parser.rs:13:1: 15:2 error: the parameter type `C` may not live long enough [E0309]<commit_after>use token::Token;

use regex::Regex;
use context::ParseContext;

pub trait ESCharClasses {
    fn is_es_newline(self) -> bool;
    fn is_es_whitespace(self) -> bool;
}

impl ESCharClasses for char {
    fn is_es_newline(self) -> bool {
        match self {
            '\u{000a}' | '\u{000d}' | '\u{2028}' | '\u{2029}' => true,
            _ => false
        }
    }

    fn is_es_whitespace(self) -> bool {
        match self {
              '\u{0009}' | '\u{000b}' | '\u{000c}' | '\u{0020}' | '\u{00a0}'
            | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}'
            | '\u{2005}' | '\u{2006}' | '\u{2009}' | '\u{200a}' | '\u{202f}' | '\u{205f}'
            | '\u{3000}' | '\u{feff}' => true,
            _ => false
        }
    }
}

pub struct Lexer<'a, I, C: 'a> {
    chars: I,
    cx: &'a C
}

impl<'a, I, C> Lexer<'a, I, C> where I: Iterator<Item=char>, C: ParseContext {
    pub fn new(chars: I, cx: &'a C) -> Lexer<'a, I, C> {
        Lexer { chars: chars, cx: cx }
    }
}

impl<'a, I, C> Iterator for Lexer<'a, I, C> where I: Iterator<Item=char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        let char = self.chars.by_ref().find(|c| !c.is_es_whitespace() );

        char.map(|chr| {
            match chr {
                '1' => Token::DecimalInt(String::from_str("1")),
                '+' => Token::Plus,
                _ => Token::Error(chr)
            }
        })
    }
}
<|endoftext|>