<commit_before>use core::ptr;
use core::slice;
use header::Tag;

#[derive(Debug)]
pub struct FramebufferTag {
    pub address: u64,
    pub pitch: u32,
    pub width: u32,
    pub height: u32,
    pub bpp: u8,
    pub buffer_type: FramebufferType
}

#[derive(Debug)]
pub enum FramebufferType {
    Indexed {
        palette: &'static [FramebufferColor]
    },
    RGB {
        red: FramebufferField,
        green: FramebufferField,
        blue: FramebufferField
    },
    Text
}

#[derive(Debug)]
pub struct FramebufferField {
    position: u8,
    size: u8
}

#[derive(Debug)]
#[repr(C, packed)]
pub struct FramebufferColor {
    red: u8,
    green: u8,
    blue: u8
}

struct Reader {
    ptr: *const u8,
    off: usize
}

impl Reader {
    fn new<T>(ptr: *const T) -> Reader {
        Reader {
            ptr: ptr as *const u8,
            off: 0
        }
    }

    fn read_u8(&mut self) -> u8 {
        self.off += 1;
        unsafe {
            ptr::read(self.ptr.offset((self.off - 1) as isize))
        }
    }

    fn read_u16(&mut self) -> u16 {
        self.read_u8() as u16 | (self.read_u8() as u16) << 8
    }

    fn read_u32(&mut self) -> u32 {
        self.read_u16() as u32 | (self.read_u16() as u32) << 16
    }

    fn read_u64(&mut self) -> u64 {
        self.read_u32() as u64 | (self.read_u32() as u64) << 32
    }

    fn skip(&mut self, n: usize) {
        self.off += n;
    }
}

pub fn framebuffer_tag(tag: &Tag) -> FramebufferTag {
    let mut reader = Reader::new(tag as *const Tag);
    reader.skip(8);
    let address = reader.read_u64();
    let pitch = reader.read_u32();
    let width = reader.read_u32();
    let height = reader.read_u32();
    let bpp = reader.read_u8();
    let type_no = reader.read_u8();
    reader.skip(2); // RAAAAAAAAAAAAARGH THIS WAS _NOT_ IN THE MULTIBOOT SPEC AAAASDAUHSDKJAHSDKJAHSD.
                    // In the multiboot spec, it has this listed as a u8 _NOT_ a u16.
                    // Reading the GRUB2 source code reveals it is in fact a u16.
    let buffer_type = match type_no {
        0 =>  {
            let num_colors = reader.read_u32();
            let palette = unsafe {
                slice::from_raw_parts(reader.ptr.offset(reader.off as isize) as *const FramebufferColor, num_colors as usize)
            } as &'static [FramebufferColor];
            FramebufferType::Indexed { palette }
        },
        1 => {
            let red_pos = reader.read_u8();     //Also.... WHAT DO THESE MEAN????
            let red_mask = reader.read_u8();    //i mean, i can guess
            let green_pos = reader.read_u8();   //but i shouldn't have to.
            let green_mask = reader.read_u8();  //come on multiboot... why is your spec so shite??
            let blue_pos = reader.read_u8();
            let blue_mask = reader.read_u8();
            FramebufferType::RGB {
                red: FramebufferField { position: red_pos, size: red_mask },
                green: FramebufferField { position: green_pos, size: green_mask },
                blue: FramebufferField { position: blue_pos, size: blue_mask }
            }
        },
        2 => FramebufferType::Text,
        _ => panic!("Unknown framebuffer type: {}", type_no)
    };

    FramebufferTag {
        address,
        pitch,
        width,
        height,
        bpp,
        buffer_type
    }
}
<commit_msg>More helpful comments<commit_after>use core::ptr;
use core::slice;
use header::Tag;

#[derive(Debug)]
pub struct FramebufferTag {
    pub address: u64,
    pub pitch: u32,
    pub width: u32,
    pub height: u32,
    pub bpp: u8,
    pub buffer_type: FramebufferType
}

#[derive(Debug)]
pub enum FramebufferType {
    Indexed {
        palette: &'static [FramebufferColor]
    },
    RGB {
        red: FramebufferField,
        green: FramebufferField,
        blue: FramebufferField
    },
    Text
}

#[derive(Debug)]
pub struct FramebufferField {
    position: u8,
    size: u8
}

#[derive(Debug)]
#[repr(C, packed)]
pub struct FramebufferColor {
    red: u8,
    green: u8,
    blue: u8
}

struct Reader {
    ptr: *const u8,
    off: usize
}

impl Reader {
    fn new<T>(ptr: *const T) -> Reader {
        Reader {
            ptr: ptr as *const u8,
            off: 0
        }
    }

    fn read_u8(&mut self) -> u8 {
        self.off += 1;
        unsafe {
            ptr::read(self.ptr.offset((self.off - 1) as isize))
        }
    }

    fn read_u16(&mut self) -> u16 {
        self.read_u8() as u16 | (self.read_u8() as u16) << 8
    }

    fn read_u32(&mut self) -> u32 {
        self.read_u16() as u32 | (self.read_u16() as u32) << 16
    }

    fn read_u64(&mut self) -> u64 {
        self.read_u32() as u64 | (self.read_u32() as u64) << 32
    }

    fn skip(&mut self, n: usize) {
        self.off += n;
    }
}

pub fn framebuffer_tag(tag: &Tag) -> FramebufferTag {
    let mut reader = Reader::new(tag as *const Tag);
    reader.skip(8);
    let address = reader.read_u64();
    let pitch = reader.read_u32();
    let width = reader.read_u32();
    let height = reader.read_u32();
    let bpp = reader.read_u8();
    let type_no = reader.read_u8();
    reader.skip(2); // In the multiboot spec, it has this listed as a u8 _NOT_ a u16.
                    // Reading the GRUB2 source code reveals it is in fact a u16.
    let buffer_type = match type_no {
        0 =>  {
            let num_colors = reader.read_u32();
            let palette = unsafe {
                slice::from_raw_parts(reader.ptr.offset(reader.off as isize) as *const FramebufferColor, num_colors as usize)
            } as &'static [FramebufferColor];
            FramebufferType::Indexed { palette }
        },
        1 => {
            let red_pos = reader.read_u8();     //These refer to the bit positions of the MSB of each field
            let red_mask = reader.read_u8();    //And then the length of the field from MSB to LSB
            let green_pos = reader.read_u8();
            let green_mask = reader.read_u8();
            let blue_pos = reader.read_u8();
            let blue_mask = reader.read_u8();
            FramebufferType::RGB {
                red: FramebufferField { position: red_pos, size: red_mask },
                green: FramebufferField { position: green_pos, size: green_mask },
                blue: FramebufferField { position: blue_pos, size: blue_mask }
            }
        },
        2 => FramebufferType::Text,
        _ => panic!("Unknown framebuffer type: {}", type_no)
    };

    FramebufferTag {
        address,
        pitch,
        width,
        height,
        bpp,
        buffer_type
    }
}
<|endoftext|>


<commit_before>// A port of selecta's scoring algorithm parsing.
// selecta (c) 2014 John Hawthorn
// Licensed under the MIT license

use std::cmp::Ordering;
use super::eq;
use super::mat::Mat;
use super::bonus::compute_bonus;
use super::consts::*;

#[derive(Debug)]
pub struct Score {
    /// The computed score value
    pub value: f32,

    /// Optional vector of match positions
    pub positions: Option<Vec<usize>>
}

impl Score {
    /// Creates a new Score with the provided value
    ///
    /// # Examples
    ///
    /// ```
    /// let score = rff::fuzzy::Score::new(1.0);
    /// assert_eq!(score.value, 1.0);
    /// ```
    pub fn new(value: f32) -> Score {
        Score { value: value, positions: None }
    }

    /// Creates a new Score with the provided value and match positions
    ///
    /// # Examples
    ///
    /// ```
    /// let score = rff::fuzzy::Score::with_positions(1.0, vec![1, 2, 3]);
    /// assert_eq!(score.value, 1.0);
    /// assert_eq!(score.positions, Some(vec![1, 2, 3]));
    /// ```
    pub fn with_positions(value: f32, positions: Vec<usize>) -> Score {
        Score { value: value, positions: Some(positions) }
    }

    /// Creates a new Score, with value derived from provided needle / haystack
    pub fn calculate(needle: &str, haystack: &str) -> Score {
        let len_n = needle.len();
        let len_h = haystack.len();

        if len_n == 0 { return Score::new(SCORE_MIN); }
        if len_n == len_h { return Score::new(SCORE_MAX); }

        let (m, _) = generate_score_matrices(needle, haystack);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        Score::new(score)
    }
}

