<commit_before>// This benchmark suite contains some benchmarks along a set of dimensions:
//   Hasher: std default (SipHash) and crate default (FxHash).
//   Int key distribution: low bit heavy, top bit heavy, and random.
//   Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter
#![feature(test)]

extern crate test;

use test::{black_box, Bencher};

use hashbrown::hash_map::DefaultHashBuilder;
use hashbrown::HashMap;
use std::collections::hash_map::RandomState;

const SIZE: usize = 1000;

// The default hashmap when using this crate directly.
type FxHashMap<K, V> = HashMap<K, V, DefaultHashBuilder>;
// This uses the hashmap from this crate with the default hasher of the stdlib.
type StdHashMap<K, V> = HashMap<K, V, RandomState>;

// A random key iterator.
#[derive(Clone, Copy)]
struct RandomKeys {
    remaining: usize,
    state: usize,
}

impl RandomKeys {
    fn new(size: usize) -> Self {
        RandomKeys {
            remaining: size,
            state: 1,
        }
    }

    // Produce a different set of random values.
    fn new2(size: usize) -> Self {
        RandomKeys {
            remaining: size,
            state: 2,
        }
    }
}

impl Iterator for RandomKeys {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        if self.remaining == 0 {
            None
        } else {
            self.remaining -= 1;
            // Multiply by some 32 bit prime.
            self.state = self.state.wrapping_mul(3787392781);
            // Mix in to the bottom bits which are constant mod powers of 2.
            Some(self.state ^ (self.state >> 4))
        }
    }
}

macro_rules! bench_insert {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in $keydist {
                    m.insert(i, i);
                }
                black_box(m);
            })
        }
    };
}

bench_insert!(insert_fx_serial, FxHashMap, 0..SIZE);
bench_insert!(insert_std_serial, StdHashMap, 0..SIZE);
bench_insert!(
    insert_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert!(
    insert_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert!(insert_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_insert!(insert_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_insert_erase {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in $keydist {
                    m.insert(i, i);
                }
                black_box(&mut m);
                for i in $keydist {
                    m.remove(&i);
                }
                black_box(m);
            })
        }
    };
}

bench_insert_erase!(insert_erase_fx_serial, FxHashMap, 0..SIZE);
bench_insert_erase!(insert_erase_std_serial, StdHashMap, 0..SIZE);
bench_insert_erase!(
    insert_erase_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert_erase!(
    insert_erase_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert_erase!(insert_erase_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_insert_erase!(insert_erase_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_lookup {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist {
                    black_box(m.get(&i));
                }
            })
        }
    };
}

bench_lookup!(lookup_fx_serial, FxHashMap, 0..SIZE);
bench_lookup!(lookup_std_serial, StdHashMap, 0..SIZE);
bench_lookup!(
    lookup_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_lookup!(
    lookup_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_lookup!(lookup_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_lookup!(lookup_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_lookup_fail {
    ($name:ident, $maptype:ident, $keydist:expr, $keydist2:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist2 {
                    black_box(m.get(&i));
                }
            })
        }
    };
}

bench_lookup_fail!(lookup_fail_fx_serial, FxHashMap, 0..SIZE, SIZE..SIZE * 2);
bench_lookup_fail!(lookup_fail_std_serial, StdHashMap, 0..SIZE, SIZE..SIZE * 2);
bench_lookup_fail!(
    lookup_fail_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes),
    (SIZE..SIZE * 2).map(usize::swap_bytes)
);
bench_lookup_fail!(
    lookup_fail_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes),
    (SIZE..SIZE * 2).map(usize::swap_bytes)
);
bench_lookup_fail!(
    lookup_fail_fx_random,
    FxHashMap,
    RandomKeys::new(SIZE),
    RandomKeys::new2(SIZE)
);
bench_lookup_fail!(
    lookup_fail_std_random,
    StdHashMap,
    RandomKeys::new(SIZE),
    RandomKeys::new2(SIZE)
);

macro_rules! bench_iter {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in &m {
                    black_box(i);
                }
            })
        }
    };
}

bench_iter!(iter_fx_serial, FxHashMap, 0..SIZE);
bench_iter!(iter_std_serial, StdHashMap, 0..SIZE);
bench_iter!(
    iter_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_iter!(
    iter_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_iter!(iter_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_iter!(iter_std_random, StdHashMap, RandomKeys::new(SIZE));
<commit_msg>Update insert_erase benchmark to keep the table size constant.<commit_after>// This benchmark suite contains some benchmarks along a set of dimensions:
//   Hasher: std default (SipHash) and crate default (FxHash).
//   Int key distribution: low bit heavy, top bit heavy, and random.
//   Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter
#![feature(test)]

extern crate test;

use test::{black_box, Bencher};

use hashbrown::hash_map::DefaultHashBuilder;
use hashbrown::HashMap;
use std::collections::hash_map::RandomState;

const SIZE: usize = 1000;

// The default hashmap when using this crate directly.
type FxHashMap<K, V> = HashMap<K, V, DefaultHashBuilder>;
// This uses the hashmap from this crate with the default hasher of the stdlib.
type StdHashMap<K, V> = HashMap<K, V, RandomState>;

// A random key iterator.
#[derive(Clone, Copy)]
struct RandomKeys {
    state: usize,
}

impl RandomKeys {
    fn new() -> Self {
        RandomKeys { state: 0 }
    }
}

impl Iterator for RandomKeys {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        // Add 1 then multiply by some 32 bit prime.
        self.state = self.state.wrapping_add(1).wrapping_mul(3787392781);
        Some(self.state)
    }
}

macro_rules! bench_suite {
    ($bench_macro:ident, $bench_fx_serial:ident, $bench_std_serial:ident,
     $bench_fx_highbits:ident, $bench_std_highbits:ident,
     $bench_fx_random:ident, $bench_std_random:ident) => {
        $bench_macro!($bench_fx_serial, FxHashMap, 0..);
        $bench_macro!($bench_std_serial, StdHashMap, 0..);
        $bench_macro!($bench_fx_highbits, FxHashMap, (0..).map(usize::swap_bytes));
        $bench_macro!(
            $bench_std_highbits,
            StdHashMap,
            (0..).map(usize::swap_bytes)
        );
        $bench_macro!($bench_fx_random, FxHashMap, RandomKeys::new());
        $bench_macro!($bench_std_random, StdHashMap, RandomKeys::new());
    };
}

macro_rules! bench_insert {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in ($keydist).take(SIZE) {
                    m.insert(i, i);
                }
                black_box(m);
            })
        }
    };
}

bench_suite!(
    bench_insert,
    insert_fx_serial,
    insert_std_serial,
    insert_fx_highbits,
    insert_std_highbits,
    insert_fx_random,
    insert_std_random
);

macro_rules! bench_insert_erase {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            let mut add_iter = $keydist;
            for i in (&mut add_iter).take(SIZE) {
                m.insert(i, i);
            }
            let mut remove_iter = $keydist;
            b.iter(|| {
                // While keeping the size constant,
                // replace the first keydist with the second.
                for (add, remove) in (&mut add_iter).zip(&mut remove_iter).take(SIZE) {
                    m.insert(add, add);
                    black_box(m.remove(&remove));
                }
            })
        }
    };
}

bench_suite!(
    bench_insert_erase,
    insert_erase_fx_serial,
    insert_erase_std_serial,
    insert_erase_fx_highbits,
    insert_erase_std_highbits,
    insert_erase_fx_random,
    insert_erase_std_random
);

macro_rules! bench_lookup {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist.take(SIZE) {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist.take(SIZE) {
                    black_box(m.get(&i));
                }
            })
        }
    };
}

bench_suite!(
    bench_lookup,
    lookup_fx_serial,
    lookup_std_serial,
    lookup_fx_highbits,
    lookup_std_highbits,
    lookup_fx_random,
    lookup_std_random
);

macro_rules! bench_lookup_fail {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            let mut iter = $keydist;
            for i in (&mut iter).take(SIZE) {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in (&mut iter).take(SIZE) {
                    black_box(m.get(&i));
                }
            })
        }
    };
}

bench_suite!(
    bench_lookup_fail,
    lookup_fail_fx_serial,
    lookup_fail_std_serial,
    lookup_fail_fx_highbits,
    lookup_fail_std_highbits,
    lookup_fail_fx_random,
    lookup_fail_std_random
);

macro_rules! bench_iter {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in ($keydist).take(SIZE) {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in &m {
                    black_box(i);
                }
            })
        }
    };
}

bench_suite!(
    bench_iter,
    iter_fx_serial,
    iter_std_serial,
    iter_fx_highbits,
    iter_std_highbits,
    iter_fx_random,
    iter_std_random
);
<|endoftext|>


<commit_before>#![feature(test)]

extern crate glob;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate test;

const SHORT: &'static str = "some/needle.txt";
const SHORT_PAT: &'static str = "some/**/needle.txt";

const LONG: &'static str = "some/a/bigger/path/to/the/crazy/needle.txt";
const LONG_PAT: &'static str = "some/**/needle.txt";

#[allow(dead_code, unused_variables)]
#[path = "../src/glob.rs"]
mod reglob;

fn new_glob(pat: &str) -> glob::Pattern {
    glob::Pattern::new(pat).unwrap()
}

fn new_reglob(pat: &str) -> reglob::Set {
    let mut builder = reglob::SetBuilder::new();
    builder.add(pat).unwrap();
    builder.build().unwrap()
}

fn new_reglob_many(pats: &[&str]) -> reglob::Set {
    let mut builder = reglob::SetBuilder::new();
    for pat in pats {
        builder.add(pat).unwrap();
    }
    builder.build().unwrap()
}

#[bench]
fn short_glob(b: &mut test::Bencher) {
    let pat = new_glob(SHORT_PAT);
    b.iter(|| assert!(pat.matches(SHORT)));
}