impl PartialOrd for Score {
    fn partial_cmp(&self, other: &Score) -> Option<Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl PartialEq for Score {
    fn eq(&self, other: &Score) -> bool {
        self.value == other.value
    }
}

#[inline]
fn generate_score_matrices(needle: &str, haystack: &str) -> (Mat, Mat) {
    let len_n = needle.len();
    let len_h = haystack.len();

    let bonus = compute_bonus(haystack);

    let mut d = Mat::new(len_n, len_h);
    let mut m = Mat::new(len_n, len_h);

    for (i, n) in needle.chars().enumerate() {
        let mut prev_score = SCORE_MIN;
        let gap_score = if i == len_n - 1 { SCORE_GAP_TRAILING } else { SCORE_GAP_INNER };

        for (j, h) in haystack.chars().enumerate() {
            if eq(n, h) {
                let mut score = SCORE_MIN;

                let bonus_score = bonus[j];

                if i == 0 {
                    score = ((j as f32) * SCORE_GAP_LEADING) + bonus_score;
                } else if j > 0 {
                    let m = m.get(i - 1, j - 1).unwrap();
                    let d = d.get(i - 1, j - 1).unwrap();

                    score = (m + bonus_score).max(d + SCORE_MATCH_CONSECUTIVE);
                }

                prev_score = score.max(prev_score + gap_score);

                d.set(i, j, score).unwrap();
                m.set(i, j, prev_score).unwrap();
            } else {
                d.set(i, j, SCORE_MIN).unwrap();
                m.set(i, j, prev_score + gap_score).unwrap();
                prev_score += gap_score;
            }
        }
    }

    (m, d)
}

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

    fn score(needle: &str, haystack: &str) -> Score {
        Score::calculate(needle, haystack)
    }

    #[test]
    fn test_eq() {
        let a = Score::new(1.0);
        let b = Score::new(1.0);
        assert_eq!(a, b);
    }

    #[test]
    fn test_cmp() {
        let a = Score::new(2.0);
        let b = Score::new(1.0);
        assert!(a > b);
        assert!(b < a);

        let b = Score::new(2.0);
        assert!(a == b);
    }

    #[test]
    fn relative_scores() {
        // App/Models/Order is better than App/MOdels/zRder
        assert!(score("amor", "app/models/order") > score("amor", "app/models/zrder"));

        // App/MOdels/foo is better than App/M/fOo
        assert!(score("amo", "app/m/foo") < score("amo", "app/models/foo"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // Prefer shorter scorees
        assert!(score("abce", "abcdef") > score("abce", "abc de"));

        // Prefer shorter candidates
        assert!(score("test", "tests") > score("test", "testing"));

        // Scores first letter highly
        assert!(score("test", "testing") > score("test", "/testing"));

        // Prefer shorter scorees
        assert!(score("abc", "    a b c ") > score("abc", " a  b  c "));
        assert!(score("abc", " a b c    ") > score("abc", " a  b  c "));
    }

    #[bench]
    fn bench_score(b: &mut Bencher) {
        b.iter(|| Score::calculate("amor", "app/models/order.rb"))
    }

    #[bench]
    fn bench_score_multiple(b: &mut Bencher) {
        b.iter(|| {
            Score::calculate("amor", "app/models/order.rb");
            Score::calculate("amor", "spec/models/order_spec.rb");
            Score::calculate("amor", "other_garbage.rb");
            Score::calculate("amor", "Gemfile");
            Score::calculate("amor", "node_modules/test/a/thing.js");
            Score::calculate("amor", "vendor/bundle/ruby/gem.rb")
        })
    }

}
<commit_msg>Add Score::calculate_with_positions<commit_after>// A port of selecta's scoring algorithm parsing.
// selecta (c) 2014 John Hawthorn
// Licensed under the MIT license

use std::cmp::Ordering;
use super::eq;
use super::mat::Mat;
use super::bonus::compute_bonus;
use super::consts::*;

#[derive(Debug)]
pub struct Score {
    /// The computed score value
    pub value: f32,

    /// Optional vector of match positions
    pub positions: Option<Vec<usize>>
}

impl Score {
    /// Creates a new Score with the provided value
    ///
    /// # Examples
    ///
    /// ```
    /// let score = rff::fuzzy::Score::new(1.0);
    /// assert_eq!(score.value, 1.0);
    /// ```
    pub fn new(value: f32) -> Score {
        Score { value: value, positions: None }
    }

    /// Creates a new Score with the provided value and match positions
    ///
    /// # Examples
    ///
    /// ```
    /// let score = rff::fuzzy::Score::with_positions(1.0, vec![1, 2, 3]);
    /// assert_eq!(score.value, 1.0);
    /// assert_eq!(score.positions, Some(vec![1, 2, 3]));
    /// ```
    pub fn with_positions(value: f32, positions: Vec<usize>) -> Score {
        Score { value: value, positions: Some(positions) }
    }

    /// Creates a new Score, with value derived from provided needle / haystack
    pub fn calculate(needle: &str, haystack: &str) -> Score {
        let len_n = needle.len();
        let len_h = haystack.len();

        if len_n == 0 { return Score::new(SCORE_MIN); }
        if len_n == len_h { return Score::new(SCORE_MAX); }

        let (m, _) = generate_score_matrices(needle, haystack);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        Score::new(score)
    }

    /// Calculates match positions of needle's chars, in addition to the score
    pub fn calculate_with_positions(needle: &str, haystack: &str) -> Score {
        let len_n = needle.len();
        let len_h = haystack.len();

        if len_n == 0 { return Score::new(SCORE_MIN); }

        if len_n == len_h {
            let positions = (0..len_n).collect();
            return Score::with_positions(SCORE_MAX, positions);
        }

        let (m, d) = generate_score_matrices(needle, haystack);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        let positions = derive_match_positions(len_n, len_h, m, d);

        Score::with_positions(score, positions)
    }
}

impl PartialOrd for Score {
    fn partial_cmp(&self, other: &Score) -> Option<Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl PartialEq for Score {
    fn eq(&self, other: &Score) -> bool {
        self.value == other.value
    }
}

#[inline]
fn generate_score_matrices(needle: &str, haystack: &str) -> (Mat, Mat) {
    let len_n = needle.len();
    let len_h = haystack.len();

    let bonus = compute_bonus(haystack);

    let mut d = Mat::new(len_n, len_h);
    let mut m = Mat::new(len_n, len_h);

    for (i, n) in needle.chars().enumerate() {
        let mut prev_score = SCORE_MIN;
        let gap_score = if i == len_n - 1 { SCORE_GAP_TRAILING } else { SCORE_GAP_INNER };

        for (j, h) in haystack.chars().enumerate() {
            if eq(n, h) {
                let mut score = SCORE_MIN;

                let bonus_score = bonus[j];

                if i == 0 {
                    score = ((j as f32) * SCORE_GAP_LEADING) + bonus_score;
                } else if j > 0 {
                    let m = m.get(i - 1, j - 1).unwrap();
                    let d = d.get(i - 1, j - 1).unwrap();

                    score = (m + bonus_score).max(d + SCORE_MATCH_CONSECUTIVE);
                }

                prev_score = score.max(prev_score + gap_score);

                d.set(i, j, score).unwrap();
                m.set(i, j, prev_score).unwrap();
            } else {
                d.set(i, j, SCORE_MIN).unwrap();
                m.set(i, j, prev_score + gap_score).unwrap();
                prev_score += gap_score;
            }
        }
    }

    (m, d)
}

/// Given the length of the input strings, and generated scoring matrices,
/// generates a len_n vector of optimal match positions for each haystack char.
#[inline]
fn derive_match_positions(len_n: usize, len_h: usize, m: Mat, d: Mat) -> Vec<usize> {
    let mut positions = vec![0 as usize; len_n];
    let mut match_required = false;

    let mut j = len_h - 1;

    for i in (0..len_n).rev() {
        while j > (0 as usize) {
            let last = if i > 0 && j > 0 { d.get(i - 1, j - 1).unwrap() } else { 0.0 };

            let d = d.get(i, j).unwrap();
            let m = m.get(i, j).unwrap();

            if d != SCORE_MIN && (match_required || d == m) {
                if i > 0 && j > 0 && m == last + SCORE_MATCH_CONSECUTIVE {
                    match_required = true;
                }

                positions[i] = j;

                break;
            }

            j -= 1
        }
    }

    positions
}

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

    fn score(needle: &str, haystack: &str) -> Score {
        Score::calculate(needle, haystack)
    }

    #[test]
    fn test_eq() {
        let a = Score::new(1.0);
        let b = Score::new(1.0);
        assert_eq!(a, b);
    }

    #[test]
    fn test_cmp() {
        let a = Score::new(2.0);
        let b = Score::new(1.0);
        assert!(a > b);
        assert!(b < a);

        let b = Score::new(2.0);
        assert!(a == b);
    }

    #[test]
    fn relative_scores() {
        // App/Models/Order is better than App/MOdels/zRder
        assert!(score("amor", "app/models/order") > score("amor", "app/models/zrder"));

        // App/MOdels/foo is better than App/M/fOo
        assert!(score("amo", "app/m/foo") < score("amo", "app/models/foo"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // Prefer shorter scorees
        assert!(score("abce", "abcdef") > score("abce", "abc de"));

        // Prefer shorter candidates
        assert!(score("test", "tests") > score("test", "testing"));

        // Scores first letter highly
        assert!(score("test", "testing") > score("test", "/testing"));

        // Prefer shorter scorees
        assert!(score("abc", "    a b c ") > score("abc", " a  b  c "));
        assert!(score("abc", " a b c    ") > score("abc", " a  b  c "));
    }

    #[test]
    fn positions() {
        macro_rules! test_positions {
            ($needle:expr, $haystack:expr, $result:expr) => {
                let score = Score::calculate_with_positions($needle, $haystack);
                assert_eq!(score.positions, Some($result));
            }
        }

        test_positions!("amo", "app/models/foo", vec![0, 4, 5]);
        test_positions!("amor", "app/models/order", vec![0, 4, 11, 12]);
        test_positions!("as", "tags", vec![1, 3]);
        test_positions!("abc", "a/a/b/c/c", vec![2, 4, 6]);
        test_positions!("foo", "foo", vec![0, 1, 2]);
        test_positions!("drivers", "/path/to/drivers/file.txt", vec![9, 10, 11, 12, 13, 14, 15]);
    }

    #[bench]
    fn bench_score(b: &mut Bencher) {
        b.iter(|| Score::calculate("amor", "app/models/order.rb"))
    }

    #[bench]
    fn bench_score_multiple(b: &mut Bencher) {
        b.iter(|| {
            Score::calculate("amor", "app/models/order.rb");
            Score::calculate("amor", "spec/models/order_spec.rb");
            Score::calculate("amor", "other_garbage.rb");
            Score::calculate("amor", "Gemfile");
            Score::calculate("amor", "node_modules/test/a/thing.js");
            Score::calculate("amor", "vendor/bundle/ruby/gem.rb")
        })
    }

}
<|endoftext|>


<commit_before>
//! Glyph caching

use error::Error;
use freetype::ffi;
use freetype;
use freetype::error::Error::MissingFontField;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::iter::{Map, Range};
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 font_str = match font.as_str() {
            Some(font_str) => font_str,
            None => return Err(Error::FreetypeError(MissingFontField)),
        };
        let face = match freetype.new_face(font_str, 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) {
        if self.data.get(&size) // Don't load glyph twice
            .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<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));
    }
}

impl graphics::character::CharacterCache<Texture> for GlyphCache {
    fn character(&mut self, size: FontSize, ch: char) -> &Character {
        match {
            match self.data.entry(size) {
                Vacant(entry) => entry.set(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>Quick fixes<commit_after>
//! Glyph caching

use error::Error;
use freetype::ffi;
use freetype;
use freetype::error::Error::MissingFontField;
use std::collections::HashMap;
use std::collections::hash_map::{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 font_str = match font.as_str() {
            Some(font_str) => font_str,
            None => return Err(Error::FreetypeError(MissingFontField)),
        };
        let face = match freetype.new_face(font_str, 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<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));
    }
}

impl graphics::character::CharacterCache<Texture> for GlyphCache {
    fn character(&mut self, size: FontSize, ch: char) -> &Character {
        match {
            match self.data.entry(size) {
                Vacant(entry) => entry.set(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>extern crate ncurses;

use self::ncurses::*;
use cpu::ExecState;
use instruction;

struct CpuWin {
    win:        WINDOW,
    winner:     WINDOW,
    wsidebar:   WINDOW,
}

const SIDEBAR_CELL_HEIGHT: i32 = 2;
const SIDEBAR_WIDTH: i32 = 6;
const CPUWIN_HEIGHT: i32 = (SIDEBAR_CELL_HEIGHT + 1) * 4 + 1;
const CPUWIN_WIDTH: i32 = CPUWIN_HEIGHT*2 + SIDEBAR_WIDTH;
const SIDEBAR_X: i32 = CPUWIN_WIDTH - 1 - SIDEBAR_WIDTH - 1;

impl CpuWin {
    fn new(posx: i32, posy: i32) -> CpuWin {

        let win = newwin(CPUWIN_HEIGHT, CPUWIN_WIDTH, posy, posx);
        let winner = derwin(win, CPUWIN_HEIGHT-2, CPUWIN_WIDTH-2, 1, 1);
        let wsidebar = derwin(winner, CPUWIN_HEIGHT-2, SIDEBAR_WIDTH, 0, SIDEBAR_X);

        /* Border */
        box_(win, 0, 0);

        /* Left size of sidebar */
        mvwaddch(win, 0, SIDEBAR_X, ACS_TTEE());
        mvwvline(win, 1, SIDEBAR_X, ACS_VLINE(), CPUWIN_HEIGHT - 2);
        mvwaddch(win, CPUWIN_HEIGHT-1, SIDEBAR_X, ACS_BTEE());

        let mut cpuwin = CpuWin {
            win:        win,
            winner:     winner,
            wsidebar:   wsidebar,
        };
        cpuwin.cell_label(0, "ACC");
        cpuwin.cell_label(1, "BAK");
        cpuwin.cell_label(2, "LAST");
        cpuwin.cell_label(3, "MODE");

        cpuwin.cell_divider(1);
        cpuwin.cell_divider(2);
        cpuwin.cell_divider(3);

        cpuwin.set_values(0, 10, None, ExecState::EXEC);

        cpuwin
    }

    fn cell_label(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell), 1, l);
    }

    fn cell_val(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell)+1, 1, l);
    }

    fn cell_divider(&mut self, cell: i32) {
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X, ACS_LTEE());
        mvwhline(self.win, Self::cell_y(cell), SIDEBAR_X+1, ACS_HLINE(), SIDEBAR_WIDTH);
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X+SIDEBAR_WIDTH+1, ACS_RTEE());
    }

    fn cell_y(cell: i32) -> i32 {
        (SIDEBAR_CELL_HEIGHT + 1) * cell
    }

    fn refresh(&mut self) {
        wrefresh(self.win);
    }

    fn set_values(&mut self, acc: i32, bak: i32, last: Option<instruction::Port>, mode: ExecState) {
        let acc = format!("{:^4}", acc);
        let bak = format!("{:^4}", bak);
        let last = last.map_or_else(|| "N/A".to_string(), |p| p.to_string());
        let mode = mode.to_string();
        self.cell_val(0, &acc);
        self.cell_val(1, &bak);
        self.cell_val(2, &last);
        self.cell_val(3, &mode);
    }
}

impl Drop for CpuWin {
    fn drop(&mut self) {
        delwin(self.wsidebar);
        delwin(self.winner);
        wclear(self.win);
        wrefresh(self.win);
        delwin(self.win);
    }
}

pub fn gui() {
    initscr();
    refresh();

    let mut cpuwin = CpuWin::new(12, 12);
    cpuwin.refresh();

    getch();

    drop(cpuwin);
    refresh();
    getch();

    endwin();
}
<commit_msg>gui_ncurses: multiple cpus<commit_after>extern crate ncurses;

use std::option::Option;
use self::ncurses::*;
use cpu::ExecState;
use instruction;

struct CpuWin {
    win:        WINDOW,
    winner:     WINDOW,
    wsidebar:   WINDOW,
}

const SIDEBAR_CELL_HEIGHT: i32 = 2;
const SIDEBAR_WIDTH: i32 = 6;
const CPUWIN_HEIGHT: i32 = (SIDEBAR_CELL_HEIGHT + 1) * 4 + 1;
const CPUWIN_WIDTH: i32 = CPUWIN_HEIGHT*2 + SIDEBAR_WIDTH;
const SIDEBAR_X: i32 = CPUWIN_WIDTH - 1 - SIDEBAR_WIDTH - 1;

impl CpuWin {
    fn new(posx: i32, posy: i32) -> CpuWin {

        let win = newwin(CPUWIN_HEIGHT, CPUWIN_WIDTH, posy, posx);
        let winner = derwin(win, CPUWIN_HEIGHT-2, CPUWIN_WIDTH-2, 1, 1);
        let wsidebar = derwin(winner, CPUWIN_HEIGHT-2, SIDEBAR_WIDTH, 0, SIDEBAR_X);

        /* Border */
        box_(win, 0, 0);

        /* Left size of sidebar */
        mvwaddch(win, 0, SIDEBAR_X, ACS_TTEE());
        mvwvline(win, 1, SIDEBAR_X, ACS_VLINE(), CPUWIN_HEIGHT - 2);
        mvwaddch(win, CPUWIN_HEIGHT-1, SIDEBAR_X, ACS_BTEE());

        let mut cpuwin = CpuWin {
            win:        win,
            winner:     winner,
            wsidebar:   wsidebar,
        };
        cpuwin.cell_label(0, "ACC");
        cpuwin.cell_label(1, "BAK");
        cpuwin.cell_label(2, "LAST");
        cpuwin.cell_label(3, "MODE");

        cpuwin.cell_divider(1);
        cpuwin.cell_divider(2);
        cpuwin.cell_divider(3);

        cpuwin.set_values(0, 10, None, ExecState::EXEC);

        cpuwin
    }

    fn cell_label(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell), 1, l);
    }