#[bench]
fn short_regex(b: &mut test::Bencher) {
    let set = new_reglob(SHORT_PAT);
    b.iter(|| assert!(set.is_match(SHORT)));
}

#[bench]
fn long_glob(b: &mut test::Bencher) {
    let pat = new_glob(LONG_PAT);
    b.iter(|| assert!(pat.matches(LONG)));
}

#[bench]
fn long_regex(b: &mut test::Bencher) {
    let set = new_reglob(LONG_PAT);
    b.iter(|| assert!(set.is_match(LONG)));
}

const MANY_SHORT_GLOBS: &'static [&'static str] = &[
    // Taken from a random .gitignore on my system.
    ".*.swp",
    "tags",
    "target",
    "*.lock",
    "tmp",
    "*.csv",
    "*.fst",
    "*-got",
    "*.csv.idx",
    "words",
    "98m*",
    "dict",
    "test",
    "months",
];

const MANY_SHORT_SEARCH: &'static str = "98m-blah.csv.idx";

#[bench]
fn many_short_glob(b: &mut test::Bencher) {
    let pats: Vec<_> = MANY_SHORT_GLOBS.iter().map(|&s| new_glob(s)).collect();
    b.iter(|| {
        let mut count = 0;
        for pat in &pats {
            if pat.matches(MANY_SHORT_SEARCH) {
                count += 1;
            }
        }
        assert_eq!(2, count);
    })
}

#[bench]
fn many_short_regex_set(b: &mut test::Bencher) {
    let set = new_reglob_many(MANY_SHORT_GLOBS);
    b.iter(|| assert_eq!(2, set.matches(MANY_SHORT_SEARCH).iter().count()));
}

// This is the fastest on my system (beating many_glob by about 2x). This
// suggests that a RegexSet needs quite a few regexes (or a larger haystack)
// in order for it to scale.
//
// TODO(burntsushi): come up with a benchmark that uses more complex patterns
// or a longer haystack.
#[bench]
fn many_short_regex_pattern(b: &mut test::Bencher) {
    let pats: Vec<_> = MANY_SHORT_GLOBS.iter().map(|&s| {
        let pat = reglob::Pattern::new(s).unwrap();
        regex::Regex::new(&pat.to_regex()).unwrap()
    }).collect();
    b.iter(|| {
        let mut count = 0;
        for pat in &pats {
            if pat.is_match(MANY_SHORT_SEARCH) {
                count += 1;
            }
        }
        assert_eq!(2, count);
    })
}
<commit_msg>Add doc.<commit_after>/*!
This module benchmarks the glob implementation. For benchmarks on the ripgrep
tool itself, see the benchsuite directory.
*/
#![feature(test)]

extern crate glob;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate test;

const SHORT: &'static str = "some/needle.txt";
const SHORT_PAT: &'static str = "some/**/needle.txt";

const LONG: &'static str = "some/a/bigger/path/to/the/crazy/needle.txt";
const LONG_PAT: &'static str = "some/**/needle.txt";

#[allow(dead_code, unused_variables)]
#[path = "../src/glob.rs"]
mod reglob;

fn new_glob(pat: &str) -> glob::Pattern {
    glob::Pattern::new(pat).unwrap()
}

fn new_reglob(pat: &str) -> reglob::Set {
    let mut builder = reglob::SetBuilder::new();
    builder.add(pat).unwrap();
    builder.build().unwrap()
}

fn new_reglob_many(pats: &[&str]) -> reglob::Set {
    let mut builder = reglob::SetBuilder::new();
    for pat in pats {
        builder.add(pat).unwrap();
    }
    builder.build().unwrap()
}

#[bench]
fn short_glob(b: &mut test::Bencher) {
    let pat = new_glob(SHORT_PAT);
    b.iter(|| assert!(pat.matches(SHORT)));
}

#[bench]
fn short_regex(b: &mut test::Bencher) {
    let set = new_reglob(SHORT_PAT);
    b.iter(|| assert!(set.is_match(SHORT)));
}

#[bench]
fn long_glob(b: &mut test::Bencher) {
    let pat = new_glob(LONG_PAT);
    b.iter(|| assert!(pat.matches(LONG)));
}

#[bench]
fn long_regex(b: &mut test::Bencher) {
    let set = new_reglob(LONG_PAT);
    b.iter(|| assert!(set.is_match(LONG)));
}

const MANY_SHORT_GLOBS: &'static [&'static str] = &[
    // Taken from a random .gitignore on my system.
    ".*.swp",
    "tags",
    "target",
    "*.lock",
    "tmp",
    "*.csv",
    "*.fst",
    "*-got",
    "*.csv.idx",
    "words",
    "98m*",
    "dict",
    "test",
    "months",
];

const MANY_SHORT_SEARCH: &'static str = "98m-blah.csv.idx";

#[bench]
fn many_short_glob(b: &mut test::Bencher) {
    let pats: Vec<_> = MANY_SHORT_GLOBS.iter().map(|&s| new_glob(s)).collect();
    b.iter(|| {
        let mut count = 0;
        for pat in &pats {
            if pat.matches(MANY_SHORT_SEARCH) {
                count += 1;
            }
        }
        assert_eq!(2, count);
    })
}

#[bench]
fn many_short_regex_set(b: &mut test::Bencher) {
    let set = new_reglob_many(MANY_SHORT_GLOBS);
    b.iter(|| assert_eq!(2, set.matches(MANY_SHORT_SEARCH).iter().count()));
}

// This is the fastest on my system (beating many_glob by about 2x). This
// suggests that a RegexSet needs quite a few regexes (or a larger haystack)
// in order for it to scale.
//
// TODO(burntsushi): come up with a benchmark that uses more complex patterns
// or a longer haystack.
#[bench]
fn many_short_regex_pattern(b: &mut test::Bencher) {
    let pats: Vec<_> = MANY_SHORT_GLOBS.iter().map(|&s| {
        let pat = reglob::Pattern::new(s).unwrap();
        regex::Regex::new(&pat.to_regex()).unwrap()
    }).collect();
    b.iter(|| {
        let mut count = 0;
        for pat in &pats {
            if pat.is_match(MANY_SHORT_SEARCH) {
                count += 1;
            }
        }
        assert_eq!(2, count);
    })
}
<|endoftext|>


<commit_before>use std::ptr;
use ui_ffi::*;
use std::fmt;
use std::fmt::Write;
use scintilla::Scintilla;
use std::os::raw::{c_void};

use CFixedString;

/// Taken from minifb. Not sure if we can share this somehow?
/// Key is used by the get key functions to check if some keys on the keyboard has been pressed
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Key {
    Key0 = 0,
    Key1 = 1,
    Key2 = 2,
    Key3 = 3,
    Key4 = 4,
    Key5 = 5,
    Key6 = 6,
    Key7 = 7,
    Key8 = 8,
    Key9 = 9,

    A = 10,
    B = 11,
    C = 12,
    D = 13,
    E = 14,
    F = 15,
    G = 16,
    H = 17,
    I = 18,
    J = 19,
    K = 20,
    L = 21,
    M = 22,
    N = 23,
    O = 24,
    P = 25,
    Q = 26,
    R = 27,
    S = 28,
    T = 29,
    U = 30,
    V = 31,
    W = 32,
    X = 33,
    Y = 34,
    Z = 35,

    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,

    Down,
    Left,
    Right,
    Up,
    Apostrophe,
    Backquote,

    Backslash,
    Comma,
    Equal,
    LeftBracket,
    Minus,
    Period,
    RightBracket,
    Semicolon,

    Slash,
    Backspace,
    Delete,
    End,
    Enter,

    Escape,

    Home,
    Insert,
    Menu,

    PageDown,
    PageUp,

    Pause,
    Space,
    Tab,
    NumLock,
    CapsLock,
    ScrollLock,
    LeftShift,
    RightShift,
    LeftCtrl,
    RightCtrl,

    NumPad0,
    NumPad1,
    NumPad2,
    NumPad3,
    NumPad4,
    NumPad5,
    NumPad6,
    NumPad7,
    NumPad8,
    NumPad9,
    NumPadDot,
    NumPadSlash,
    NumPadAsterisk,
    NumPadMinus,
    NumPadPlus,
    NumPadEnter,

    LeftAlt,
    RightAlt,

    LeftSuper,
    RightSuper,

    /// Used when an Unknown key has been pressed
    Unknown,

    Count = 107,
}

#[derive(Clone)]
pub struct Ui {
    pub api: *mut CPdUI,
    fmt_buffer: String,
}

#[derive(Clone, Copy, Debug)]
pub struct Color {
    color: u32,
}

impl Color {
    pub fn from_u32(color: u32) -> Color {
        Color { color: color }
    }

    pub fn from_rgb(r: u32, g: u32, b: u32) -> Color {
        Self::from_u32((255 << 24) | (r << 16) | (g << 8) | b)
    }

    pub fn from_rgba(r: u32, g: u32, b: u32, a: u32) -> Color {
        Self::from_u32((a << 24) | (r << 16) | (g << 8) | b)
    }

    pub fn from_argb(a: u32, r: u32, g: u32, b: u32) -> Color {
        Self::from_u32((a << 24) | (r << 16) | (g << 8) | b)
    }
    pub fn from_au32(a: u32, rgb: u32) -> Color {
        Self::from_u32((a << 24) | rgb)
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}

impl Vec2 {
    pub fn new(x: f32, y: f32) -> Vec2 {
        Vec2 { x: x, y: y }
    }
}

macro_rules! true_is_1 {
    ($e:expr) => (if $e { 1 } else { 0 })
}

macro_rules! int_to_bool {
    ($e:expr) => (if $e == 1 { true } else { false })
}

impl Ui {
    pub fn new(native_api: *mut CPdUI) -> Ui {
        Ui {
            api: native_api,
            fmt_buffer: String::with_capacity(2048),
        }
    }

    pub fn set_title(&self, title: &str) {
        unsafe {
            let t = CFixedString::from_str(title).as_ptr();
            ((*self.api).set_title)((*self.api).private_data, t);
        }
    }

    #[inline]
    pub fn get_window_size(&self) -> (f32, f32) {
        unsafe {
            let t = ((*self.api).get_window_size)();
            (t.x, t.y)
        }
    }

    #[inline]
    pub fn get_window_pos(&self) -> PDVec2 {
        unsafe { ((*self.api).get_window_pos)() }
    }

    #[inline]
    pub fn get_text_line_height_with_spacing(&self) -> f32 {
        unsafe { ((*self.api).get_text_line_height_with_spacing)() as f32 }
    }

    #[inline]
    pub fn get_cursor_pos(&self) -> (f32, f32) {
        unsafe {
            let t = ((*self.api).get_cursor_pos)();
            (t.x, t.y)
        }
    }

    #[inline]
    pub fn get_cursor_screen_pos(&self) -> (f32, f32) {
        unsafe {
            let t = ((*self.api).get_cursor_screen_pos)();
            (t.x, t.y)
        }
    }

    #[inline]
    pub fn fill_rect(&self, x: f32, y: f32, width: f32, height: f32, col: Color) {
        unsafe {
            ((*self.api).fill_rect)(PDRect { x: x, y: y, width: width, height: height }, col.color);
        }
    }

    #[inline]
    pub fn set_scroll_here(&self, center: f32) {
        unsafe { ((*self.api).set_scroll_here)(center) }
    }

    pub fn begin_child(&self, id: &str, pos: Option<PDVec2>, border: bool, flags: u32) {
        unsafe {
            let t = CFixedString::from_str(id).as_ptr();
            match pos {
                Some(p) => ((*self.api).begin_child)(t, p, border as i32, flags as i32),
                None => {
                    ((*self.api).begin_child)(t,
                                              PDVec2 { x: 0.0, y: 0.0 },
                                              border as i32,
                                              flags as i32)
                }
            }
        }
    }

    #[inline]
    pub fn end_child(&self) {
        unsafe { ((*self.api).end_child)() }
    }

    #[inline]
    pub fn get_scroll_y(&self) -> f32 {
        unsafe { ((*self.api).get_scroll_y)() as f32 }
    }

    #[inline]
    pub fn get_scroll_max_y(&self) -> f32 {
        unsafe { ((*self.api).get_scroll_max_y)() as f32 }
    }

    #[inline]
    pub fn set_scroll_y(&self, pos: f32) {
        unsafe { ((*self.api).set_scroll_y)(pos) }
    }

    #[inline]
    pub fn set_scroll_from_pos_y(&self, pos_y: f32, center_ratio: f32) {
        unsafe { ((*self.api).set_scroll_from_pos_y)(pos_y, center_ratio) }
    }

    #[inline]
    pub fn set_keyboard_focus_here(&self, offset: i32) {
        unsafe { ((*self.api).set_keyboard_focus_here)(offset) }
    }

    // TODO: push/pop font

    #[inline]
	pub fn push_style_color(&self, index: usize, col: Color) {
        unsafe { ((*self.api).push_style_color)(index as u32, col.color) }
    }

    #[inline]
	pub fn pop_style_color(&self, index: usize) {
        unsafe { ((*self.api).pop_style_color)(index as i32) }
    }

    #[inline]
	pub fn push_style_var(&self, index: usize, val: f32) {
        unsafe { ((*self.api).push_style_var)(index as u32, val) }
    }

    #[inline]
	pub fn push_style_var_vec(&self, index: usize, val: PDVec2) {
        unsafe { ((*self.api).push_style_var_vec)(index as u32, val) }
    }

    #[inline]
    pub fn get_font_size(&self) -> f32 {
        unsafe { ((*self.api).get_font_size)() }
    }

    #[inline]
    pub fn calc_text_size(&self, text: &str, offset: usize) -> (f32, f32) {
        unsafe {
            if offset == 0 {
                let t = ((*self.api).calc_text_size)(text.as_ptr(), ptr::null(), 0, -1.0);
                (t.x, t.y)
            } else {
                let slice = &text[offset..];
                let t = ((*self.api).calc_text_size)(text.as_ptr(), slice.as_ptr(), 0, -1.0);
                (t.x, t.y)
            }
        }
    }

    // Text

    pub fn text(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text)(t);
        }
    }

    pub fn text_fmt(&mut self, args: fmt::Arguments) {
        unsafe {
            self.fmt_buffer.clear();
            write!(&mut self.fmt_buffer, "{}", args).unwrap();
            let t = CFixedString::from_str(&self.fmt_buffer).as_ptr();
            ((*self.api).text)(t);
        }
    }

    pub fn text_colored(&self, col: Color, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text_colored)(col.color, t);
        }
    }

    pub fn text_disabled(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text_disabled)(t);
        }
    }

    pub fn text_wrapped(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text_wrapped)(t);
        }
    }

	pub fn columns(&self, count: isize, id: Option<&str>, border: bool) {
	    unsafe {
            match id {
                Some(p) => {
                    let t = CFixedString::from_str(p).as_ptr();
                    ((*self.api).columns)(count as i32, t, border as i32)
                }
                None => ((*self.api).columns)(count as i32, ptr::null(), border as i32),
            }
        }
    }

    #[inline]
    pub fn next_column(&self) {
        unsafe { ((*self.api).next_column)() }
    }

    pub fn button(&self, title: &str, pos: Option<PDVec2>) -> bool {
        unsafe {
            let t = CFixedString::from_str(title).as_ptr();
            match pos {
                Some(p) => ((*self.api).button)(t, p) != 0,
                None => ((*self.api).button)(t, PDVec2 { x: 0.0, y: 0.0 }) != 0,
            }
        }
    }
    pub fn begin_popup(&self, text: &str) -> bool {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            int_to_bool!(((*self.api).begin_popup)(t))
        }
    }

    pub fn begin_menu(&self, text: &str, enabled: bool) -> bool {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            let s = if enabled { 1 } else { 0 };
            int_to_bool!(((*self.api).begin_menu)(t, s))
        }
    }

    pub fn open_popup(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).open_popup)(t);
        }
    }

	pub fn menu_item(&self, text: &str, selected: bool, enabled: bool) -> bool {
        unsafe {
            let name = CFixedString::from_str(text).as_ptr();
            let s = if selected { 1 } else { 0 };
            let e = if enabled { 1 } else { 0 };
            int_to_bool!(((*self.api).menu_item)(name, ptr::null(), s, e))
        }
    }

    pub fn end_menu(&self) {
        unsafe { ((*self.api).end_menu)() }
    }

    pub fn end_popup(&self) {
        unsafe { ((*self.api).end_popup)() }
    }

	pub fn sc_input_text(&self, title: &str, width: usize, height: usize) -> Scintilla {
	    unsafe {
            let name = CFixedString::from_str(title);
	        Scintilla::new(((*self.api).sc_input_text)(name.as_ptr(),
	                        width as f32,
	                        height as f32, None))
        }
    }

    ///
    /// Keyboard support
    ///

	pub fn is_key_down(&self, key: Key) -> bool {
        unsafe { int_to_bool!(((*self.api).is_key_down)(key as i32)) }
    }

	pub fn is_key_pressed(&self, key: Key, repeat: bool) -> bool {
        unsafe { int_to_bool!(((*self.api).is_key_pressed)(key as i32, true_is_1!(repeat))) }
    }

	pub fn is_key_released(&self, key: Key) -> bool {
        unsafe { int_to_bool!(((*self.api).is_key_released)(key as i32)) }
    }

    ///
    /// Rendering primitives
    ///

    pub fn fill_convex_poly(&self, vertices: &[Vec2], col: Color, anti_aliased: bool) {
	    unsafe {
            ((*self.api).fill_convex_poly)(
                vertices.as_ptr() as *const c_void,
                vertices.len() as u32,
                col.color,
                true_is_1!(anti_aliased))
        }
    }

    pub fn fill_circle(&self, pos: &Vec2, radius: f32, col: Color, segment_count: usize, anti_aliased: bool) {
	    unsafe {
            ((*self.api).fill_circle)(
                PDVec2 { x: pos.x, y: pos.y },
                radius,
                col.color,
                segment_count as u32,
                true_is_1!(anti_aliased))
        }
    }
}

<commit_msg>Added set_cursor_pos<commit_after>use std::ptr;
use ui_ffi::*;
use std::fmt;
use std::fmt::Write;
use scintilla::Scintilla;
use std::os::raw::{c_void};

use CFixedString;

/// Taken from minifb. Not sure if we can share this somehow?
/// Key is used by the get key functions to check if some keys on the keyboard has been pressed
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Key {
    Key0 = 0,
    Key1 = 1,
    Key2 = 2,
    Key3 = 3,
    Key4 = 4,
    Key5 = 5,
    Key6 = 6,
    Key7 = 7,
    Key8 = 8,
    Key9 = 9,

    A = 10,
    B = 11,
    C = 12,
    D = 13,
    E = 14,
    F = 15,
    G = 16,
    H = 17,
    I = 18,
    J = 19,
    K = 20,
    L = 21,
    M = 22,
    N = 23,
    O = 24,
    P = 25,
    Q = 26,
    R = 27,
    S = 28,
    T = 29,
    U = 30,
    V = 31,
    W = 32,
    X = 33,
    Y = 34,
    Z = 35,

    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,

    Down,
    Left,
    Right,
    Up,
    Apostrophe,
    Backquote,

    Backslash,
    Comma,
    Equal,
    LeftBracket,
    Minus,
    Period,
    RightBracket,
    Semicolon,

    Slash,
    Backspace,
    Delete,
    End,
    Enter,

    Escape,

    Home,
    Insert,
    Menu,

    PageDown,
    PageUp,

    Pause,
    Space,
    Tab,
    NumLock,
    CapsLock,
    ScrollLock,
    LeftShift,
    RightShift,
    LeftCtrl,
    RightCtrl,

    NumPad0,
    NumPad1,
    NumPad2,
    NumPad3,
    NumPad4,
    NumPad5,
    NumPad6,
    NumPad7,
    NumPad8,
    NumPad9,
    NumPadDot,
    NumPadSlash,
    NumPadAsterisk,
    NumPadMinus,
    NumPadPlus,
    NumPadEnter,

    LeftAlt,
    RightAlt,

    LeftSuper,
    RightSuper,

    /// Used when an Unknown key has been pressed
    Unknown,

    Count = 107,
}