    fn cell_val(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell)+1, 1, l);
    }

    fn cell_divider(&mut self, cell: i32) {
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X, ACS_LTEE());
        mvwhline(self.win, Self::cell_y(cell), SIDEBAR_X+1, ACS_HLINE(), SIDEBAR_WIDTH);
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X+SIDEBAR_WIDTH+1, ACS_RTEE());
    }

    fn cell_y(cell: i32) -> i32 {
        (SIDEBAR_CELL_HEIGHT + 1) * cell
    }

    fn refresh(&mut self) {
        wrefresh(self.win);
    }

    fn set_values(&mut self, acc: i32, bak: i32, last: Option<instruction::Port>, mode: ExecState) {
        let acc = format!("{:^4}", acc);
        let bak = format!("{:^4}", bak);
        let last = last.map_or_else(|| "N/A".to_string(), |p| p.to_string());
        let mode = mode.to_string();
        self.cell_val(0, &acc);
        self.cell_val(1, &bak);
        self.cell_val(2, &last);
        self.cell_val(3, &mode);
    }
}

impl Drop for CpuWin {
    fn drop(&mut self) {
        delwin(self.wsidebar);
        delwin(self.winner);
        wclear(self.win);
        wrefresh(self.win);
        delwin(self.win);
    }
}

pub fn gui() {
    initscr();
    refresh();

    let left_margin = 10;
    let inner_margin = 4;

    let mut cpuwins: Vec<Vec<CpuWin>> = (0..4).map(|x| {
        (0..3).map(|y| (x, y)).map(|(x, y)| {
            CpuWin::new(x*(CPUWIN_WIDTH + inner_margin) + left_margin,
                        y*(CPUWIN_HEIGHT + inner_margin/2) + left_margin/2)
        }).collect::<Vec<_>>()
    }).collect();

    refresh();
    getch();

    for y in cpuwins.iter_mut() {
        for cpu in y.iter_mut() {
            cpu.refresh();
        }
    }

    getch();

    refresh();
    getch();

    endwin();
}
<|endoftext|>


<commit_before>extern crate ncurses;

use std::option::Option;
use self::ncurses::*;
use cpu::ExecState;
use instruction;

struct CodeWin {
    wtext:  WINDOW,
    lines:  Vec<String>,
    line:   Option<u8>,
}

impl CodeWin {
    fn new(win: WINDOW, s: &str) -> Self {
        let wtext = derwin(win, TEXT_LINES, TEXT_COLS, 0, 0);
        wbkgd(wtext, '?' as u64);
        wprintw(wtext, "hello ");

        let mut codewin = CodeWin {
            wtext: wtext,
            lines: s.lines().map(str::to_string).collect(),
            line:  None,
        };

        for i in (0..codewin.lines.len() as u8) {
            codewin.draw_line(i);
        }
        codewin.set_line(Some(1));
        codewin
    }

    fn draw_line(&mut self, line: u8) {
        let mut max_x: i32 = 0;
        let mut max_y: i32 = 0;
        getmaxyx(self.wtext, &mut max_y, &mut max_x);

        if self.line == Some(line) {
            wattr_on(self.wtext, A_STANDOUT());
        }

        let line = line as i32;
        assert!(line < max_y);

        wmove(self.wtext, line, 0);
        wclrtoeol(self.wtext);
        if let Some(s) = self.lines.get(line as usize) {
            mvwprintw(self.wtext, line, 0, s);
        }
        wattr_off(self.wtext, A_STANDOUT());
    }

    /// Sets the active (highlighted) line
    fn set_line(&mut self, newline: Option<u8>) {
        let oldline = self.line;
        self.line = newline;

        if let Some(old) = oldline {
            self.draw_line(old);
        }

        if let Some(new) = newline {
            self.draw_line(new);
        }
    }
}

impl Drop for CodeWin {
    fn drop(&mut self) {
        delwin(self.wtext);
    }
}

struct CpuWin {
    win:        WINDOW,
    winner:     WINDOW,
    wsidebar:   WINDOW,
    codewin:    CodeWin,
}

const SIDEBAR_CELL_HEIGHT: i32 = 2;
const SIDEBAR_WIDTH: i32 = 6;
const CPUWIN_HEIGHT: i32 = (SIDEBAR_CELL_HEIGHT + 1) * 4 + 1;
const CPUWIN_WIDTH: i32 = CPUWIN_HEIGHT*2 + SIDEBAR_WIDTH;
const SIDEBAR_X: i32 = CPUWIN_WIDTH - 1 - SIDEBAR_WIDTH - 1;

const TEXT_LINES: i32 = CPUWIN_HEIGHT - 2;
const TEXT_COLS: i32 = CPUWIN_WIDTH - SIDEBAR_WIDTH - 3;

impl CpuWin {
    fn new(posx: i32, posy: i32) -> CpuWin {

        let win = newwin(CPUWIN_HEIGHT, CPUWIN_WIDTH, posy, posx);
        let winner = derwin(win, CPUWIN_HEIGHT-2, CPUWIN_WIDTH-2, 1, 1);
        let wsidebar = derwin(winner, CPUWIN_HEIGHT-2, SIDEBAR_WIDTH, 0, SIDEBAR_X);

        /* Border */
        box_(win, 0, 0);

        /* Left size of sidebar */
        mvwaddch(win, 0, SIDEBAR_X, ACS_TTEE());
        mvwvline(win, 1, SIDEBAR_X, ACS_VLINE(), CPUWIN_HEIGHT - 2);
        mvwaddch(win, CPUWIN_HEIGHT-1, SIDEBAR_X, ACS_BTEE());

        let mut cpuwin = CpuWin {
            win:        win,
            winner:     winner,
            wsidebar:   wsidebar,
            codewin:    CodeWin::new(winner, "line1\nline2\n\nline4"),
        };
        cpuwin.cell_label(0, "ACC");
        cpuwin.cell_label(1, "BAK");
        cpuwin.cell_label(2, "LAST");
        cpuwin.cell_label(3, "MODE");

        cpuwin.cell_divider(1);
        cpuwin.cell_divider(2);
        cpuwin.cell_divider(3);

        cpuwin.set_values(0, 10, None, ExecState::EXEC);

        cpuwin
    }

    fn cell_label(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell), 1, l);
    }

    fn cell_val(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell)+1, 1, l);
    }

    fn cell_divider(&mut self, cell: i32) {
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X, ACS_LTEE());
        mvwhline(self.win, Self::cell_y(cell), SIDEBAR_X+1, ACS_HLINE(), SIDEBAR_WIDTH);
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X+SIDEBAR_WIDTH+1, ACS_RTEE());
    }

    fn cell_y(cell: i32) -> i32 {
        (SIDEBAR_CELL_HEIGHT + 1) * cell
    }

    fn refresh(&mut self) {
        wrefresh(self.win);
    }

    fn set_values(&mut self, acc: i32, bak: i32, last: Option<instruction::Port>, mode: ExecState) {
        let acc = format!("{:^4}", acc);
        let bak = format!("{:^4}", bak);
        let last = last.map_or_else(|| "N/A".to_string(), |p| p.to_string());
        let mode = mode.to_string();
        self.cell_val(0, &acc);
        self.cell_val(1, &bak);
        self.cell_val(2, &last);
        self.cell_val(3, &mode);
    }
}

impl Drop for CpuWin {
    fn drop(&mut self) {
        delwin(self.wsidebar);
        delwin(self.winner);
        wclear(self.win);
        //wrefresh(self.win);
        delwin(self.win);
    }
}

fn create_cpu_wins() -> Vec<Vec<CpuWin>> {
    let left_margin = 10;
    let inner_margin = 4;

    let mut cpuwins: Vec<Vec<CpuWin>> = (0..4).map(|x| {
        (0..3).map(|y| (x, y)).map(|(x, y)| {
            CpuWin::new(x*(CPUWIN_WIDTH + inner_margin) + left_margin,
                        y*(CPUWIN_HEIGHT + inner_margin/2) + left_margin/2)
        }).collect::<Vec<_>>()
    }).collect();

    for y in cpuwins.iter_mut() {
        for cpu in y.iter_mut() {
            cpu.refresh();
        }
    }

    cpuwins
}

pub fn gui() {
    initscr();
    refresh();

    let mut cpuwins = create_cpu_wins();

    loop {
        let c = getch();
        if c == b'q' as i32 {
            break;
        } else if c == KEY_RESIZE {
            drop(cpuwins);
            clear();
            refresh();
            cpuwins = create_cpu_wins();
        }
    }

    drop(cpuwins);
    endwin();
}
<commit_msg>gui_ncurses: public set_code<commit_after>extern crate ncurses;

use std::option::Option;
use self::ncurses::*;
use cpu::ExecState;
use instruction;

struct CodeWin {
    wtext:  WINDOW,
    lines:  Vec<String>,
    line:   Option<u8>,
}

impl CodeWin {
    fn new(win: WINDOW, s: &str) -> Self {
        let wtext = derwin(win, TEXT_LINES, TEXT_COLS, 0, 0);
        wbkgd(wtext, '?' as u64);

        let mut codewin = CodeWin {
            wtext: wtext,
            lines: Self::code_vec(s),
            line:  None,
        };

        codewin.set_line(Some(1));
        codewin.draw_all_lines();
        codewin
    }

    fn code_vec(s: &str) -> Vec<String> {
        s.lines().map(str::to_string).collect()
    }