#[derive(Clone)]
pub struct Ui {
    pub api: *mut CPdUI,
    fmt_buffer: String,
}

#[derive(Clone, Copy, Debug)]
pub struct Color {
    color: u32,
}

impl Color {
    pub fn from_u32(color: u32) -> Color {
        Color { color: color }
    }

    pub fn from_rgb(r: u32, g: u32, b: u32) -> Color {
        Self::from_u32((255 << 24) | (r << 16) | (g << 8) | b)
    }

    pub fn from_rgba(r: u32, g: u32, b: u32, a: u32) -> Color {
        Self::from_u32((a << 24) | (r << 16) | (g << 8) | b)
    }

    pub fn from_argb(a: u32, r: u32, g: u32, b: u32) -> Color {
        Self::from_u32((a << 24) | (r << 16) | (g << 8) | b)
    }
    pub fn from_au32(a: u32, rgb: u32) -> Color {
        Self::from_u32((a << 24) | rgb)
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}

impl Vec2 {
    pub fn new(x: f32, y: f32) -> Vec2 {
        Vec2 { x: x, y: y }
    }
}

macro_rules! true_is_1 {
    ($e:expr) => (if $e { 1 } else { 0 })
}

macro_rules! int_to_bool {
    ($e:expr) => (if $e == 1 { true } else { false })
}

impl Ui {
    pub fn new(native_api: *mut CPdUI) -> Ui {
        Ui {
            api: native_api,
            fmt_buffer: String::with_capacity(2048),
        }
    }

    pub fn set_title(&self, title: &str) {
        unsafe {
            let t = CFixedString::from_str(title).as_ptr();
            ((*self.api).set_title)((*self.api).private_data, t);
        }
    }

    #[inline]
    pub fn get_window_size(&self) -> (f32, f32) {
        unsafe {
            let t = ((*self.api).get_window_size)();
            (t.x, t.y)
        }
    }

    #[inline]
    pub fn get_window_pos(&self) -> PDVec2 {
        unsafe { ((*self.api).get_window_pos)() }
    }

    #[inline]
    pub fn get_text_line_height_with_spacing(&self) -> f32 {
        unsafe { ((*self.api).get_text_line_height_with_spacing)() as f32 }
    }

    #[inline]
    pub fn get_cursor_pos(&self) -> (f32, f32) {
        unsafe {
            let t = ((*self.api).get_cursor_pos)();
            (t.x, t.y)
        }
    }

    #[inline]
    pub fn set_cursor_pos(&self, pos: (f32, f32)) {
        unsafe {
            ((*self.api).set_cursor_pos)(PDVec2{x: pos.0, y: pos.1});
        }
    }

    #[inline]
    pub fn get_cursor_screen_pos(&self) -> (f32, f32) {
        unsafe {
            let t = ((*self.api).get_cursor_screen_pos)();
            (t.x, t.y)
        }
    }

    #[inline]
    pub fn set_cursor_screen_pos(&self, pos: (f32, f32)) {
        unsafe {
            ((*self.api).set_cursor_screen_pos)(PDVec2{x: pos.0, y: pos.1});
        }
    }

    #[inline]
    pub fn fill_rect(&self, x: f32, y: f32, width: f32, height: f32, col: Color) {
        unsafe {
            ((*self.api).fill_rect)(PDRect { x: x, y: y, width: width, height: height }, col.color);
        }
    }

    #[inline]
    pub fn set_scroll_here(&self, center: f32) {
        unsafe { ((*self.api).set_scroll_here)(center) }
    }

    pub fn begin_child(&self, id: &str, pos: Option<PDVec2>, border: bool, flags: u32) {
        unsafe {
            let t = CFixedString::from_str(id).as_ptr();
            match pos {
                Some(p) => ((*self.api).begin_child)(t, p, border as i32, flags as i32),
                None => {
                    ((*self.api).begin_child)(t,
                                              PDVec2 { x: 0.0, y: 0.0 },
                                              border as i32,
                                              flags as i32)
                }
            }
        }
    }

    #[inline]
    pub fn end_child(&self) {
        unsafe { ((*self.api).end_child)() }
    }

    #[inline]
    pub fn get_scroll_y(&self) -> f32 {
        unsafe { ((*self.api).get_scroll_y)() as f32 }
    }

    #[inline]
    pub fn get_scroll_max_y(&self) -> f32 {
        unsafe { ((*self.api).get_scroll_max_y)() as f32 }
    }

    #[inline]
    pub fn set_scroll_y(&self, pos: f32) {
        unsafe { ((*self.api).set_scroll_y)(pos) }
    }

    #[inline]
    pub fn set_scroll_from_pos_y(&self, pos_y: f32, center_ratio: f32) {
        unsafe { ((*self.api).set_scroll_from_pos_y)(pos_y, center_ratio) }
    }

    #[inline]
    pub fn set_keyboard_focus_here(&self, offset: i32) {
        unsafe { ((*self.api).set_keyboard_focus_here)(offset) }
    }

    // TODO: push/pop font

    #[inline]
	pub fn push_style_color(&self, index: usize, col: Color) {
        unsafe { ((*self.api).push_style_color)(index as u32, col.color) }
    }

    #[inline]
	pub fn pop_style_color(&self, index: usize) {
        unsafe { ((*self.api).pop_style_color)(index as i32) }
    }

    #[inline]
	pub fn push_style_var(&self, index: usize, val: f32) {
        unsafe { ((*self.api).push_style_var)(index as u32, val) }
    }

    #[inline]
	pub fn push_style_var_vec(&self, index: usize, val: PDVec2) {
        unsafe { ((*self.api).push_style_var_vec)(index as u32, val) }
    }

    #[inline]
    pub fn get_font_size(&self) -> f32 {
        unsafe { ((*self.api).get_font_size)() }
    }

    #[inline]
    pub fn calc_text_size(&self, text: &str, offset: usize) -> (f32, f32) {
        unsafe {
            if offset == 0 {
                let t = ((*self.api).calc_text_size)(text.as_ptr(), ptr::null(), 0, -1.0);
                (t.x, t.y)
            } else {
                let slice = &text[offset..];
                let t = ((*self.api).calc_text_size)(text.as_ptr(), slice.as_ptr(), 0, -1.0);
                (t.x, t.y)
            }
        }
    }

    // Text

    pub fn text(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text)(t);
        }
    }

    pub fn text_fmt(&mut self, args: fmt::Arguments) {
        unsafe {
            self.fmt_buffer.clear();
            write!(&mut self.fmt_buffer, "{}", args).unwrap();
            let t = CFixedString::from_str(&self.fmt_buffer).as_ptr();
            ((*self.api).text)(t);
        }
    }

    pub fn text_colored(&self, col: Color, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text_colored)(col.color, t);
        }
    }

    pub fn text_disabled(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text_disabled)(t);
        }
    }

    pub fn text_wrapped(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).text_wrapped)(t);
        }
    }

	pub fn columns(&self, count: isize, id: Option<&str>, border: bool) {
	    unsafe {
            match id {
                Some(p) => {
                    let t = CFixedString::from_str(p).as_ptr();
                    ((*self.api).columns)(count as i32, t, border as i32)
                }
                None => ((*self.api).columns)(count as i32, ptr::null(), border as i32),
            }
        }
    }

    #[inline]
    pub fn next_column(&self) {
        unsafe { ((*self.api).next_column)() }
    }

    pub fn button(&self, title: &str, pos: Option<PDVec2>) -> bool {
        unsafe {
            let t = CFixedString::from_str(title).as_ptr();
            match pos {
                Some(p) => ((*self.api).button)(t, p) != 0,
                None => ((*self.api).button)(t, PDVec2 { x: 0.0, y: 0.0 }) != 0,
            }
        }
    }
    pub fn begin_popup(&self, text: &str) -> bool {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            int_to_bool!(((*self.api).begin_popup)(t))
        }
    }

    pub fn begin_menu(&self, text: &str, enabled: bool) -> bool {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            let s = if enabled { 1 } else { 0 };
            int_to_bool!(((*self.api).begin_menu)(t, s))
        }
    }

    pub fn open_popup(&self, text: &str) {
        unsafe {
            let t = CFixedString::from_str(text).as_ptr();
            ((*self.api).open_popup)(t);
        }
    }

	pub fn menu_item(&self, text: &str, selected: bool, enabled: bool) -> bool {
        unsafe {
            let name = CFixedString::from_str(text).as_ptr();
            let s = if selected { 1 } else { 0 };
            let e = if enabled { 1 } else { 0 };
            int_to_bool!(((*self.api).menu_item)(name, ptr::null(), s, e))
        }
    }

    pub fn end_menu(&self) {
        unsafe { ((*self.api).end_menu)() }
    }

    pub fn end_popup(&self) {
        unsafe { ((*self.api).end_popup)() }
    }

	pub fn sc_input_text(&self, title: &str, width: usize, height: usize) -> Scintilla {
	    unsafe {
            let name = CFixedString::from_str(title);
	        Scintilla::new(((*self.api).sc_input_text)(name.as_ptr(),
	                        width as f32,
	                        height as f32, None))
        }
    }

    ///
    /// Keyboard support
    ///

	pub fn is_key_down(&self, key: Key) -> bool {
        unsafe { int_to_bool!(((*self.api).is_key_down)(key as i32)) }
    }

	pub fn is_key_pressed(&self, key: Key, repeat: bool) -> bool {
        unsafe { int_to_bool!(((*self.api).is_key_pressed)(key as i32, true_is_1!(repeat))) }
    }

	pub fn is_key_released(&self, key: Key) -> bool {
        unsafe { int_to_bool!(((*self.api).is_key_released)(key as i32)) }
    }

    ///
    /// Rendering primitives
    ///

    pub fn fill_convex_poly(&self, vertices: &[Vec2], col: Color, anti_aliased: bool) {
	    unsafe {
            ((*self.api).fill_convex_poly)(
                vertices.as_ptr() as *const c_void,
                vertices.len() as u32,
                col.color,
                true_is_1!(anti_aliased))
        }
    }

    pub fn fill_circle(&self, pos: &Vec2, radius: f32, col: Color, segment_count: usize, anti_aliased: bool) {
	    unsafe {
            ((*self.api).fill_circle)(
                PDVec2 { x: pos.x, y: pos.y },
                radius,
                col.color,
                segment_count as u32,
                true_is_1!(anti_aliased))
        }
    }
}

<|endoftext|>


<commit_before>use std::io::{ Write, Result as IoResult };

use exec::{Step, Message};
use eval::Expr;
use data::DataMode;
use session::ValueID;

type StateId = u32;
type CounterId = u32;

#[derive(Clone, Debug)]
pub struct Nfa {
    states: Vec<State>,
    initial: StateId,
    success: StateId,
}

impl Nfa {
    pub fn new() -> Nfa {
        let mut nfa = Nfa { states: vec![], initial: 0, success: 0 };
        nfa.initial = nfa.add_state();
        nfa.success = nfa.add_state();
        nfa
    }

    pub fn add_state(&mut self) -> StateId {
        let id = self.states.len() as StateId;
        self.states.push(State::new());
        id
    }

    pub fn add_transition(&mut self, from: StateId, to: StateId, action: Action) {
        self.states[from as usize].transitions.push(Transition { target: to, action: action});
    }

    pub fn to_graphviz(&self, f: &mut Write) -> IoResult<()> {
        try!(writeln!(f, "digraph G {{"));
        for (id, state) in self.states.iter().enumerate() {
            for transition in &state.transitions {
                try!(writeln!(f, "{} -> {} [ label=\"{:?}\" ];", id, transition.target, transition.action));
            }
        }
        try!(writeln!(f, "}}"));
        Ok(())
    }
}

#[derive(Clone, Debug)]
pub struct State {
    transitions: Vec<Transition>,
}

impl State {
    fn new() -> State {
        State { transitions: vec![] }
    }
}

#[derive(Clone, Debug)]
pub struct Transition {
    target: StateId,
    action: Action,
}

#[derive(Clone, Debug)]
pub enum Action {
    Epsilon,
    Lower(Message),
    UpperBegin(Message),
    UpperEnd(Message),

    RepeatDnInit(CounterId, Expr), // Down-evaluate count, initialize counter to zero
    RepeatDnBack(CounterId), // Increment counter, guard on counter < count
    RepeatDnExit(CounterId), // Guard on counter == count

    RepeatUpInit(CounterId), // initialize counter to zero
    RepeatUpBack(CounterId), // increment counter
    RepeatUpExit(CounterId, Expr), // Guard on up-evaluate count

    // Down-evaluate outer variables, pop first inner variables down, set counter to zero
    ForInit(CounterId, u32, Vec<(ValueID, Expr, DataMode)>),
    // guard on counter < size, push next outer variables up, pop next inner variables down
    ForBack(CounterId, u32, Vec<(ValueID, Expr, DataMode)>),
    // guard on counter == size, Up-evaluate outer variables
    ForExit(CounterId, u32, Vec<(ValueID, Expr, DataMode)>),
}

pub fn from_step_tree(s: &Step) -> Nfa {
    let mut nfa = Nfa::new();
    let initial = nfa.initial;
    let success = nfa.success;
    from_step_tree_inner(s, &mut nfa, initial, success);

    fn from_step_tree_inner(s: &Step, nfa: &mut Nfa, from: StateId, to: StateId) {
        match *s {
            Step::Nop => nfa.add_transition(from, to, Action::Epsilon),
            Step::Token(ref message) => {
                let m: Message = message.clone();
                nfa.add_transition(from, to, Action::Lower(m))
            }
            Step::TokenTop(ref message, box ref body) => {
                let is = nfa.add_state();
                let ie = nfa.add_state();
                nfa.add_transition(from, is, Action::UpperBegin(message.clone()));
                from_step_tree_inner(body, nfa, is, ie);
                nfa.add_transition(ie, to, Action::UpperEnd(message.clone()));
            }
            Step::Seq(ref steps) => {
                if let Some((last, rest)) = steps.split_last() {
                    let mut conn = from;
                    for c in rest.iter() {
                        let next = nfa.add_state();
                        from_step_tree_inner(c, nfa, conn, next);
                        conn = next;
                    }
                    from_step_tree_inner(last, nfa, conn, to);
                } else {
                    nfa.add_transition(from, to, Action::Epsilon);
                }
            }
            Step::Repeat(ref count, box ref inner, up) => {
                let start = nfa.add_state();
                let end = nfa.add_state();
                let counter = start;

                if up {
                    nfa.add_transition(from, start, Action::RepeatUpInit(counter));
                    nfa.add_transition(end, start, Action::RepeatUpBack(counter));
                    nfa.add_transition(end, to, Action::RepeatUpExit(counter, count.clone()));
                } else {
                    nfa.add_transition(from, start, Action::RepeatDnInit(counter, count.clone()));
                    nfa.add_transition(end, start, Action::RepeatDnBack(counter));
                    nfa.add_transition(end, to, Action::RepeatDnExit(counter));
                }
                from_step_tree_inner(inner, nfa, start, end);
            }
            Step::Foreach(width, ref vars, box ref inner) => {
                let start = nfa.add_state();
                let end = nfa.add_state();
                let counter = start;

                nfa.add_transition(from, start, Action::ForInit(counter, width, vars.clone()));
                nfa.add_transition(end, start, Action::ForBack(counter, width, vars.clone()));
                nfa.add_transition(end, to, Action::ForExit(counter, width, vars.clone()));

                from_step_tree_inner(inner, nfa, start, end);
            }
        }
    }

    nfa
}
<commit_msg>nfa: color token nodes in dot graph<commit_after>use std::io::{ Write, Result as IoResult };

use exec::{Step, Message};
use eval::Expr;
use data::DataMode;
use session::ValueID;

type StateId = u32;
type CounterId = u32;

#[derive(Clone, Debug)]
pub struct Nfa {
    states: Vec<State>,
    initial: StateId,
    success: StateId,
}

impl Nfa {
    pub fn new() -> Nfa {
        let mut nfa = Nfa { states: vec![], initial: 0, success: 0 };
        nfa.initial = nfa.add_state();
        nfa.success = nfa.add_state();
        nfa
    }

    pub fn add_state(&mut self) -> StateId {
        let id = self.states.len() as StateId;
        self.states.push(State::new());
        id
    }

    pub fn add_transition(&mut self, from: StateId, to: StateId, action: Action) {
        self.states[from as usize].transitions.push(Transition { target: to, action: action});
    }

    pub fn to_graphviz(&self, f: &mut Write) -> IoResult<()> {
        try!(writeln!(f, "digraph G {{"));
        for (id, state) in self.states.iter().enumerate() {
            for transition in &state.transitions {
                let colorstr = match &transition.action {
                    &Action::Epsilon => r#"fontcolor="gray""#,
                    &Action::Lower(..) => r#"fontcolor="blue""#,
                    &Action::UpperBegin(..) | &Action::UpperEnd(..) => r#"fontcolor="green""#,
                    _ => ""
                };
                try!(writeln!(f, "{} -> {} [ label=\"{:?}\" {}];", id, transition.target, transition.action, colorstr));
            }
        }
        try!(writeln!(f, "}}"));
        Ok(())
    }
}

#[derive(Clone, Debug)]
pub struct State {
    transitions: Vec<Transition>,
}

impl State {
    fn new() -> State {
        State { transitions: vec![] }
    }
}

#[derive(Clone, Debug)]
pub struct Transition {
    target: StateId,
    action: Action,
}

#[derive(Clone, Debug)]
pub enum Action {
    Epsilon,
    Lower(Message),
    UpperBegin(Message),
    UpperEnd(Message),

    RepeatDnInit(CounterId, Expr), // Down-evaluate count, initialize counter to zero
    RepeatDnBack(CounterId), // Increment counter, guard on counter < count
    RepeatDnExit(CounterId), // Guard on counter == count

    RepeatUpInit(CounterId), // initialize counter to zero
    RepeatUpBack(CounterId), // increment counter
    RepeatUpExit(CounterId, Expr), // Guard on up-evaluate count

    // Down-evaluate outer variables, pop first inner variables down, set counter to zero
    ForInit(CounterId, u32, Vec<(ValueID, Expr, DataMode)>),
    // guard on counter < size, push next outer variables up, pop next inner variables down
    ForBack(CounterId, u32, Vec<(ValueID, Expr, DataMode)>),
    // guard on counter == size, Up-evaluate outer variables
    ForExit(CounterId, u32, Vec<(ValueID, Expr, DataMode)>),
}