    fn set_code(&mut self, s: &str) {
        self.lines = Self::code_vec(s);
        self.draw_all_lines();
    }

    fn draw_all_lines(&mut self) {
        for i in (0..self.lines.len() as u8) {
            self.draw_line(i);
        }
    }

    fn draw_line(&mut self, line: u8) {
        let mut max_x: i32 = 0;
        let mut max_y: i32 = 0;
        getmaxyx(self.wtext, &mut max_y, &mut max_x);

        if self.line == Some(line) {
            wattr_on(self.wtext, A_STANDOUT());
        }

        let line = line as i32;
        assert!(line < max_y);

        wmove(self.wtext, line, 0);
        wclrtoeol(self.wtext);
        if let Some(s) = self.lines.get(line as usize) {
            mvwprintw(self.wtext, line, 0, s);
        }
        wattr_off(self.wtext, A_STANDOUT());
        wrefresh(self.wtext);
    }

    /// Sets the active (highlighted) line
    fn set_line(&mut self, newline: Option<u8>) {
        let oldline = self.line;
        self.line = newline;

        if let Some(old) = oldline {
            self.draw_line(old);
        }

        if let Some(new) = newline {
            self.draw_line(new);
        }
    }
}

impl Drop for CodeWin {
    fn drop(&mut self) {
        delwin(self.wtext);
    }
}

struct CpuWin {
    win:        WINDOW,
    winner:     WINDOW,
    wsidebar:   WINDOW,
    codewin:    CodeWin,
}

const SIDEBAR_CELL_HEIGHT: i32 = 2;
const SIDEBAR_WIDTH: i32 = 6;
const CPUWIN_HEIGHT: i32 = (SIDEBAR_CELL_HEIGHT + 1) * 4 + 1;
const CPUWIN_WIDTH: i32 = CPUWIN_HEIGHT*2 + SIDEBAR_WIDTH;
const SIDEBAR_X: i32 = CPUWIN_WIDTH - 1 - SIDEBAR_WIDTH - 1;

const TEXT_LINES: i32 = CPUWIN_HEIGHT - 2;
const TEXT_COLS: i32 = CPUWIN_WIDTH - SIDEBAR_WIDTH - 3;

impl CpuWin {
    fn new(posx: i32, posy: i32) -> CpuWin {

        let win = newwin(CPUWIN_HEIGHT, CPUWIN_WIDTH, posy, posx);
        let winner = derwin(win, CPUWIN_HEIGHT-2, CPUWIN_WIDTH-2, 1, 1);
        let wsidebar = derwin(winner, CPUWIN_HEIGHT-2, SIDEBAR_WIDTH, 0, SIDEBAR_X);

        /* Border */
        box_(win, 0, 0);

        /* Left size of sidebar */
        mvwaddch(win, 0, SIDEBAR_X, ACS_TTEE());
        mvwvline(win, 1, SIDEBAR_X, ACS_VLINE(), CPUWIN_HEIGHT - 2);
        mvwaddch(win, CPUWIN_HEIGHT-1, SIDEBAR_X, ACS_BTEE());

        let mut cpuwin = CpuWin {
            win:        win,
            winner:     winner,
            wsidebar:   wsidebar,
            codewin:    CodeWin::new(winner, "line1\nline2\n\nline4"),
        };
        cpuwin.cell_label(0, "ACC");
        cpuwin.cell_label(1, "BAK");
        cpuwin.cell_label(2, "LAST");
        cpuwin.cell_label(3, "MODE");

        cpuwin.cell_divider(1);
        cpuwin.cell_divider(2);
        cpuwin.cell_divider(3);

        cpuwin.set_values(0, 10, None, ExecState::EXEC);

        cpuwin
    }

    fn cell_label(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell), 1, l);
    }

    fn cell_val(&mut self, cell: i32, l: &str) {
        mvwprintw(self.wsidebar, Self::cell_y(cell)+1, 1, l);
    }

    fn cell_divider(&mut self, cell: i32) {
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X, ACS_LTEE());
        mvwhline(self.win, Self::cell_y(cell), SIDEBAR_X+1, ACS_HLINE(), SIDEBAR_WIDTH);
        mvwaddch(self.win, Self::cell_y(cell), SIDEBAR_X+SIDEBAR_WIDTH+1, ACS_RTEE());
    }

    fn cell_y(cell: i32) -> i32 {
        (SIDEBAR_CELL_HEIGHT + 1) * cell
    }

    fn refresh(&mut self) {
        wrefresh(self.win);
    }

    fn set_values(&mut self, acc: i32, bak: i32, last: Option<instruction::Port>, mode: ExecState) {
        let acc = format!("{:^4}", acc);
        let bak = format!("{:^4}", bak);
        let last = last.map_or_else(|| "N/A".to_string(), |p| p.to_string());
        let mode = mode.to_string();
        self.cell_val(0, &acc);
        self.cell_val(1, &bak);
        self.cell_val(2, &last);
        self.cell_val(3, &mode);
    }

    fn set_code(&mut self, s: &str) {
        self.codewin.set_code(s)
    }

    fn set_line(&mut self, newline: Option<u8>) {
        self.codewin.set_line(newline)
    }
}

impl Drop for CpuWin {
    fn drop(&mut self) {
        delwin(self.wsidebar);
        delwin(self.winner);
        wclear(self.win);
        //wrefresh(self.win);
        delwin(self.win);
    }
}

fn create_cpu_wins() -> Vec<Vec<CpuWin>> {
    let left_margin = 10;
    let inner_margin = 4;

    let mut cpuwins: Vec<Vec<CpuWin>> = (0..4).map(|x| {
        (0..3).map(|y| (x, y)).map(|(x, y)| {
            CpuWin::new(x*(CPUWIN_WIDTH + inner_margin) + left_margin,
                        y*(CPUWIN_HEIGHT + inner_margin/2) + left_margin/2)
        }).collect::<Vec<_>>()
    }).collect();

    for y in cpuwins.iter_mut() {
        for cpu in y.iter_mut() {
            cpu.refresh();
        }
    }

    cpuwins
}

pub fn gui() {
    initscr();
    refresh();

    let mut cpuwins = create_cpu_wins();

    loop {
        let c = getch();
        if c == b'q' as i32 {
            break;
        } else if c == KEY_RESIZE {
            drop(cpuwins);
            clear();
            refresh();
            cpuwins = create_cpu_wins();
        } else {
            cpuwins[0][0].set_code("whoo");
            refresh();
        }
    }

    drop(cpuwins);
    endwin();
}
<|endoftext|>


<commit_before>extern crate mio;
extern crate regex;

#[cfg(test)]
mod tests;

mod route;
mod request;
mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