pub fn from_step_tree(s: &Step) -> Nfa {
    let mut nfa = Nfa::new();
    let initial = nfa.initial;
    let success = nfa.success;
    from_step_tree_inner(s, &mut nfa, initial, success);

    fn from_step_tree_inner(s: &Step, nfa: &mut Nfa, from: StateId, to: StateId) {
        match *s {
            Step::Nop => nfa.add_transition(from, to, Action::Epsilon),
            Step::Token(ref message) => {
                let m: Message = message.clone();
                nfa.add_transition(from, to, Action::Lower(m))
            }
            Step::TokenTop(ref message, box ref body) => {
                let is = nfa.add_state();
                let ie = nfa.add_state();
                nfa.add_transition(from, is, Action::UpperBegin(message.clone()));
                from_step_tree_inner(body, nfa, is, ie);
                nfa.add_transition(ie, to, Action::UpperEnd(message.clone()));
            }
            Step::Seq(ref steps) => {
                if let Some((last, rest)) = steps.split_last() {
                    let mut conn = from;
                    for c in rest.iter() {
                        let next = nfa.add_state();
                        from_step_tree_inner(c, nfa, conn, next);
                        conn = next;
                    }
                    from_step_tree_inner(last, nfa, conn, to);
                } else {
                    nfa.add_transition(from, to, Action::Epsilon);
                }
            }
            Step::Repeat(ref count, box ref inner, up) => {
                let start = nfa.add_state();
                let end = nfa.add_state();
                let counter = start;

                if up {
                    nfa.add_transition(from, start, Action::RepeatUpInit(counter));
                    nfa.add_transition(end, start, Action::RepeatUpBack(counter));
                    nfa.add_transition(end, to, Action::RepeatUpExit(counter, count.clone()));
                } else {
                    nfa.add_transition(from, start, Action::RepeatDnInit(counter, count.clone()));
                    nfa.add_transition(end, start, Action::RepeatDnBack(counter));
                    nfa.add_transition(end, to, Action::RepeatDnExit(counter));
                }
                from_step_tree_inner(inner, nfa, start, end);
            }
            Step::Foreach(width, ref vars, box ref inner) => {
                let start = nfa.add_state();
                let end = nfa.add_state();
                let counter = start;

                nfa.add_transition(from, start, Action::ForInit(counter, width, vars.clone()));
                nfa.add_transition(end, start, Action::ForBack(counter, width, vars.clone()));
                nfa.add_transition(end, to, Action::ForExit(counter, width, vars.clone()));

                from_step_tree_inner(inner, nfa, start, end);
            }
        }
    }

    nfa
}
<|endoftext|>


<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A one-dimensional length, tagged with its units.

use num_traits;

// Euclid has its own Zero and One traits instead of of using the num_traits equivalents.
// Unfortunately, num_traits::Zero requires Add, which opens a bag of sad things:
//  - Most importantly, for Point2D to implement Zero it would need to implement Add<Self> which we
//    don't want (we allow "Point + Vector" and "Vector + Vector" semantics and purposefully disallow
//    "Point + Point".
//  - Some operations that require, say, One and Div (for example Scale::inv) currently return a
//    type parameterized over T::Output which is ambiguous with num_traits::One because it inherits
//    Mul which also has an Output associated type. To fix it need to complicate type signatures
//    by using <T as Trait>::Output which makes the code and documentation harder to read.
//
// On the other hand, euclid::num::Zero/One are automatically implemented for all types that
// implement their num_traits counterpart. Euclid users never need to explicitly use
// euclid::num::Zero/One and can/should only manipulate the num_traits equivalents without risk
// of compatibility issues with euclid.

pub trait Zero {
    fn zero() -> Self;
}

impl<T: num_traits::Zero> Zero for T {
    fn zero() -> T {
        num_traits::Zero::zero()
    }
}

pub trait One {
    fn one() -> Self;
}

impl<T: num_traits::One> One for T {
    fn one() -> T {
        num_traits::One::one()
    }
}

/// Defines the nearest integer value to the original value.
pub trait Round: Copy {
    /// Rounds to the nearest integer value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn round(self) -> Self;
}
/// Defines the biggest integer equal or lower than the original value.
pub trait Floor: Copy {
    /// Rounds to the biggest integer equal or lower than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn floor(self) -> Self;
}
/// Defines the smallest integer equal or greater than the original value.
pub trait Ceil: Copy {
    /// Rounds to the smallest integer equal or greater than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn ceil(self) -> Self;
}

macro_rules! num_int {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                self
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                self
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                self
            }
        }
    };
}
macro_rules! num_float {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                num_traits::Float::round(self)
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                num_traits::Float::floor(self)
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                num_traits::Float::ceil(self)
            }
        }
    };
}

num_int!(i16);
num_int!(u16);
num_int!(i32);
num_int!(u32);
num_int!(i64);
num_int!(u64);
num_int!(isize);
num_int!(usize);
num_float!(f32);
num_float!(f64);
<commit_msg>Don't implement Floor, Ceil and Round on integer types.<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A one-dimensional length, tagged with its units.

use num_traits;

// Euclid has its own Zero and One traits instead of of using the num_traits equivalents.
// Unfortunately, num_traits::Zero requires Add, which opens a bag of sad things:
//  - Most importantly, for Point2D to implement Zero it would need to implement Add<Self> which we
//    don't want (we allow "Point + Vector" and "Vector + Vector" semantics and purposefully disallow
//    "Point + Point".
//  - Some operations that require, say, One and Div (for example Scale::inv) currently return a
//    type parameterized over T::Output which is ambiguous with num_traits::One because it inherits
//    Mul which also has an Output associated type. To fix it need to complicate type signatures
//    by using <T as Trait>::Output which makes the code and documentation harder to read.
//
// On the other hand, euclid::num::Zero/One are automatically implemented for all types that
// implement their num_traits counterpart. Euclid users never need to explicitly use
// euclid::num::Zero/One and can/should only manipulate the num_traits equivalents without risk
// of compatibility issues with euclid.

pub trait Zero {
    fn zero() -> Self;
}

impl<T: num_traits::Zero> Zero for T {
    fn zero() -> T {
        num_traits::Zero::zero()
    }
}

pub trait One {
    fn one() -> Self;
}

impl<T: num_traits::One> One for T {
    fn one() -> T {
        num_traits::One::one()
    }
}

/// Defines the nearest integer value to the original value.
pub trait Round: Copy {
    /// Rounds to the nearest integer value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn round(self) -> Self;
}
/// Defines the biggest integer equal or lower than the original value.
pub trait Floor: Copy {
    /// Rounds to the biggest integer equal or lower than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn floor(self) -> Self;
}
/// Defines the smallest integer equal or greater than the original value.
pub trait Ceil: Copy {
    /// Rounds to the smallest integer equal or greater than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn ceil(self) -> Self;
}

macro_rules! num_float {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                num_traits::Float::round(self)
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                num_traits::Float::floor(self)
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                num_traits::Float::ceil(self)
            }
        }
    };
}
num_float!(f32);
num_float!(f64);
<|endoftext|>


<commit_before>
// Copyright 2020 John Hanley.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// The software is provided "AS IS", without warranty of any kind, express or
// implied, including but not limited to the warranties of merchantability,
// fitness for a particular purpose and noninfringement. In no event shall
// the authors or copyright holders be liable for any claim, damages or
// other liability, whether in an action of contract, tort or otherwise,
// arising from, out of or in connection with the software or the use or
// other dealings in the software.

use std::env;
use std::time::Instant;

const MAX_ITER: i32 = 255;  // Rust lacks adequate support for default args.

fn mandelbrot_set(xc: f64, yc: f64, sz: f64, px_resolution: i32) {
    let step = (2.0 * sz) / (px_resolution as f64 - 1.0);

    for j in 0 .. px_resolution {
        for i in 0 .. px_resolution {
            let x0 = xc - sz + step * i as f64;
            let y0 = yc - sz + step * j as f64;
            plot(_cycles_to_escape(x0, y0));
        }
    }
}

fn _cycles_to_escape(x0: f64, y0: f64) -> i32 {
    let mut x = 0.0;
    let mut y = 0.0;
    let mut i = 0;
    while x * x + y * y <= 4.0 && i < MAX_ITER {
        let (a, b) = (x * x - y * y + x0, 2.0 * x * y + y0);
        x = a;
        y = b;  // rust 1.47 lacks tuple unpack, aka destructuring assignment
        i += 1;
    }
    return i;
}

fn plot(grey_value: i32) {
    let v = &grey_value.to_string();
    let mut rgb :String = v.to_owned();
    rgb.push_str(" ");
    rgb.push_str(v);
    rgb.push_str(" ");
    rgb.push_str(v);
    rgb.push_str("\n");
    print!("{}", v);
}
pub fn plot_slow(grey_value: i32) {
    // If _cycles_to_escape costs 220 msec, this costs 840 msec,
    // while the verbose plot costs 730 msec. The to_string
    // alone costs 270 msec. Appending a SPACE costs 140 msec.
    let v = &grey_value;
    println!("{} {} {}", &v, &v, &v);
}

fn getenv(key: &str) -> i32 {
    let s: String;
    match env::var(key) {
        Ok(v) => s = v,
        Err(_) => s = "400".to_string()
    }
    return stoi(s);
}

fn stoi(s: String) -> i32 {
    return s.parse::<i32>().unwrap();
}

fn stof(s: String) -> f64 {
    return s.parse::<f64>().unwrap();
}

pub fn main() {
    let px_resolution = getenv("MSET_PX_RESOLUTION");
    let args: Vec<String> = env::args().into_iter().collect();
    let xc = stof(args[1].to_string());
    let yc = stof(args[2].to_string());
    let sz = stof(args[3].to_string());
    println!("P3\n{} {}\n255", px_resolution, px_resolution);
    let t0 = Instant::now();

    mandelbrot_set(xc, yc, sz, px_resolution);

    let elapsed = t0.elapsed().as_millis() as f64;
    eprintln!("{} seconds", elapsed / 1e3);
}
<commit_msg>Pushing a space char is cheaper<commit_after>
// Copyright 2020 John Hanley.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// The software is provided "AS IS", without warranty of any kind, express or
// implied, including but not limited to the warranties of merchantability,
// fitness for a particular purpose and noninfringement. In no event shall
// the authors or copyright holders be liable for any claim, damages or
// other liability, whether in an action of contract, tort or otherwise,
// arising from, out of or in connection with the software or the use or
// other dealings in the software.

use std::env;
use std::time::Instant;

const MAX_ITER: i32 = 255;  // Rust lacks adequate support for default args.

fn mandelbrot_set(xc: f64, yc: f64, sz: f64, px_resolution: i32) {
    let step = (2.0 * sz) / (px_resolution as f64 - 1.0);

    for j in 0 .. px_resolution {
        for i in 0 .. px_resolution {
            let x0 = xc - sz + step * i as f64;
            let y0 = yc - sz + step * j as f64;
            plot(_cycles_to_escape(x0, y0));
        }
    }
    // io::stdout().flush().ok().expect("flush failed");
}

fn _cycles_to_escape(x0: f64, y0: f64) -> i32 {
    let mut x = 0.0;
    let mut y = 0.0;
    let mut i = 0;
    while x * x + y * y <= 4.0 && i < MAX_ITER {
        let (a, b) = (x * x - y * y + x0, 2.0 * x * y + y0);
        x = a;
        y = b;  // rust 1.47 lacks tuple unpack, aka destructuring assignment
        i += 1;
    }
    return i;
}

fn plot(grey_value: i32) {
    // If _cycles_to_escape costs 220 msec, this costs 840 msec.
    let v = &grey_value;
    println!("{} {} {}", &v, &v, &v);
}
pub fn plot_verbose(grey_value: i32) {
    let v :&str = &grey_value.to_string();
    let mut rgb = String::with_capacity(14);
    rgb.push_str(&v);
    rgb.push(' ');
    rgb.push_str(&v);
    rgb.push(' ');
    rgb.push_str(&v);
    println!("{}", &rgb);
}

fn getenv(key: &str) -> i32 {
    let s: String;
    match env::var(key) {
        Ok(v) => s = v,
        Err(_) => s = "400".to_string()
    }
    return stoi(s);
}

fn stoi(s: String) -> i32 {
    return s.parse::<i32>().unwrap();
}

fn stof(s: String) -> f64 {
    return s.parse::<f64>().unwrap();
}

pub fn main() {
    let px_resolution = getenv("MSET_PX_RESOLUTION");
    let args: Vec<String> = env::args().into_iter().collect();
    let xc = stof(args[1].to_string());
    let yc = stof(args[2].to_string());
    let sz = stof(args[3].to_string());
    println!("P3\n{} {}\n255", px_resolution, px_resolution);
    let t0 = Instant::now();

    mandelbrot_set(xc, yc, sz, px_resolution);

    let elapsed = t0.elapsed().as_millis() as f64;
    eprintln!("{} seconds", elapsed / 1e3);
}
<|endoftext|>


<commit_before>use crate::compiler_plugin;
use crate::gen::code_writer::CodeWriter;

pub(crate) fn gen_mod_rs(mods: &[String]) -> compiler_plugin::GenResult {
    let v = CodeWriter::with_no_error(|w| {
        w.comment(&format!("{}generated", "@"));
        w.write_line("");
        for m in mods {
            w.write_line(&format!("pub mod {};", m));
        }
    });
    compiler_plugin::GenResult {
        name: "mod.rs".to_owned(),
        content: v.into_bytes(),
    }
}
<commit_msg>Fix generated mod.rs to pass cargo fmt -- --check<commit_after>use crate::compiler_plugin;
use crate::gen::code_writer::CodeWriter;

pub(crate) fn gen_mod_rs(mods: &[String]) -> compiler_plugin::GenResult {
    let v = CodeWriter::with_no_error(|w| {
        w.comment(&format!("{}generated", "@"));
        w.write_line("");
        let mut mods: Vec<&String> = mods.into_iter().collect();
        mods.sort();
        for m in mods {
            w.write_line(&format!("pub mod {};", m));
        }
    });
    compiler_plugin::GenResult {
        name: "mod.rs".to_owned(),
        content: v.into_bytes(),
    }
}
<|endoftext|>


<commit_before>//! Decoding and Encoding of PNG Images
//!
//! PNG (Portable Network Graphics) is an image format that supports lossless compression.
//!
//! # Related Links
//! * <http://www.w3.org/TR/PNG/> - The PNG Specification
//!

extern crate png;

use self::png::HasParameters;

use std::io::{self, Read, Write};

use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};

/// PNG Reader
///
/// This reader will try to read the png one row at a time,
/// however for interlaced png files this is not posible and
/// these are therefore readed at once.
pub struct PNGReader<R: Read> {
    reader: png::Reader<R>,
    buffer: Vec<u8>,
    index: usize,
}

impl<R: Read> PNGReader<R> {
    fn new(mut reader: png::Reader<R>) -> ImageResult<PNGReader<R>> {
        let len = reader.output_buffer_size();
        // Since interlaced images do not come in
        // scanline order it is almost impossible to
        // read them in a streaming fashion, however
        // this shouldn't be a too big of a problem
        // as most interlaced images should fit in memory.
        let buffer = if reader.info().interlaced {
            let mut buffer = vec![0; len];
            reader.next_frame(&mut buffer)?;
            buffer
        } else {
            Vec::new()
        };

        Ok(PNGReader {
            reader,
            buffer,
            index: 0,
        })
    }
}

impl<R: Read> Read for PNGReader<R> {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        // io::Write::write for slice cannot fail
        let readed = buf.write(&self.buffer[self.index..]).unwrap();

        let mut bytes = readed;
        self.index += readed;

        while self.index + 1 >= self.buffer.len() {
            match self.reader.next_row()? {
                Some(row) => {
                    // Faster to copy directly to external buffer
                    let readed  = buf.write(row).unwrap();
                    bytes += readed;

                    self.buffer = (&row[readed..]).to_owned();
                    self.index = 0;
                }
                None => return Ok(bytes)
            }
        }

        Ok(bytes)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut bytes = self.buffer.len();
        buf.extend_from_slice(&self.buffer);
        self.buffer = Vec::new();
        self.index = 0;

        while let Some(row) = self.reader.next_row()? {
            buf.extend_from_slice(row);
            bytes += row.len();
        }

        Ok(bytes)
    }
}

/// PNG decoder
pub struct PNGDecoder<R: Read> {
    colortype: ColorType,
    reader: png::Reader<R>,
}

impl<R: Read> PNGDecoder<R> {
    /// Creates a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
        let decoder = png::Decoder::new(r);
        let (_, mut reader) = decoder.read_info()?;
        let colortype = reader.output_color_type().into();

        Ok(PNGDecoder { colortype, reader })
    }
}

impl<R: Read> ImageDecoder for PNGDecoder<R> {
    type Reader = PNGReader<R>;

    fn dimensions(&self) -> (u64, u64) {
        let (w, h) = self.reader.info().size();
        (w as u64, h as u64)
    }

    fn colortype(&self) -> ColorType {
        self.colortype
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        PNGReader::new(self.reader)
    }

    fn read_image(mut self) -> ImageResult<Vec<u8>> {
        // This should be slightly faster than the default implementation
        let mut data = vec![0; self.reader.output_buffer_size()];
        self.reader.next_frame(&mut data)?;
        Ok(data)
    }

    fn scanline_bytes(&self) -> u64 {
        let width = self.reader.info().width;
        self.reader.output_line_size(width) as u64
    }
}

/// PNG encoder
pub struct PNGEncoder<W: Write> {
    w: W,
}

impl<W: Write> PNGEncoder<W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: W) -> PNGEncoder<W> {
        PNGEncoder { w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
        let (ct, bits) = color.into();
        let mut encoder = png::Encoder::new(self.w, width, height);
        encoder.set(ct).set(bits);
        let mut writer = try!(encoder.write_header());
        writer.write_image_data(data).map_err(|e| e.into())
    }
}

impl From<(png::ColorType, png::BitDepth)> for ColorType {
    fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
        use self::png::ColorType::*;
        let bits = bits as u8;
        match ct {
            Grayscale => ColorType::Gray(bits),
            RGB => ColorType::RGB(bits),
            Indexed => ColorType::Palette(bits),
            GrayscaleAlpha => ColorType::GrayA(bits),
            RGBA => ColorType::RGBA(bits),
        }
    }
}

impl From<ColorType> for (png::ColorType, png::BitDepth) {
    fn from(ct: ColorType) -> (png::ColorType, png::BitDepth) {
        use self::png::ColorType::*;
        let (ct, bits) = match ct {
            ColorType::Gray(bits) => (Grayscale, bits),
            ColorType::RGB(bits) => (RGB, bits),
            ColorType::Palette(bits) => (Indexed, bits),
            ColorType::GrayA(bits) => (GrayscaleAlpha, bits),
            ColorType::RGBA(bits) => (RGBA, bits),
            ColorType::BGRA(bits) => (RGBA, bits),
            ColorType::BGR(bits) => (RGB, bits),
        };
        (ct, png::BitDepth::from_u8(bits).unwrap())
    }
}

impl From<png::DecodingError> for ImageError {
    fn from(err: png::DecodingError) -> ImageError {
        use self::png::DecodingError::*;
        match err {
            IoError(err) => ImageError::IoError(err),
            Format(desc) => ImageError::FormatError(desc.into_owned()),
            InvalidSignature => ImageError::FormatError("invalid signature".into()),
            CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
            Other(desc) => ImageError::FormatError(desc.into_owned()),
            CorruptFlateStream => {
                ImageError::FormatError("compressed data stream corrupted".into())
            }
        }
    }
}
<commit_msg>Update png limits<commit_after>//! Decoding and Encoding of PNG Images
//!
//! PNG (Portable Network Graphics) is an image format that supports lossless compression.
//!
//! # Related Links
//! * <http://www.w3.org/TR/PNG/> - The PNG Specification
//!