use route::*;
use request::*;
use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::new(),
            o_buf:  Vec::new(),
        }
    }

    fn readable(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(sz) => {
                        println!("read {} ({}) bytes", sz, buf.len());
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None     => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    /* write the client's output buffer to the socket.
     *
     * the following return values mean:
     *  - Ok(true):  we can close the connection
     *  - Ok(false): keep listening for writeable event and continue next time
     *  - Err(e):    something dun fucked up
     */
    fn writable(&mut self) -> Result<bool> {
        let tmp = self.o_buf.clone();
        let out = tmp.as_slice();
        match self.sock.write(&out) {
            Ok(sz)  => {
                if sz == self.o_buf.len() {
                    /* we did it! */
                    self.events.remove(EventSet::writable());
                    return Ok(true);
                } else {
                    let tmp: Vec<u8> = self.o_buf.split_off(sz);
                    println!("{:?}, -{}, {:?}", out, sz, tmp);
                    self.o_buf = tmp;

                    return Ok(false);
                }
            },
            Err(e)  => {
                panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
            }
        }

        Ok(false)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/* our primary object. similar interface to Flask, the
 * Python microframework. much faster, however! :)
 */
pub struct Canteen {
    routes:  HashMap<String, Route>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).writable() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    fn new(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: Route::_no_op,
        }
    }

    fn add_route(&mut self, path: &str, mlist: Vec<Method>, handler: fn(Request) -> Response) {
        let pc = String::from(path);

        if self.routes.contains_key(&pc) {
            panic!("a route handler for {} has already been defined!", path);
        }

        self.routes.insert(String::from(path), Route::new(&path, mlist, handler));
    }

    pub fn set_default(&mut self, handler: fn(Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn find_handler(&self, req: &Request) -> (fn(Request) -> Response) {
        let mut handler: fn(Request) -> Response = self.default;

        for (_, route) in &self.routes {
            match (route).is_match(req) {
                true  => { handler = route.handler; break; },
                false => continue,
            }
        }

        handler
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).readable() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let req = Request::from_str(&rqstr);
                let handler: fn(Request) -> Response = self.find_handler(&req);

                self.get_client(token).o_buf.extend(handler(req).gen_output());
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        /* kill the connection */
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}

fn my_handler(req: Request) -> Response {
    let mut res = Response::new();

    res.set_content_type("text/html");
    res.append(String::from("\

It's alive!

Welcome to Canteen! :)
"));

    res
}

fn main() {
    let mut cnt = Canteen::new(("127.0.0.1", 8080));
    cnt.add_route("/hello", vec![Method::Get], my_handler);
    cnt.set_default(Route::err_404);
    cnt.run();
}
<commit_msg>make the add_route function public<commit_after>extern crate mio;
extern crate regex;

#[cfg(test)]
mod tests;

mod route;
mod request;
mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

use route::*;
use request::*;
use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::new(),
            o_buf:  Vec::new(),
        }
    }

    fn readable(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(sz) => {
                        println!("read {} ({}) bytes", sz, buf.len());
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None     => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    /* write the client's output buffer to the socket.
     *
     * the following return values mean:
     *  - Ok(true):  we can close the connection
     *  - Ok(false): keep listening for writeable event and continue next time
     *  - Err(e):    something dun fucked up
     */
    fn writable(&mut self) -> Result<bool> {
        let tmp = self.o_buf.clone();
        let out = tmp.as_slice();
        match self.sock.write(&out) {
            Ok(sz)  => {
                if sz == self.o_buf.len() {
                    /* we did it! */
                    self.events.remove(EventSet::writable());
                    return Ok(true);
                } else {
                    let tmp: Vec<u8> = self.o_buf.split_off(sz);
                    println!("{:?}, -{}, {:?}", out, sz, tmp);
                    self.o_buf = tmp;

                    return Ok(false);
                }
            },
            Err(e)  => {
                panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
            }
        }

        Ok(false)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/* our primary object. similar interface to Flask, the
 * Python microframework. much faster, however! :)
 */
pub struct Canteen {
    routes:  HashMap<String, Route>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).writable() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    fn new(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: Route::_no_op,
        }
    }

    pub fn add_route(&mut self, path: &str, mlist: Vec<Method>, handler: fn(Request) -> Response) {
        let pc = String::from(path);

        if self.routes.contains_key(&pc) {
            panic!("a route handler for {} has already been defined!", path);
        }

        self.routes.insert(String::from(path), Route::new(&path, mlist, handler));
    }

    pub fn set_default(&mut self, handler: fn(Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn find_handler(&self, req: &Request) -> (fn(Request) -> Response) {
        let mut handler: fn(Request) -> Response = self.default;

        for (_, route) in &self.routes {
            match (route).is_match(req) {
                true  => { handler = route.handler; break; },
                false => continue,
            }
        }

        handler
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).readable() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let req = Request::from_str(&rqstr);
                let handler: fn(Request) -> Response = self.find_handler(&req);

                self.get_client(token).o_buf.extend(handler(req).gen_output());
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        /* kill the connection */
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}

fn my_handler(req: Request) -> Response {
    let mut res = Response::new();

    res.set_content_type("text/html");
    res.append(String::from("\

It's alive!

Welcome to Canteen! :)
"));

    res
}

fn main() {
    let mut cnt = Canteen::new(("127.0.0.1", 8080));
    cnt.add_route("/hello", vec![Method::Get], my_handler);
    cnt.set_default(Route::err_404);
    cnt.run();
}
<|endoftext|>


<commit_before>// extern crate libc;

// use libc::types;
use std::io::File;
use std::mem;
use std::os;

// https://stackoverflow.com/questions/24633784/is-there-a-gzip-library-available-for-rust

// #[link(name = "z")]
// extern {
//     fn gzopen(path: *const types::os::arch::c95::c_char,
//               mode: *const types::os::arch::c95::c_char)
//               -> types::common::c95::c_void;
// }

// #[link(name = "z")]
// extern {
//     fn gzread(file: types::common::c95::c_void,
//               buf:  types::common::c95::c_void,
//               len:  uint)
//               -> int;
// }

// #[link(name = "z")]
// extern {
//     fn gzclose(file: types::common::c95::c_void) -> int;
// }

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                let ptr_size = pointer_size();
                println!("size of pointer in bytes: {}", ptr_size);
                println!("Header (12 chars): {}", header);
                let mut ptr_size_differs = false;
                if buf[7] as char == '_' {
                    // 32-bit pointers expected
                    if ptr_size != 4 {
                        ptr_size_differs = true;
                    }
                    println!("32-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                } else {
                    // 64-bit pointers expected
                    if ptr_size != 8 {
                        ptr_size_differs = true;
                    }
                    println!("64-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                }
                // little endian or big endian?
                let mut l_endian;
                let endian_test = 1u16; // value one stored in two bytes
                if endian_test.to_le() != endian_test {
                    l_endian = false;
                } else {
                    // if we are on a little endian machine to_le() is a no-op
                    l_endian = true;
                }
                println!("l_endian = {}", l_endian);
                let mut switch_endian;
                if buf[8] as char == 'v' {
                    // file stores little endian
                    if !l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                } else {
                    // file stores big endian
                    if l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                }
                println!("switch_endian = {}", switch_endian);
                // get the version number
                let mut num = String::new();
                for n in range(9u, 12) {
                    num.push(buf[n] as char);
                }
                println!("num = {}", num);
                // assumes 64-bit pointers (in file as well as on platform)
                loop {
                    // read_file_dna
                    let mut bhead8 = [0u8, ..24]; // 4 * int + 64-bit pointer
                    match file.read(bhead8) {
                        Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                        Ok(_) => (),
                    }
                    // pack those 12 bytes into a string ...
                    let mut bhead = String::new();
                    for n in range(0u, 24) {
                        bhead.push(bhead8[n] as char);
                    }
                    let slice = bhead.as_slice();
                    let code: &str = slice.slice(0, 4); // first 4 chars
                    println!("code = {}", code);
                    let mut len: uint = 0;
                    len += (bhead8[4] as uint) <<  0;
                    len += (bhead8[5] as uint) <<  8;
                    len += (bhead8[6] as uint) << 16;
                    len += (bhead8[7] as uint) << 24;
                    println!("len = {}", len);
                    file.read_exact(len);
                    if code == "ENDB" && len == 0 {
                        break;
                    }
                }
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
    }
}
<commit_msg>Typo.<commit_after>// extern crate libc;

// use libc::types;
use std::io::File;
use std::mem;
use std::os;

// https://stackoverflow.com/questions/24633784/is-there-a-gzip-library-available-for-rust

// #[link(name = "z")]
// extern {
//     fn gzopen(path: *const types::os::arch::c95::c_char,
//               mode: *const types::os::arch::c95::c_char)
//               -> types::common::c95::c_void;
// }

// #[link(name = "z")]
// extern {
//     fn gzread(file: types::common::c95::c_void,
//               buf:  types::common::c95::c_void,
//               len:  uint)
//               -> int;
// }

// #[link(name = "z")]
// extern {
//     fn gzclose(file: types::common::c95::c_void) -> int;
// }

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                let ptr_size = pointer_size();
                println!("size of pointer in bytes: {}", ptr_size);
                println!("Header (12 chars): {}", header);
                let mut ptr_size_differs = false;
                if buf[7] as char == '_' {
                    // 32-bit pointers expected
                    if ptr_size != 4 {
                        ptr_size_differs = true;
                    }
                    println!("32-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                } else {
                    // 64-bit pointers expected
                    if ptr_size != 8 {
                        ptr_size_differs = true;
                    }
                    println!("64-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                }
                // little endian or big endian?
                let mut l_endian;
                let endian_test = 1u16; // value one stored in two bytes
                if endian_test.to_le() != endian_test {
                    l_endian = false;
                } else {
                    // if we are on a little endian machine to_le() is a no-op
                    l_endian = true;
                }
                println!("l_endian = {}", l_endian);
                let mut switch_endian;
                if buf[8] as char == 'v' {
                    // file stores little endian
                    if !l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                } else {
                    // file stores big endian
                    if l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                }
                println!("switch_endian = {}", switch_endian);
                // get the version number
                let mut num = String::new();
                for n in range(9u, 12) {
                    num.push(buf[n] as char);
                }
                println!("num = {}", num);
                // assumes 64-bit pointers (in file as well as on platform)
                loop {
                    // read_file_dna
                    let mut bhead8 = [0u8, ..24]; // 4 * int + 64-bit pointer
                    match file.read(bhead8) {
                        Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                        Ok(_) => (),
                    }
                    // pack those 24 bytes into a string ...
                    let mut bhead = String::new();
                    for n in range(0u, 24) {
                        bhead.push(bhead8[n] as char);
                    }
                    let slice = bhead.as_slice();
                    let code: &str = slice.slice(0, 4); // first 4 chars
                    println!("code = {}", code);
                    let mut len: uint = 0;
                    len += (bhead8[4] as uint) <<  0;
                    len += (bhead8[5] as uint) <<  8;
                    len += (bhead8[6] as uint) << 16;
                    len += (bhead8[7] as uint) << 24;
                    println!("len = {}", len);
                    file.read_exact(len);
                    if code == "ENDB" && len == 0 {
                        break;
                    }
                }
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::vec::Vec;
use autograd::variable::*;
use tensor::*;
use ::*;

thread_local! {
    pub static FUNC_TABLE: RefCell<VecDeque<FuncImpl>> = RefCell::new(VecDeque::new());
}
pub type FuncId = i32;
#[derive(Clone, Debug)]
pub enum RootKind {
    RootVar(VarKind),
    RootFunc(Function),
}
impl RootKind {
    pub fn requires_grad(&self) -> bool {
        match *self {
            RootKind::RootVar(ref v) => v.requires_grad(),
            RootKind::RootFunc(ref f) => f.requires_grad(),
        }
    }
}

pub struct FuncImpl {
    previous_functions: Vec<(RootKind, i32)>,
    saved_variables: Vec<VarId>,
    needs_input_grad: Vec<bool>,
    non_differentiable: Vec<TensorId>,
    dirty_tensors: Vec<TensorKind>,
    output_ids: HashMap<VarId, usize>,
    to_save: Vec<TensorId>,
    requires_grad: bool,
    owner: Option<RcMut<FuncIntf>>,
}
impl Default for FuncImpl {
    fn default() -> Self {
        FuncImpl {
            previous_functions: Vec::new(),
            saved_variables: Vec::new(),
            needs_input_grad: Vec::new(),
            dirty_tensors: Vec::new(),
            non_differentiable: Vec::new(),
            output_ids: HashMap::new(),
            to_save: Vec::new(),
            requires_grad: false,
            owner: None,
        }
    }
}

impl FuncImpl {
    fn _call_hooks(&self, input: &TensorKindList, output: &TensorKindList) {
        unimplemented!();
    }
    fn init(&mut self, intf: RcMut<FuncIntf>) {
        self.owner = Some(intf);
    }
}

#[derive(Clone, Debug)]
pub struct Function {
    pub id: FuncId,
}

impl Default for Function {
    fn default() -> Self {
        Function { id: -1 }
    }
}

pub struct FIWrap<T> {
    value: RcMut<T>,
}
impl<T: 'static + FuncIntf> FIWrap<T> {
    pub fn new(arg: T) -> Self {
        let t = FIWrap { value: RcMutNew(arg) };
        t.value.borrow_mut().delegate().init(t.value.clone());
        t
    }
    pub fn f(&mut self, mut input_: &mut VarKindList) -> VarKindList {
        self.value.borrow_mut().f(input_)
    }
}

impl Function {
    pub fn new() -> Self {
        use std::usize;
        let mut id = usize::MAX;
        FUNC_TABLE.with(|f| {
                            let mut table = f.borrow_mut();
                            id = table.len();
                            table.push_back(FuncImpl::default());
                        });
        Function { id: id as i32 }
    }
    pub fn init(&self, intf: RcMut<FuncIntf>) {
        //FUNC_INTF_TABLE.with(|m| m.borrow_mut().insert(self.id, intf));
        self.access().init(intf)
    }
    pub fn previous_functions(&self) -> &Vec<(RootKind, i32)> {
        &self.access().previous_functions
    }
    pub fn output_ids(&self) -> &HashMap<VarId, usize> {
        &self.access().output_ids
    }
    pub fn requires_grad(&self) -> bool {
        self.access().requires_grad
    }
    pub fn needs_input_grad(&self) -> &Vec<bool> {
        &self.access().needs_input_grad
    }
    pub fn mark_dirty(&mut self, input: &TensorKindList) {
        self.access().dirty_tensors = input.iter().map(|t| t.clone()).collect();
    }
    pub fn mark_non_differentiable(&mut self, input: &TensorKindList) {
        self.access().non_differentiable = input.iter().map(|t| t.id()).collect();
    }
    fn access(&self) -> &mut FuncImpl {
        let vecp = FUNC_TABLE.with(|f| f.as_ptr());
        let vec = unsafe { &mut *vecp };
        &mut vec[self.id as usize]
    }
    pub fn from(id: FuncId) -> Self {
        Function { id: id }
    }
    pub fn saved_tensors(&mut self) -> TensorKindList {
        // XXX see if we can't avoid the clone
        self.access()
            .saved_variables
            .iter()
            .map(|v| VarKind::from(*v).data())
            .collect()
    }
    pub fn saved_variables(&mut self) -> VarKindList {
        // XXX see if we can't avoid the clone
        self.access()
            .saved_variables
            .iter()
            .map(|v| VarKind::from(*v))
            .collect()
    }
    pub fn save_for_backward(&mut self, input: &TensorKindList) {
        self.access().to_save = input.iter().map(|t| t.id()).collect();
    }
    pub fn _do_backward(&mut self,
                        grad_output: &mut OptVarKindList,
                        retain_variables: bool)
                        -> OptVarKindList {
        let inner = self.access();
        if inner.saved_variables.is_empty() {
            panic!("Trying to backward through the graph second \
                    time, but the buffers have already been freed. Please \
                    specify retain_variables=True when calling backward for \
                    the first time.");
        };

        let grad_input = if let Some(ref owner) = inner.owner {
            owner.borrow_mut().backward_var(grad_output)
        } else {
            panic!("owner not set")
        };
        //inner._call_hooks(&grad_input, grad_output);
        if !retain_variables {
            inner.saved_variables.clear();
        };
        grad_input
    }
}

pub trait FuncDelegate {
    fn delegate(&mut self) -> &mut Function;
}

fn ovkl2otkl(input: &mut OptVarKindList) -> OptTensorKindList {
    input
        .iter_mut()
        .map(|ov| match *ov {
                 Some(ref mut v) => Some(v.data().clone()),
                 None => None,
             })
        .collect()
}
fn otkl2ovkl(input: &mut OptTensorKindList) -> OptVarKindList {
    input
        .iter()
        .map(|ov| match ov {
                 &Some(ref v) => Some(v.clone().into()),
                 &None => None,
             })
        .collect()
}

pub trait FuncIntf: FuncDelegate {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList;
    fn backward(&mut self, input: &mut OptTensorKindList) -> OptTensorKindList;

    fn backward_var(&mut self, input: &mut OptVarKindList) -> OptVarKindList {
        let mut input = ovkl2otkl(input);
        let mut output = self.backward(&mut input);
        otkl2ovkl(&mut output)
    }

    fn save_for_backward(&mut self, input: &TensorKindList) {
        self.delegate().save_for_backward(input)
    }
    fn saved_variables(&mut self) -> VarKindList {
        self.delegate().saved_variables()
    }
    fn saved_tensors(&mut self) -> TensorKindList {
        self.delegate().saved_tensors()
    }
    fn needs_input_grad(&mut self) -> &Vec<bool> {
        self.delegate().needs_input_grad()
    }
    fn mark_dirty(&mut self, input: &TensorKindList) {
        self.delegate().mark_dirty(input)
    }
    fn mark_non_differentiable(&mut self, input: &TensorKindList) {
        self.delegate().mark_non_differentiable(input)
    }

    fn f(&mut self, mut input_: &mut VarKindList) -> VarKindList {
        let is_volatile = input_.iter().any(|v| v.is_volatile());
        {
            // do start graph stuff with f
            let f = self.delegate();
            let mut inner = f.access();
            if !is_volatile {
                inner.previous_functions = input_
                    .iter()
                    .map(|v| if let Some(grad_fn) = v.grad_fn() {
                             (RootKind::RootFunc(grad_fn), v.varid())
                         } else {
                             (RootKind::RootVar(v.clone()), v.varid())
                         })
                    .collect();
                inner.needs_input_grad = input_.iter().map(|v| v.requires_grad()).collect();
                inner.requires_grad = inner.needs_input_grad.iter().any(|v| *v);
            }
        }
        let v;
        {
            let mut input_tensors = input_.iter_mut().map(|v| v.data()).collect();
            v = self.forward(&mut input_tensors);
        }
        let f = self.delegate();
        let mut inner = f.access();
        let output = if is_volatile {
            let args = VariableArgs::build().volatile(true).done();
            v.into_iter().map(|t| VarKind::new_args(t, &args)).collect()
        } else {
            let args = VariableArgs::build()
                .creator(Some(f.clone()))
                .requires_grad(inner.requires_grad)
                .done();
            let mut output: VarKindList =
                v.into_iter().map(|t| VarKind::new_args(t, &args)).collect();
            for (i, v) in output.iter().enumerate() {
                inner.output_ids.insert(v.varid(), i);
            }
            if !inner.to_save.is_empty() {
                /* if a tensor was modified in place replace the old variable with the new one */
                let mut t2v = HashMap::new();
                for ref mut var in input_.iter_mut() {
                    t2v.insert(var.tid(), var.varid());
                }
                for ref mut var in &mut output.iter_mut() {
                    t2v.insert(var.tid(), var.varid());
                }
                for t in inner.to_save.iter() {
                    inner.saved_variables.push(t2v[t]);
                }
                inner.to_save.clear();
            };
            if !inner.non_differentiable.is_empty() {
                for ref mut var in &mut output {
                    if inner.non_differentiable.contains(&var.tid()) {
                        var.requires_nograd()
                    }
                }
                inner.non_differentiable.clear();
            };
            output
        };
        output
    }
}
<commit_msg>not all Functions call save_backward<commit_after>use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::vec::Vec;
use autograd::variable::*;
use tensor::*;
use ::*;

thread_local! {
    pub static FUNC_TABLE: RefCell<VecDeque<FuncImpl>> = RefCell::new(VecDeque::new());
}
pub type FuncId = i32;
#[derive(Clone, Debug)]
pub enum RootKind {
    RootVar(VarKind),
    RootFunc(Function),
}
impl RootKind {
    pub fn requires_grad(&self) -> bool {
        match *self {
            RootKind::RootVar(ref v) => v.requires_grad(),
            RootKind::RootFunc(ref f) => f.requires_grad(),
        }
    }
}

pub struct FuncImpl {
    previous_functions: Vec<(RootKind, i32)>,
    saved_variables: Vec<VarId>,
    needs_input_grad: Vec<bool>,
    non_differentiable: Vec<TensorId>,
    dirty_tensors: Vec<TensorKind>,
    output_ids: HashMap<VarId, usize>,
    to_save: Vec<TensorId>,
    requires_grad: bool,
    saved: bool,
    owner: Option<RcMut<FuncIntf>>,
}
impl Default for FuncImpl {
    fn default() -> Self {
        FuncImpl {
            previous_functions: Vec::new(),
            saved_variables: Vec::new(),
            needs_input_grad: Vec::new(),
            dirty_tensors: Vec::new(),
            non_differentiable: Vec::new(),
            output_ids: HashMap::new(),
            to_save: Vec::new(),
            requires_grad: false,
            saved: false,
            owner: None,
        }
    }
}

impl FuncImpl {
    fn _call_hooks(&self, input: &TensorKindList, output: &TensorKindList) {
        unimplemented!();
    }
    fn init(&mut self, intf: RcMut<FuncIntf>) {
        self.owner = Some(intf);
    }
}

#[derive(Clone, Debug)]
pub struct Function {
    pub id: FuncId,
}

impl Default for Function {
    fn default() -> Self {
        Function { id: -1 }
    }
}

pub struct FIWrap<T> {
    value: RcMut<T>,
}
impl<T: 'static + FuncIntf> FIWrap<T> {
    pub fn new(arg: T) -> Self {
        let t = FIWrap { value: RcMutNew(arg) };
        t.value.borrow_mut().delegate().init(t.value.clone());
        t
    }
    pub fn f(&mut self, mut input_: &mut VarKindList) -> VarKindList {
        self.value.borrow_mut().f(input_)
    }
}

impl Function {
    pub fn new() -> Self {
        use std::usize;
        let mut id = usize::MAX;
        FUNC_TABLE.with(|f| {
                            let mut table = f.borrow_mut();
                            id = table.len();
                            table.push_back(FuncImpl::default());
                        });
        Function { id: id as i32 }
    }
    pub fn init(&self, intf: RcMut<FuncIntf>) {
        //FUNC_INTF_TABLE.with(|m| m.borrow_mut().insert(self.id, intf));
        self.access().init(intf)
    }
    pub fn previous_functions(&self) -> &Vec<(RootKind, i32)> {
        &self.access().previous_functions
    }
    pub fn output_ids(&self) -> &HashMap<VarId, usize> {
        &self.access().output_ids
    }
    pub fn requires_grad(&self) -> bool {
        self.access().requires_grad
    }
    pub fn needs_input_grad(&self) -> &Vec<bool> {
        &self.access().needs_input_grad
    }
    pub fn mark_dirty(&mut self, input: &TensorKindList) {
        self.access().dirty_tensors = input.iter().map(|t| t.clone()).collect();
    }
    pub fn mark_non_differentiable(&mut self, input: &TensorKindList) {
        self.access().non_differentiable = input.iter().map(|t| t.id()).collect();
    }
    fn access(&self) -> &mut FuncImpl {
        let vecp = FUNC_TABLE.with(|f| f.as_ptr());
        let vec = unsafe { &mut *vecp };
        &mut vec[self.id as usize]
    }
    pub fn from(id: FuncId) -> Self {
        Function { id: id }
    }
    pub fn saved_tensors(&mut self) -> TensorKindList {
        // XXX see if we can't avoid the clone
        self.access()
            .saved_variables
            .iter()
            .map(|v| VarKind::from(*v).data())
            .collect()
    }
    pub fn saved_variables(&mut self) -> VarKindList {
        // XXX see if we can't avoid the clone
        self.access()
            .saved_variables
            .iter()
            .map(|v| VarKind::from(*v))
            .collect()
    }
    pub fn save_for_backward(&mut self, input: &TensorKindList) {
        self.access().saved = true;
        self.access().to_save = input.iter().map(|t| t.id()).collect();
    }
    pub fn _do_backward(&mut self,
                        grad_output: &mut OptVarKindList,
                        retain_variables: bool)
                        -> OptVarKindList {
        let inner = self.access();
        if  inner.saved  && inner.saved_variables.is_empty() {
            panic!("Trying to backward through the graph second \
                    time, but the buffers have already been freed. Please \
                    specify retain_variables=True when calling backward for \
                    the first time.");
        };

        let grad_input = if let Some(ref owner) = inner.owner {
            owner.borrow_mut().backward_var(grad_output)
        } else {
            panic!("owner not set")
        };
        //inner._call_hooks(&grad_input, grad_output);
        if !retain_variables {
            inner.saved_variables.clear();
        };
        grad_input
    }
}

pub trait FuncDelegate {
    fn delegate(&mut self) -> &mut Function;
}

fn ovkl2otkl(input: &mut OptVarKindList) -> OptTensorKindList {
    input
        .iter_mut()
        .map(|ov| match *ov {
                 Some(ref mut v) => Some(v.data().clone()),
                 None => None,
             })
        .collect()
}
fn otkl2ovkl(input: &mut OptTensorKindList) -> OptVarKindList {
    input
        .iter()
        .map(|ov| match ov {
                 &Some(ref v) => Some(v.clone().into()),
                 &None => None,
             })
        .collect()
}

pub trait FuncIntf: FuncDelegate {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList;
    fn backward(&mut self, input: &mut OptTensorKindList) -> OptTensorKindList;

    fn backward_var(&mut self, input: &mut OptVarKindList) -> OptVarKindList {
        let mut input = ovkl2otkl(input);
        let mut output = self.backward(&mut input);
        otkl2ovkl(&mut output)
    }

    fn save_for_backward(&mut self, input: &TensorKindList) {
        self.delegate().save_for_backward(input)
    }
    fn saved_variables(&mut self) -> VarKindList {
        self.delegate().saved_variables()
    }
    fn saved_tensors(&mut self) -> TensorKindList {
        self.delegate().saved_tensors()
    }
    fn needs_input_grad(&mut self) -> &Vec<bool> {
        self.delegate().needs_input_grad()
    }
    fn mark_dirty(&mut self, input: &TensorKindList) {
        self.delegate().mark_dirty(input)
    }
    fn mark_non_differentiable(&mut self, input: &TensorKindList) {
        self.delegate().mark_non_differentiable(input)
    }

    fn f(&mut self, mut input_: &mut VarKindList) -> VarKindList {
        let is_volatile = input_.iter().any(|v| v.is_volatile());
        {
            // do start graph stuff with f
            let f = self.delegate();
            let mut inner = f.access();
            if !is_volatile {
                inner.previous_functions = input_
                    .iter()
                    .map(|v| if let Some(grad_fn) = v.grad_fn() {
                             (RootKind::RootFunc(grad_fn), v.varid())
                         } else {
                             (RootKind::RootVar(v.clone()), v.varid())
                         })
                    .collect();
                inner.needs_input_grad = input_.iter().map(|v| v.requires_grad()).collect();
                inner.requires_grad = inner.needs_input_grad.iter().any(|v| *v);
            }
        }
        let v;
        {
            let mut input_tensors = input_.iter_mut().map(|v| v.data()).collect();
            v = self.forward(&mut input_tensors);
        }
        let f = self.delegate();
        let mut inner = f.access();
        let output = if is_volatile {
            let args = VariableArgs::build().volatile(true).done();
            v.into_iter().map(|t| VarKind::new_args(t, &args)).collect()
        } else {
            let args = VariableArgs::build()
                .creator(Some(f.clone()))
                .requires_grad(inner.requires_grad)
                .done();
            let mut output: VarKindList =
                v.into_iter().map(|t| VarKind::new_args(t, &args)).collect();
            for (i, v) in output.iter().enumerate() {
                inner.output_ids.insert(v.varid(), i);
            }
            if !inner.to_save.is_empty() {
                /* if a tensor was modified in place replace the old variable with the new one */
                let mut t2v = HashMap::new();
                for ref mut var in input_.iter_mut() {
                    t2v.insert(var.tid(), var.varid());
                }
                for ref mut var in &mut output.iter_mut() {
                    t2v.insert(var.tid(), var.varid());
                }
                for t in inner.to_save.iter() {
                    inner.saved_variables.push(t2v[t]);
                }
                inner.to_save.clear();
            };
            if !inner.non_differentiable.is_empty() {
                for ref mut var in &mut output {
                    if inner.non_differentiable.contains(&var.tid()) {
                        var.requires_nograd()
                    }
                }
                inner.non_differentiable.clear();
            };
            output
        };
        output
    }
}
<|endoftext|>