extern crate png;

use self::png::HasParameters;

use std;
use std::io::{self, Read, Write};

use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};

/// PNG Reader
///
/// This reader will try to read the png one row at a time,
/// however for interlaced png files this is not posible and
/// these are therefore readed at once.
pub struct PNGReader<R: Read> {
    reader: png::Reader<R>,
    buffer: Vec<u8>,
    index: usize,
}

impl<R: Read> PNGReader<R> {
    fn new(mut reader: png::Reader<R>) -> ImageResult<PNGReader<R>> {
        let len = reader.output_buffer_size();
        // Since interlaced images do not come in
        // scanline order it is almost impossible to
        // read them in a streaming fashion, however
        // this shouldn't be a too big of a problem
        // as most interlaced images should fit in memory.
        let buffer = if reader.info().interlaced {
            let mut buffer = vec![0; len];
            reader.next_frame(&mut buffer)?;
            buffer
        } else {
            Vec::new()
        };

        Ok(PNGReader {
            reader,
            buffer,
            index: 0,
        })
    }
}

impl<R: Read> Read for PNGReader<R> {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        // io::Write::write for slice cannot fail
        let readed = buf.write(&self.buffer[self.index..]).unwrap();

        let mut bytes = readed;
        self.index += readed;

        while self.index + 1 >= self.buffer.len() {
            match self.reader.next_row()? {
                Some(row) => {
                    // Faster to copy directly to external buffer
                    let readed  = buf.write(row).unwrap();
                    bytes += readed;

                    self.buffer = (&row[readed..]).to_owned();
                    self.index = 0;
                }
                None => return Ok(bytes)
            }
        }

        Ok(bytes)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut bytes = self.buffer.len();
        buf.extend_from_slice(&self.buffer);
        self.buffer = Vec::new();
        self.index = 0;

        while let Some(row) = self.reader.next_row()? {
            buf.extend_from_slice(row);
            bytes += row.len();
        }

        Ok(bytes)
    }
}

/// PNG decoder
pub struct PNGDecoder<R: Read> {
    colortype: ColorType,
    reader: png::Reader<R>,
}

impl<R: Read> PNGDecoder<R> {
    /// Creates a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
        let limits = png::Limits {
            pixels: std::u64::MAX,
        };
        let decoder = png::Decoder::new_with_limits(r, limits);
        let (_, mut reader) = decoder.read_info()?;
        let colortype = reader.output_color_type().into();

        Ok(PNGDecoder { colortype, reader })
    }
}

impl<R: Read> ImageDecoder for PNGDecoder<R> {
    type Reader = PNGReader<R>;

    fn dimensions(&self) -> (u64, u64) {
        let (w, h) = self.reader.info().size();
        (w as u64, h as u64)
    }

    fn colortype(&self) -> ColorType {
        self.colortype
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        PNGReader::new(self.reader)
    }

    fn read_image(mut self) -> ImageResult<Vec<u8>> {
        // This should be slightly faster than the default implementation
        let mut data = vec![0; self.reader.output_buffer_size()];
        self.reader.next_frame(&mut data)?;
        Ok(data)
    }

    fn scanline_bytes(&self) -> u64 {
        let width = self.reader.info().width;
        self.reader.output_line_size(width) as u64
    }
}

/// PNG encoder
pub struct PNGEncoder<W: Write> {
    w: W,
}

impl<W: Write> PNGEncoder<W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: W) -> PNGEncoder<W> {
        PNGEncoder { w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
        let (ct, bits) = color.into();
        let mut encoder = png::Encoder::new(self.w, width, height);
        encoder.set(ct).set(bits);
        let mut writer = try!(encoder.write_header());
        writer.write_image_data(data).map_err(|e| e.into())
    }
}

impl From<(png::ColorType, png::BitDepth)> for ColorType {
    fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
        use self::png::ColorType::*;
        let bits = bits as u8;
        match ct {
            Grayscale => ColorType::Gray(bits),
            RGB => ColorType::RGB(bits),
            Indexed => ColorType::Palette(bits),
            GrayscaleAlpha => ColorType::GrayA(bits),
            RGBA => ColorType::RGBA(bits),
        }
    }
}

impl From<ColorType> for (png::ColorType, png::BitDepth) {
    fn from(ct: ColorType) -> (png::ColorType, png::BitDepth) {
        use self::png::ColorType::*;
        let (ct, bits) = match ct {
            ColorType::Gray(bits) => (Grayscale, bits),
            ColorType::RGB(bits) => (RGB, bits),
            ColorType::Palette(bits) => (Indexed, bits),
            ColorType::GrayA(bits) => (GrayscaleAlpha, bits),
            ColorType::RGBA(bits) => (RGBA, bits),
            ColorType::BGRA(bits) => (RGBA, bits),
            ColorType::BGR(bits) => (RGB, bits),
        };
        (ct, png::BitDepth::from_u8(bits).unwrap())
    }
}

impl From<png::DecodingError> for ImageError {
    fn from(err: png::DecodingError) -> ImageError {
        use self::png::DecodingError::*;
        match err {
            IoError(err) => ImageError::IoError(err),
            Format(desc) => ImageError::FormatError(desc.into_owned()),
            InvalidSignature => ImageError::FormatError("invalid signature".into()),
            CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
            Other(desc) => ImageError::FormatError(desc.into_owned()),
            CorruptFlateStream => {
                ImageError::FormatError("compressed data stream corrupted".into())
            }
        }
    }
}
<|endoftext|>


<commit_before>use core::slice;

/// Internal enum mapping type
///
/// This trait is internally used by `#[derive(EnumMap)]`. Despite it being
/// a public trait, it's not intended to be public. `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
/// Users aren't expected to use this trait directly, but rather to use
/// `EnumMap<K, V>` which uses this internally.
///
/// This trait is also implemented by `bool`, `u8` and `Option` type. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Internal<V>: Sized {
    /// Representation of an enum map for type `V`, usually an array.
    type Array;
    #[doc(hidden)]
    fn slice(array: &Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(array: &mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(value: usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(f: F) -> Self::Array;
}

impl<T> Internal<T> for bool {
    type Array = [T; 2];
    fn slice(array: &[T; 2]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 2]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 2] {
        [f(false), f(true)]
    }
}

impl<T> Internal<T> for u8 {
    type Array = [T; 256];
    fn slice(array: &[T; 256]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 256]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        value as u8
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 256] {
        array![|i| f(i); 256]
    }
}

// C representation is needed to ensure Rust compiler won't reorder those 2 fields.
#[repr(C)]
pub struct OptionInternal<T, U> {
    none: T,
    some: U,
}

impl<T, U: Internal<T>> Internal<T> for Option<U> {
    type Array = OptionInternal<T, U::Array>;
    fn slice(array: &Self::Array) -> &[T] {
        unsafe {
            slice::from_raw_parts(
                array as *const _ as *const T,
                1 + U::slice(&array.some).len(),
            )
        }
    }
    fn slice_mut(array: &mut Self::Array) -> &mut [T] {
        unsafe {
            slice::from_raw_parts_mut(array as *mut _ as *mut T, 1 + U::slice(&array.some).len())
        }
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => None,
            v => Some(U::from_usize(v - 1)),
        }
    }
    fn to_usize(self) -> usize {
        match self {
            None => 0,
            Some(x) => x.to_usize() + 1,
        }
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> Self::Array {
        OptionInternal {
            none: f(None),
            some: U::from_function(|x| f(Some(x))),
        }
    }
}
<commit_msg>Perform a cast from usize to u8 in u8 enum map<commit_after>use core::slice;

/// Internal enum mapping type
///
/// This trait is internally used by `#[derive(EnumMap)]`. Despite it being
/// a public trait, it's not intended to be public. `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
/// Users aren't expected to use this trait directly, but rather to use
/// `EnumMap<K, V>` which uses this internally.
///
/// This trait is also implemented by `bool`, `u8` and `Option` type. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Internal<V>: Sized {
    /// Representation of an enum map for type `V`, usually an array.
    type Array;
    #[doc(hidden)]
    fn slice(array: &Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(array: &mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(value: usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(f: F) -> Self::Array;
}

impl<T> Internal<T> for bool {
    type Array = [T; 2];
    fn slice(array: &[T; 2]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 2]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 2] {
        [f(false), f(true)]
    }
}

impl<T> Internal<T> for u8 {
    type Array = [T; 256];
    fn slice(array: &[T; 256]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 256]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        value as u8
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 256] {
        array![|i| f(i as u8); 256]
    }
}

// C representation is needed to ensure Rust compiler won't reorder those 2 fields.
#[repr(C)]
pub struct OptionInternal<T, U> {
    none: T,
    some: U,
}

impl<T, U: Internal<T>> Internal<T> for Option<U> {
    type Array = OptionInternal<T, U::Array>;
    fn slice(array: &Self::Array) -> &[T] {
        unsafe {
            slice::from_raw_parts(
                array as *const _ as *const T,
                1 + U::slice(&array.some).len(),
            )
        }
    }
    fn slice_mut(array: &mut Self::Array) -> &mut [T] {
        unsafe {
            slice::from_raw_parts_mut(array as *mut _ as *mut T, 1 + U::slice(&array.some).len())
        }
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => None,
            v => Some(U::from_usize(v - 1)),
        }
    }
    fn to_usize(self) -> usize {
        match self {
            None => 0,
            Some(x) => x.to_usize() + 1,
        }
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> Self::Array {
        OptionInternal {
            none: f(None),
            some: U::from_function(|x| f(Some(x))),
        }
    }
}
<|endoftext|>