<commit_before>//! Random number generation

export Rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        move s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:Copy>(values: &[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:Copy>(values: &[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: Copy>(v : &[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:Copy>(v: &[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        util::unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:Copy>(v: &[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        move r
    }

    /// Shuffle a vec
    fn shuffle<T:Copy>(values: &[T]) -> ~[T] {
        let mut m = vec::from_slice(values);
        self.shuffle_mut(m);
        move m
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(values: &[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    c: *rctx,
    drop { rustrt::rand_free(self.c); }
}

fn RandRes(c: *rctx) -> RandRes {
    RandRes {
        c: c
    }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn Rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::Rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::Rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::Rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::Rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::Rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::Rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::Rng();
        let x: Option<int> = r.choose_option([]);
        assert x.is_none();
        assert r.choose_option([1, 1, 1]) == Some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::Rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::Rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        let v: Option<int> = r.choose_weighted_option([]);
        assert v.is_none();
    }

    #[test]
    fn weighted_vec() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Install new pub/priv/export rules as defaults, old rules accessible under #[legacy_exports];<commit_after>//! Random number generation

export Rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    #[legacy_exports];
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        move s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:Copy>(values: &[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:Copy>(values: &[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: Copy>(v : &[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:Copy>(v: &[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        util::unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:Copy>(v: &[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        move r
    }

    /// Shuffle a vec
    fn shuffle<T:Copy>(values: &[T]) -> ~[T] {
        let mut m = vec::from_slice(values);
        self.shuffle_mut(m);
        move m
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(values: &[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    c: *rctx,
    drop { rustrt::rand_free(self.c); }
}

fn RandRes(c: *rctx) -> RandRes {
    RandRes {
        c: c
    }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn Rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {
    #[legacy_exports];

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::Rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::Rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::Rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::Rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::Rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::Rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::Rng();
        let x: Option<int> = r.choose_option([]);
        assert x.is_none();
        assert r.choose_option([1, 1, 1]) == Some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::Rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::Rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        let v: Option<int> = r.choose_weighted_option([]);
        assert v.is_none();
    }

    #[test]
    fn weighted_vec() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use hir::ModuleSource;
use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt};
use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode};
use ra_text_edit::TextEdit;

use crate::{
    db::RootDatabase, FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange,
    SourceFileEdit, TextRange,
};

use super::find_all_refs;

pub(crate) fn rename(
    db: &RootDatabase,
    position: FilePosition,
    new_name: &str,
) -> Option<RangeInfo<SourceChange>> {
    let parse = db.parse(position.file_id);
    if let Some((ast_name, ast_module)) =
        find_name_and_module_at_offset(parse.tree().syntax(), position)
    {
        let range = ast_name.syntax().text_range();
        rename_mod(db, &ast_name, &ast_module, position, new_name)
            .map(|info| RangeInfo::new(range, info))
    } else {
        rename_reference(db, position, new_name)
    }
}

fn find_name_and_module_at_offset(
    syntax: &SyntaxNode,
    position: FilePosition,
) -> Option<(ast::Name, ast::Module)> {
    let ast_name = find_node_at_offset::<ast::Name>(syntax, position.offset)?;
    let ast_module = ast::Module::cast(ast_name.syntax().parent()?)?;
    Some((ast_name, ast_module))
}

fn source_edit_from_file_id_range(
    file_id: FileId,
    range: TextRange,
    new_name: &str,
) -> SourceFileEdit {
    SourceFileEdit { file_id, edit: TextEdit::replace(range, new_name.into()) }
}

fn rename_mod(
    db: &RootDatabase,
    ast_name: &ast::Name,
    ast_module: &ast::Module,
    position: FilePosition,
    new_name: &str,
) -> Option<SourceChange> {
    let mut source_file_edits = Vec::new();
    let mut file_system_edits = Vec::new();
    let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() };
    if let Some(module) = hir::Module::from_declaration(db, module_src) {
        let src = module.definition_source(db);
        let file_id = src.file_id.original_file(db);
        match src.value {
            ModuleSource::SourceFile(..) => {
                let mod_path: RelativePathBuf = db.file_relative_path(file_id);
                // mod is defined in path/to/dir/mod.rs
                let dst_path = if mod_path.file_stem() == Some("mod") {
                    mod_path
                        .parent()
                        .and_then(|p| p.parent())
                        .or_else(|| Some(RelativePath::new("")))
                        .map(|p| p.join(new_name).join("mod.rs"))
                } else {
                    Some(mod_path.with_file_name(new_name).with_extension("rs"))
                };
                if let Some(path) = dst_path {
                    let move_file = FileSystemEdit::MoveFile {
                        src: file_id,
                        dst_source_root: db.file_source_root(position.file_id),
                        dst_path: path,
                    };
                    file_system_edits.push(move_file);
                }
            }
            ModuleSource::Module(..) => {}
        }
    }

    let edit = SourceFileEdit {
        file_id: position.file_id,
        edit: TextEdit::replace(ast_name.syntax().text_range(), new_name.into()),
    };
    source_file_edits.push(edit);

    Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits))
}

fn rename_reference(
    db: &RootDatabase,
    position: FilePosition,
    new_name: &str,
) -> Option<RangeInfo<SourceChange>> {
    let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?;

    let edit = refs
        .into_iter()
        .map(|range| source_edit_from_file_id_range(range.file_id, range.range, new_name))
        .collect::<Vec<_>>();

    if edit.is_empty() {
        return None;
    }

    Some(RangeInfo::new(range, SourceChange::source_file_edits("rename", edit)))
}

#[cfg(test)]
mod tests {
    use insta::assert_debug_snapshot;
    use ra_text_edit::TextEditBuilder;
    use test_utils::assert_eq_text;

    use crate::{
        mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId,
    };

    #[test]
    fn test_rename_for_local() {
        test_rename(
            r#"
    fn main() {
        let mut i = 1;
        let j = 1;
        i = i<|> + j;

        {
            i = 0;
        }

        i = 5;
    }"#,
            "k",
            r#"
    fn main() {
        let mut k = 1;
        let j = 1;
        k = k + j;

        {
            k = 0;
        }

        k = 5;
    }"#,
        );
    }

    #[test]
    fn test_rename_for_param_inside() {
        test_rename(
            r#"
    fn foo(i : u32) -> u32 {
        i<|>
    }"#,
            "j",
            r#"
    fn foo(j : u32) -> u32 {
        j
    }"#,
        );
    }

    #[test]
    fn test_rename_refs_for_fn_param() {
        test_rename(
            r#"
    fn foo(i<|> : u32) -> u32 {
        i
    }"#,
            "new_name",
            r#"
    fn foo(new_name : u32) -> u32 {
        new_name
    }"#,
        );
    }

    #[test]
    fn test_rename_for_mut_param() {
        test_rename(
            r#"
    fn foo(mut i<|> : u32) -> u32 {
        i
    }"#,
            "new_name",
            r#"
    fn foo(mut new_name : u32) -> u32 {
        new_name
    }"#,
        );
    }

    #[test]
    fn test_rename_mod() {
        let (analysis, position) = analysis_and_position(
            "
            //- /lib.rs
            mod bar;

            //- /bar.rs
            mod foo<|>;

            //- /bar/foo.rs
            // emtpy
            ",
        );
        let new_name = "foo2";
        let source_change = analysis.rename(position, new_name).unwrap();
        assert_debug_snapshot!(&source_change,
@r###"
        Some(
            RangeInfo {
                range: [4; 7),
                info: SourceChange {
                    label: "rename",
                    source_file_edits: [
                        SourceFileEdit {
                            file_id: FileId(
                                2,
                            ),
                            edit: TextEdit {
                                atoms: [
                                    AtomTextEdit {
                                        delete: [4; 7),
                                        insert: "foo2",
                                    },
                                ],
                            },
                        },
                    ],
                    file_system_edits: [
                        MoveFile {
                            src: FileId(
                                3,
                            ),
                            dst_source_root: SourceRootId(
                                0,
                            ),
                            dst_path: "bar/foo2.rs",
                        },
                    ],
                    cursor_position: None,
                },
            },
        )
        "###);
    }

    #[test]
    fn test_rename_mod_in_dir() {
        let (analysis, position) = analysis_and_position(
            "
            //- /lib.rs
            mod fo<|>o;
            //- /foo/mod.rs
            // emtpy
            ",
        );
        let new_name = "foo2";
        let source_change = analysis.rename(position, new_name).unwrap();
        assert_debug_snapshot!(&source_change,
        @r###"
        Some(
            RangeInfo {
                range: [4; 7),
                info: SourceChange {
                    label: "rename",
                    source_file_edits: [
                        SourceFileEdit {
                            file_id: FileId(
                                1,
                            ),
                            edit: TextEdit {
                                atoms: [
                                    AtomTextEdit {
                                        delete: [4; 7),
                                        insert: "foo2",
                                    },
                                ],
                            },
                        },
                    ],
                    file_system_edits: [
                        MoveFile {
                            src: FileId(
                                2,
                            ),
                            dst_source_root: SourceRootId(
                                0,
                            ),
                            dst_path: "foo2/mod.rs",
                        },
                    ],
                    cursor_position: None,
                },
            },
        )
        "###
               );
    }

    fn test_rename(text: &str, new_name: &str, expected: &str) {
        let (analysis, position) = single_file_with_position(text);
        let source_change = analysis.rename(position, new_name).unwrap();
        let mut text_edit_builder = TextEditBuilder::default();
        let mut file_id: Option<FileId> = None;
        if let Some(change) = source_change {
            for edit in change.info.source_file_edits {
                file_id = Some(edit.file_id);
                for atom in edit.edit.as_atoms() {
                    text_edit_builder.replace(atom.delete, atom.insert.clone());
                }
            }
        }
        let result =
            text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()).unwrap());
        assert_eq_text!(expected, &*result);
    }
}
<commit_msg>Test rename for various identifiers<commit_after>//! FIXME: write short doc here

use hir::ModuleSource;
use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt};
use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode};
use ra_text_edit::TextEdit;

use crate::{
    db::RootDatabase, FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange,
    SourceFileEdit, TextRange,
};

use super::find_all_refs;

pub(crate) fn rename(
    db: &RootDatabase,
    position: FilePosition,
    new_name: &str,
) -> Option<RangeInfo<SourceChange>> {
    let parse = db.parse(position.file_id);
    if let Some((ast_name, ast_module)) =
        find_name_and_module_at_offset(parse.tree().syntax(), position)
    {
        let range = ast_name.syntax().text_range();
        rename_mod(db, &ast_name, &ast_module, position, new_name)
            .map(|info| RangeInfo::new(range, info))
    } else {
        rename_reference(db, position, new_name)
    }
}

fn find_name_and_module_at_offset(
    syntax: &SyntaxNode,
    position: FilePosition,
) -> Option<(ast::Name, ast::Module)> {
    let ast_name = find_node_at_offset::<ast::Name>(syntax, position.offset)?;
    let ast_module = ast::Module::cast(ast_name.syntax().parent()?)?;
    Some((ast_name, ast_module))
}

fn source_edit_from_file_id_range(
    file_id: FileId,
    range: TextRange,
    new_name: &str,
) -> SourceFileEdit {
    SourceFileEdit { file_id, edit: TextEdit::replace(range, new_name.into()) }
}

fn rename_mod(
    db: &RootDatabase,
    ast_name: &ast::Name,
    ast_module: &ast::Module,
    position: FilePosition,
    new_name: &str,
) -> Option<SourceChange> {
    let mut source_file_edits = Vec::new();
    let mut file_system_edits = Vec::new();
    let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() };
    if let Some(module) = hir::Module::from_declaration(db, module_src) {
        let src = module.definition_source(db);
        let file_id = src.file_id.original_file(db);
        match src.value {
            ModuleSource::SourceFile(..) => {
                let mod_path: RelativePathBuf = db.file_relative_path(file_id);
                // mod is defined in path/to/dir/mod.rs
                let dst_path = if mod_path.file_stem() == Some("mod") {
                    mod_path
                        .parent()
                        .and_then(|p| p.parent())
                        .or_else(|| Some(RelativePath::new("")))
                        .map(|p| p.join(new_name).join("mod.rs"))
                } else {
                    Some(mod_path.with_file_name(new_name).with_extension("rs"))
                };
                if let Some(path) = dst_path {
                    let move_file = FileSystemEdit::MoveFile {
                        src: file_id,
                        dst_source_root: db.file_source_root(position.file_id),
                        dst_path: path,
                    };
                    file_system_edits.push(move_file);
                }
            }
            ModuleSource::Module(..) => {}
        }
    }

    let edit = SourceFileEdit {
        file_id: position.file_id,
        edit: TextEdit::replace(ast_name.syntax().text_range(), new_name.into()),
    };
    source_file_edits.push(edit);

    Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits))
}

fn rename_reference(
    db: &RootDatabase,
    position: FilePosition,
    new_name: &str,
) -> Option<RangeInfo<SourceChange>> {
    let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?;

    let edit = refs
        .into_iter()
        .map(|range| source_edit_from_file_id_range(range.file_id, range.range, new_name))
        .collect::<Vec<_>>();

    if edit.is_empty() {
        return None;
    }

    Some(RangeInfo::new(range, SourceChange::source_file_edits("rename", edit)))
}

#[cfg(test)]
mod tests {
    use insta::assert_debug_snapshot;
    use ra_text_edit::TextEditBuilder;
    use test_utils::assert_eq_text;

    use crate::{
        mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId,
    };

    #[test]
    fn test_rename_to_underscore() {
        test_rename(
            r#"
    fn main() {
        let i<|> = 1;
    }"#,
            "_",
            r#"
    fn main() {
        let _ = 1;
    }"#,
        );
    }

    #[test]
    fn test_rename_to_raw_identifier() {
        test_rename(
            r#"
    fn main() {
        let i<|> = 1;
    }"#,
            "r#fn",
            r#"
    fn main() {
        let r#fn = 1;
    }"#,
        );
    }

    #[test]
    fn test_rename_to_invalid_identifier() {
        let (analysis, position) = single_file_with_position(
            "
    fn main() {
        let i<|> = 1;
    }",
        );
        let new_name = "invalid!";
        let source_change = analysis.rename(position, new_name).unwrap();
        assert!(source_change.is_none());
    }

    #[test]
    fn test_rename_for_local() {
        test_rename(
            r#"
    fn main() {
        let mut i = 1;
        let j = 1;
        i = i<|> + j;

        {
            i = 0;
        }

        i = 5;
    }"#,
            "k",
            r#"
    fn main() {
        let mut k = 1;
        let j = 1;
        k = k + j;

        {
            k = 0;
        }

        k = 5;
    }"#,
        );
    }

    #[test]
    fn test_rename_for_param_inside() {
        test_rename(
            r#"
    fn foo(i : u32) -> u32 {
        i<|>
    }"#,
            "j",
            r#"
    fn foo(j : u32) -> u32 {
        j
    }"#,
        );
    }

    #[test]
    fn test_rename_refs_for_fn_param() {
        test_rename(
            r#"
    fn foo(i<|> : u32) -> u32 {
        i
    }"#,
            "new_name",
            r#"
    fn foo(new_name : u32) -> u32 {
        new_name
    }"#,
        );
    }

    #[test]
    fn test_rename_for_mut_param() {
        test_rename(
            r#"
    fn foo(mut i<|> : u32) -> u32 {
        i
    }"#,
            "new_name",
            r#"
    fn foo(mut new_name : u32) -> u32 {
        new_name
    }"#,
        );
    }

    #[test]
    fn test_rename_mod() {
        let (analysis, position) = analysis_and_position(
            "
            //- /lib.rs
            mod bar;

            //- /bar.rs
            mod foo<|>;

            //- /bar/foo.rs
            // emtpy
            ",
        );
        let new_name = "foo2";
        let source_change = analysis.rename(position, new_name).unwrap();
        assert_debug_snapshot!(&source_change,
@r###"
        Some(
            RangeInfo {
                range: [4; 7),
                info: SourceChange {
                    label: "rename",
                    source_file_edits: [
                        SourceFileEdit {
                            file_id: FileId(
                                2,
                            ),
                            edit: TextEdit {
                                atoms: [
                                    AtomTextEdit {
                                        delete: [4; 7),
                                        insert: "foo2",
                                    },
                                ],
                            },
                        },
                    ],
                    file_system_edits: [
                        MoveFile {
                            src: FileId(
                                3,
                            ),
                            dst_source_root: SourceRootId(
                                0,
                            ),
                            dst_path: "bar/foo2.rs",
                        },
                    ],
                    cursor_position: None,
                },
            },
        )
        "###);
    }

    #[test]
    fn test_rename_mod_in_dir() {
        let (analysis, position) = analysis_and_position(
            "
            //- /lib.rs
            mod fo<|>o;
            //- /foo/mod.rs
            // emtpy
            ",
        );
        let new_name = "foo2";
        let source_change = analysis.rename(position, new_name).unwrap();
        assert_debug_snapshot!(&source_change,
        @r###"
        Some(
            RangeInfo {
                range: [4; 7),
                info: SourceChange {
                    label: "rename",
                    source_file_edits: [
                        SourceFileEdit {
                            file_id: FileId(
                                1,
                            ),
                            edit: TextEdit {
                                atoms: [
                                    AtomTextEdit {
                                        delete: [4; 7),
                                        insert: "foo2",
                                    },
                                ],
                            },
                        },
                    ],
                    file_system_edits: [
                        MoveFile {
                            src: FileId(
                                2,
                            ),
                            dst_source_root: SourceRootId(
                                0,
                            ),
                            dst_path: "foo2/mod.rs",
                        },
                    ],
                    cursor_position: None,
                },
            },
        )
        "###
               );
    }

    fn test_rename(text: &str, new_name: &str, expected: &str) {
        let (analysis, position) = single_file_with_position(text);
        let source_change = analysis.rename(position, new_name).unwrap();
        let mut text_edit_builder = TextEditBuilder::default();
        let mut file_id: Option<FileId> = None;
        if let Some(change) = source_change {
            for edit in change.info.source_file_edits {
                file_id = Some(edit.file_id);
                for atom in edit.edit.as_atoms() {
                    text_edit_builder.replace(atom.delete, atom.insert.clone());
                }
            }
        }
        let result =
            text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()).unwrap());
        assert_eq_text!(expected, &*result);
    }
}
<|endoftext|>


<commit_before><commit_msg>hash indexer<commit_after>use bifrost::rpc::RPCError;
use client::AsyncClient;
use futures::prelude::*;
use ram::cell::{Cell, CellHeader, ReadError, WriteError};
use ram::schema::{Field, Schema};
use ram::types::Id;
use ram::types::*;
use std::sync::Arc;

const HASH_SCHEMA: &'static str = "HASH_INDEX_SCHEMA";

lazy_static! {
    pub static ref HASH_INDEX_SCHEMA_ID: u32 = key_hash(HASH_SCHEMA) as u32;
}

pub struct HashIndexer {
    neb_client: Arc<AsyncClient>,
}

impl HashIndexer {
    pub fn add_index(
        &self,
        cell_id: Id,
        index_id: Id,
    ) -> impl Future<Item = Result<CellHeader, WriteError>, Error = RPCError> {
        let cell = Cell::new_with_id(*HASH_INDEX_SCHEMA_ID, &index_id, Value::Id(cell_id));
        self.neb_client.write_cell(cell)
    }

    pub fn remove_index(
        &self,
        index_id: Id,
    ) -> impl Future<Item = Result<(), WriteError>, Error = RPCError> {
        self.neb_client.remove_cell(index_id)
    }

    pub fn query(
        &self,
        index_id: Id,
    ) -> impl Future<Item = Result<Id, ReadError>, Error = RPCError> {
        let res = self.neb_client.read_cell(index_id);
        res.then(|res| res.map(|read| read.map(|cell| *cell.data.Id().unwrap())))
    }
}

fn hash_index_schema() -> Schema {
    Schema {
        id: *HASH_INDEX_SCHEMA_ID,
        name: HASH_SCHEMA.to_string(),
        key_field: None,
        str_key_field: None,
        fields: Field::new("*", type_id_of(Type::Id), false, false, None, vec![]),
        is_dynamic: false,
    }
}
<|endoftext|>


<commit_before>
use {
    Field,
    Borrowed,
    Line,
    Matrix2d,
    Value,
    View,
};
use vecmath::{
    identity,
};
use internal::{
    CanTransform,
    HasTransform,
};

/// A line context.
pub struct LineContext<'a> {
    /// Base/original transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current line.
    pub line: Field<'a, Line>,
}

impl<'a> HasTransform<'a, Matrix2d> for LineContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, LineContext<'a>, Matrix2d> for LineContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            line: Borrowed(self.line.get()),
        }
    }
}

impl<'a> View<'a> for LineContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
        }
    }
}

<commit_msg>Arranged `use` statements in `LineContext` alphabetically<commit_after>
use {
    Borrowed,
    Field,
    Line,
    Matrix2d,
    Value,
    View,
};
use vecmath::{
    identity,
};
use internal::{
    CanTransform,
    HasTransform,
};

/// A line context.
pub struct LineContext<'a> {
    /// Base/original transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current line.
    pub line: Field<'a, Line>,
}

impl<'a> HasTransform<'a, Matrix2d> for LineContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, LineContext<'a>, Matrix2d> for LineContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            line: Borrowed(self.line.get()),
        }
    }
}

impl<'a> View<'a> for LineContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
        }
    }
}

<|endoftext|>


<commit_before>//! Draw textures using a projection matrix.

use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

use view::shaders;

/// Draw textures using a projection matrix.
pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

#[allow(missing_docs)]
pub fn new<'a, 'b:'a>(gl: &'a GLContext, near: f32, far: f32) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, format!(r#"
      #version 330 core

      uniform mat4 projection_matrix;
      uniform vec3 eye_position;
      uniform float time_ms;

      uniform samplerBuffer positions;
      uniform samplerBuffer normals;

      in vec2 texture_position;
      in vec3 vertex_position;
      in vec3 model_translation;
      in int polygon_id;
      in uint tex_id;

      out vec2 vs_texture_position;
      out vec3 vs_normal;
      out float vs_tex_id;

      // include cnoise
      {}

      // include adjust_depth_precision
      {}

      mat3 between(vec3 v1, vec3 v2) {{
        vec3 v = cross(v1, v2);
        float s = length(v);
        float c = dot(v1, v2);
        mat3 skew =
          mat3(
            vec3(0, v.z, -v.y),
            vec3(-v.z, 0, v.x),
            vec3(v.y, -v.x, 0)
          );
        return mat3(1) + skew + skew*skew*(1-c)/(s*s);
      }}

      vec3 vec3Fetch(samplerBuffer vs, int float_idx) {{
        vec3 r;
        r.x = texelFetch(vs, float_idx + 0).r;
        r.y = texelFetch(vs, float_idx + 1).r;
        r.z = texelFetch(vs, float_idx + 2).r;
        return r;
      }}

      // compute a model-space shear to transform (0,1,0) to a desired vector.
      mat4 shearTo(vec3 desired) {{
        mat4 r = mat4(1);

        float d = dot(desired, vec3(0, 1, 0));
        // tweak the dot product to be in a valid range
        float new_d = exp(d - 1.0);
        // the common shear factor
        float k = 0;
        if (d < 0.99) {{
          k = sqrt((1.0-new_d*new_d)/(new_d*new_d*(1.0-d*d)));
        }}

        r[1].x = desired.x * k;
        r[1].y = 1.0;
        r[1].z = desired.z * k;

        return r;
      }}

      void main() {{
        vs_texture_position = texture_position;
        vs_tex_id = float(tex_id);

        // Put the grass tuft in the middle of the underlying terrain polygon.
        int position_id = polygon_id * 3 * 3;
        mat3 vertices =
          mat3(
            vec3Fetch(positions, position_id),
            vec3Fetch(positions, position_id + 3),
            vec3Fetch(positions, position_id + 6)
          );
        vec3 side_length =
          vec3(
            length(vertices[0] - vertices[1]),
            length(vertices[1] - vertices[2]),
            length(vertices[2] - vertices[0])
          );
        vec3 root = vertices * vec3(1.0/3.0);

        // Find the normal for the grass by barycentrically interpolating the
        // vertex normals to the root.
        int normal_id = polygon_id * 3 * 3;
        mat3 vertex_normals =
          mat3(
            vec3Fetch(normals, normal_id),
            vec3Fetch(normals, normal_id + 3),
            vec3Fetch(normals, normal_id + 6)
          );
        vec3 normal = vertex_normals * vec3(1.0/3.0);

        mat4 translation = mat4(1.0);
        translation[3].xyz = root;

        mat3 rotate_normal = between(vec3(0, 1, 0), normal);
        mat4 rotation = mat4(rotate_normal);

        mat4 shear = shearTo(inverse(rotate_normal) * vec3(0, 1, 0));

        mat4 noise_shear;
        {{
          vec3 billboard_seed = root / vec3(1 << 3, 1, 1 << 3);
          float azimuth = 3.14 * cnoise(billboard_seed + vec3(122, -1, 14.5) + vec3(0, time_ms / 2000, 0));
          float altitude = 3.14/2 - 3.14/4 * (cnoise(billboard_seed + vec3(-18.11, 101.1, 44.5) + vec3(0, time_ms / 2000, 0)) + 1) / 2.0;
          vec3 v =
            vec3(
              cos(altitude) * cos(azimuth),
              sin(altitude),
              cos(altitude) * sin(azimuth)
            );
          noise_shear = shearTo(v);
        }}

        mat4 scale = mat4(1.0);
        float max_side = max(max(side_length[0], side_length[1]), side_length[2]);
        float min_side = min(min(side_length[0], side_length[1]), side_length[2]);
        float side_scale = sqrt(min_side*max_side);
        scale[1].y = side_scale * 0.4;
        scale[0].x = side_scale * 1.0;
        scale[2].z = scale[0].x;

        mat4 model_translation_mat = mat4(1.0);
        model_translation_mat[3].xyz = model_translation;

        mat4 shear_mat = shear * noise_shear;
        mat4 to_world_mat = translation * rotation * model_translation_mat;

        vec4 sheared = shear_mat * scale * vec4(vertex_position, 1);
        vec4 sheared_axis = shear_mat * vec4(0, 1, 0, 0);
        sheared /= vec4(vec3(length(sheared_axis)), 1);

        gl_Position =
          adjust_depth_precision(
            projection_matrix *
            to_world_mat *
            sheared
          );

        vs_normal = normal;
      }}"#,
      shaders::adjust_depth_precision::as_string(near, far),
      shaders::noise::cnoise(),
    )),
    (gl::FRAGMENT_SHADER, format!("
      #version 330 core

      uniform struct Sun {{
        vec3 direction;
        vec3 intensity;
      }} sun;

      uniform vec3 ambient_light;
      uniform vec3 eye_position;

      uniform sampler2D texture_in;
      uniform float alpha_threshold;

      in vec2 vs_texture_position;
      in vec3 vs_normal;
      in float vs_tex_id;

      out vec4 frag_color;

      // depth fog
      {}

      // world fragment shading
      {}

      void main() {{
        int tex_id = int(round(vs_tex_id));
        int y = tex_id / 3;
        int x = tex_id % 3;
        vec2 tex_position =
          (vs_texture_position + y*vec2(0, 1) + x*vec2(1, 0)) / 3
          - vec2(0.0, 0.05);
        vec4 c = texture(texture_in, tex_position);
        if (c.a < alpha_threshold) {{
          discard;
        }}
        vec3 world_position = vec3(gl_FragCoord.xy * gl_FragCoord.w, gl_FragCoord.w);
        vec4 fog_color = vec4(sun.intensity, 1);
        frag_color =
          world_fragment(
            sun.direction,
            sun.intensity,
            normalize(world_position - eye_position),
            ambient_light,
            c,
            1.0 / 0.0,
            vs_normal,
            fog_color,
            gl_FragCoord.z / gl_FragCoord.w
          );
      }}",
      shaders::depth_fog::to_string(),
      shaders::world_fragment::to_string(),
    )),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<commit_msg>tweak grass scaling<commit_after>//! Draw textures using a projection matrix.

use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

use view::shaders;

/// Draw textures using a projection matrix.
pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

#[allow(missing_docs)]
pub fn new<'a, 'b:'a>(gl: &'a GLContext, near: f32, far: f32) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, format!(r#"
      #version 330 core

      uniform mat4 projection_matrix;
      uniform vec3 eye_position;
      uniform float time_ms;

      uniform samplerBuffer positions;
      uniform samplerBuffer normals;

      in vec2 texture_position;
      in vec3 vertex_position;
      in vec3 model_translation;
      in int polygon_id;
      in uint tex_id;

      out vec2 vs_texture_position;
      out vec3 vs_normal;
      out float vs_tex_id;

      // include cnoise
      {}

      // include adjust_depth_precision
      {}

      mat3 between(vec3 v1, vec3 v2) {{
        vec3 v = cross(v1, v2);
        float s = length(v);
        float c = dot(v1, v2);
        mat3 skew =
          mat3(
            vec3(0, v.z, -v.y),
            vec3(-v.z, 0, v.x),
            vec3(v.y, -v.x, 0)
          );
        return mat3(1) + skew + skew*skew*(1-c)/(s*s);
      }}

      vec3 vec3Fetch(samplerBuffer vs, int float_idx) {{
        vec3 r;
        r.x = texelFetch(vs, float_idx + 0).r;
        r.y = texelFetch(vs, float_idx + 1).r;
        r.z = texelFetch(vs, float_idx + 2).r;
        return r;
      }}

      // compute a model-space shear to transform (0,1,0) to a desired vector.
      mat4 shearTo(vec3 desired) {{
        mat4 r = mat4(1);

        float d = dot(desired, vec3(0, 1, 0));
        // tweak the dot product to be in a valid range
        float new_d = exp(d - 1.0);
        // the common shear factor
        float k = 0;
        if (d < 0.99) {{
          k = sqrt((1.0-new_d*new_d)/(new_d*new_d*(1.0-d*d)));
        }}

        r[1].x = desired.x * k;
        r[1].y = 1.0;
        r[1].z = desired.z * k;

        return r;
      }}

      void main() {{
        vs_texture_position = texture_position;
        vs_tex_id = float(tex_id);

        // Put the grass tuft in the middle of the underlying terrain polygon.
        int position_id = polygon_id * 3 * 3;
        mat3 vertices =
          mat3(
            vec3Fetch(positions, position_id),
            vec3Fetch(positions, position_id + 3),
            vec3Fetch(positions, position_id + 6)
          );
        vec3 side_length =
          vec3(
            length(vertices[0] - vertices[1]),
            length(vertices[1] - vertices[2]),
            length(vertices[2] - vertices[0])
          );
        vec3 root = vertices * vec3(1.0/3.0);

        // Find the normal for the grass by barycentrically interpolating the
        // vertex normals to the root.
        int normal_id = polygon_id * 3 * 3;
        mat3 vertex_normals =
          mat3(
            vec3Fetch(normals, normal_id),
            vec3Fetch(normals, normal_id + 3),
            vec3Fetch(normals, normal_id + 6)
          );
        vec3 normal = vertex_normals * vec3(1.0/3.0);

        mat4 translation = mat4(1.0);
        translation[3].xyz = root;

        mat3 rotate_normal = between(vec3(0, 1, 0), normal);
        mat4 rotation = mat4(rotate_normal);

        mat4 shear = shearTo(inverse(rotate_normal) * vec3(0, 1, 0));

        mat4 noise_shear;
        {{
          vec3 billboard_seed = root / vec3(1 << 3, 1, 1 << 3);
          float azimuth = 3.14 * cnoise(billboard_seed + vec3(122, -1, 14.5) + vec3(0, time_ms / 2000, 0));
          float altitude = 3.14/2 - 3.14/4 * (cnoise(billboard_seed + vec3(-18.11, 101.1, 44.5) + vec3(0, time_ms / 2000, 0)) + 1) / 2.0;
          vec3 v =
            vec3(
              cos(altitude) * cos(azimuth),
              sin(altitude),
              cos(altitude) * sin(azimuth)
            );
          noise_shear = shearTo(v);
        }}

        mat4 scale = mat4(1.0);
        float max_side = max(max(side_length[0], side_length[1]), side_length[2]);
        float min_side = min(min(side_length[0], side_length[1]), side_length[2]);
        float side_scale = (min_side + max_side) / 2.0;
        scale[1].y = side_scale * 0.4;
        scale[0].x = side_scale * 1.0;
        scale[2].z = scale[0].x;

        mat4 model_translation_mat = mat4(1.0);
        model_translation_mat[3].xyz = model_translation;

        mat4 shear_mat = shear * noise_shear;
        mat4 to_world_mat = translation * rotation * model_translation_mat;

        vec4 sheared = shear_mat * scale * vec4(vertex_position, 1);
        vec4 sheared_axis = shear_mat * vec4(0, 1, 0, 0);
        sheared /= vec4(vec3(length(sheared_axis)), 1);

        gl_Position =
          adjust_depth_precision(
            projection_matrix *
            to_world_mat *
            sheared
          );

        vs_normal = normal;
      }}"#,
      shaders::adjust_depth_precision::as_string(near, far),
      shaders::noise::cnoise(),
    )),
    (gl::FRAGMENT_SHADER, format!("
      #version 330 core

      uniform struct Sun {{
        vec3 direction;
        vec3 intensity;
      }} sun;

      uniform vec3 ambient_light;
      uniform vec3 eye_position;

      uniform sampler2D texture_in;
      uniform float alpha_threshold;

      in vec2 vs_texture_position;
      in vec3 vs_normal;
      in float vs_tex_id;

      out vec4 frag_color;

      // depth fog
      {}

      // world fragment shading
      {}

      void main() {{
        int tex_id = int(round(vs_tex_id));
        int y = tex_id / 3;
        int x = tex_id % 3;
        vec2 tex_position =
          (vs_texture_position + y*vec2(0, 1) + x*vec2(1, 0)) / 3
          - vec2(0.0, 0.05);
        vec4 c = texture(texture_in, tex_position);
        if (c.a < alpha_threshold) {{
          discard;
        }}
        vec3 world_position = vec3(gl_FragCoord.xy * gl_FragCoord.w, gl_FragCoord.w);
        vec4 fog_color = vec4(sun.intensity, 1);
        frag_color =
          world_fragment(
            sun.direction,
            sun.intensity,
            normalize(world_position - eye_position),
            ambient_light,
            c,
            1.0 / 0.0,
            vs_normal,
            fog_color,
            gl_FragCoord.z / gl_FragCoord.w
          );
      }}",
      shaders::depth_fog::to_string(),
      shaders::world_fragment::to_string(),
    )),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// aux-build:struct_variant_xc_aux.rs
extern mod struct_variant_xc_aux;

use struct_variant_xc_aux::Variant;

fn main() {
    let _ = Variant { arg: 1 };
}
<commit_msg>xfail-fast the new test for windows compatibility<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// xfail-fast - check-fast doesn't understand aux-build
// aux-build:struct_variant_xc_aux.rs
extern mod struct_variant_xc_aux;

use struct_variant_xc_aux::Variant;

fn main() {
    let _ = Variant { arg: 1 };
}
<|endoftext|>


<commit_before>use std::cmp::max;
use std::collections::VecDeque;
use std::mem::size_of;
use std::{ptr, slice};

use super::{Color, Event, Font, Image, Rect};

use system::error::{Error, Result, EINVAL};

pub struct Window {
    pub x: i32,
    pub y: i32,
    image: Image,
    title: String,
    title_image: Image,
    events: VecDeque<Event>,
}

impl Window {
    pub fn new(x: i32, y: i32, w: i32, h: i32, title: String) -> Window {
        let mut title_image = Image::new(title.chars().count() as i32 * 8, 16);
        title_image.as_roi().set(Color::rgba(0, 0, 0, 0));
        {
            let mut x = 0;
            for c in title.chars() {
                title_image.roi(&Rect::new(x, 0, 8, 16)).blend(&Font::render(c, Color::rgb(255, 255, 255)).as_roi());
                x += 8;
            }
        }

        Window {
            x: x,
            y: y,
            image: Image::new(w, h),
            title: title,
            title_image: title_image,
            events: VecDeque::new()
        }
    }

    pub fn width(&self) -> i32 {
        self.image.width()
    }

    pub fn height(&self) -> i32 {
        self.image.height()
    }

    pub fn rect(&self) -> Rect {
        Rect::new(self.x, self.y, self.width(), self.height())
    }

    pub fn title_rect(&self) -> Rect {
        if self.title.is_empty() {
            Rect::default()
        } else {
            Rect::new(self.x, self.y - 18, self.width(), 18)
        }
    }

    pub fn exit_contains(&self, x: i32, y: i32) -> bool {
        ! self.title.is_empty() && x >= max(self.x, self.x + self.width() - 10)  && y >= self.y - 18 && x < self.x + self.width() && y < self.y
    }

    pub fn draw_title(&mut self, image: &mut Image, rect: &Rect, focused: bool) {
        let title_rect = self.title_rect();
        let title_intersect = rect.intersection(&title_rect);
        if ! title_intersect.is_empty() {
            if focused {
                image.roi(&title_intersect).set(Color::rgb(192, 192, 192));
            } else {
                image.roi(&title_intersect).set(Color::rgb(64, 64, 64));
            }

            {
                let image_rect = Rect::new(title_rect.left() + 4, title_rect.top() + 1, self.title_image.width(), self.title_image.height());
                let image_intersect = rect.intersection(&image_rect);
                if ! image_intersect.is_empty() {
                    image.roi(&image_intersect).blend(&self.title_image.roi(&image_intersect.offset(-image_rect.left(), -image_rect.top())));
                }
            }

            let x = max(self.x + 2, self.x + self.width() - 10);
            if x + 10 <= self.x + self.width() {
                let mut font_image = Font::render('X', Color::rgb(255, 255, 255));
                let image_rect = Rect::new(x, title_rect.top() + 1, font_image.width(), font_image.height());
                let image_intersect = rect.intersection(&image_rect);
                if ! image_intersect.is_empty() {
                    image.roi(&image_intersect).blend(&font_image.roi(&image_intersect.offset(-image_rect.left(), -image_rect.top())));
                }
            }
        }
    }

    pub fn draw(&mut self, image: &mut Image, rect: &Rect) {
        let self_rect = self.rect();
        let intersect = self_rect.intersection(&rect);
        if ! intersect.is_empty() {
            image.roi(&intersect).blit(&self.image.roi(&intersect.offset(-self_rect.left(), -self_rect.top())));
        }
    }

    pub fn event(&mut self, event: Event) {
        self.events.push_back(event);
    }

    pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if buf.len() >= size_of::<Event>() {
            let mut i = 0;
            while i <= buf.len() - size_of::<Event>() {
                if let Some(event) = self.events.pop_front() {
                    unsafe { ptr::write(buf.as_mut_ptr().offset(i as isize) as *mut Event, event) };
                    i += size_of::<Event>();
                } else {
                    break;
                }
            }
            Ok(i)
        } else {
            Err(Error::new(EINVAL))
        }
    }

    pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let old = self.image.data_mut();
        let new = unsafe { slice::from_raw_parts(buf.as_ptr() as *const Color, buf.len() / size_of::<Color>()) };

        let mut i = 0;
        while i < old.len() && i < new.len() {
            old[i] = new[i];
            i += 1;
        }

        Ok(i * size_of::<Color>())
    }

    pub fn path(&self, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let path_str = format!("orbital:/{}/{}/{}/{}/{}", self.x, self.y, self.width(), self.height(), self.title);
        let path = path_str.as_bytes();
        while i < buf.len() && i < path.len() {
            buf[i] = path[i];
            i += 1;
        }
        Ok(i)
    }
}
<commit_msg>Correct rendering of title<commit_after>use std::cmp::max;
use std::collections::VecDeque;
use std::mem::size_of;
use std::{ptr, slice};

use super::{Color, Event, Font, Image, Rect};

use system::error::{Error, Result, EINVAL};

pub struct Window {
    pub x: i32,
    pub y: i32,
    image: Image,
    title: String,
    events: VecDeque<Event>,
}

impl Window {
    pub fn new(x: i32, y: i32, w: i32, h: i32, title: String) -> Window {
        Window {
            x: x,
            y: y,
            image: Image::new(w, h),
            title: title,
            events: VecDeque::new()
        }
    }

    pub fn width(&self) -> i32 {
        self.image.width()
    }

    pub fn height(&self) -> i32 {
        self.image.height()
    }

    pub fn rect(&self) -> Rect {
        Rect::new(self.x, self.y, self.width(), self.height())
    }

    pub fn title_rect(&self) -> Rect {
        if self.title.is_empty() {
            Rect::default()
        } else {
            Rect::new(self.x, self.y - 18, self.width(), 18)
        }
    }

    pub fn exit_contains(&self, x: i32, y: i32) -> bool {
        ! self.title.is_empty() && x >= max(self.x, self.x + self.width() - 10)  && y >= self.y - 18 && x < self.x + self.width() && y < self.y
    }

    pub fn draw_title(&mut self, image: &mut Image, rect: &Rect, focused: bool) {
        let title_rect = self.title_rect();
        let title_intersect = rect.intersection(&title_rect);
        if ! title_intersect.is_empty() {
            if focused {
                image.roi(&title_intersect).set(Color::rgb(192, 192, 192));
            } else {
                image.roi(&title_intersect).set(Color::rgb(64, 64, 64));
            }

            let mut x = self.x + 2;
            for c in self.title.chars() {
                if x < max(self.x + 2, self.x + self.width() - 10) {
                    let mut font_image = Font::render(c, Color::rgb(255, 255, 255));
                    let image_rect = Rect::new(x, title_rect.top() + 1, font_image.width(), font_image.height());
                    let image_intersect = rect.intersection(&image_rect);
                    if ! image_intersect.is_empty() {
                        image.roi(&image_intersect).blend(&font_image.roi(&image_intersect.offset(-image_rect.left(), -image_rect.top())));
                    }
                    x += 8;
                } else {
                    break;
                }
            }

            x = max(self.x + 2, self.x + self.width() - 10);
            if x + 10 <= self.x + self.width() {
                let mut font_image = Font::render('X', Color::rgb(255, 255, 255));
                let image_rect = Rect::new(x, title_rect.top() + 1, font_image.width(), font_image.height());
                let image_intersect = rect.intersection(&image_rect);
                if ! image_intersect.is_empty() {
                    image.roi(&image_intersect).blend(&font_image.roi(&image_intersect.offset(-image_rect.left(), -image_rect.top())));
                }
            }
        }
    }

    pub fn draw(&mut self, image: &mut Image, rect: &Rect) {
        let self_rect = self.rect();
        let intersect = self_rect.intersection(&rect);
        if ! intersect.is_empty() {
            image.roi(&intersect).blit(&self.image.roi(&intersect.offset(-self_rect.left(), -self_rect.top())));
        }
    }

    pub fn event(&mut self, event: Event) {
        self.events.push_back(event);
    }

    pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if buf.len() >= size_of::<Event>() {
            let mut i = 0;
            while i <= buf.len() - size_of::<Event>() {
                if let Some(event) = self.events.pop_front() {
                    unsafe { ptr::write(buf.as_mut_ptr().offset(i as isize) as *mut Event, event) };
                    i += size_of::<Event>();
                } else {
                    break;
                }
            }
            Ok(i)
        } else {
            Err(Error::new(EINVAL))
        }
    }

    pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let old = self.image.data_mut();
        let new = unsafe { slice::from_raw_parts(buf.as_ptr() as *const Color, buf.len() / size_of::<Color>()) };

        let mut i = 0;
        while i < old.len() && i < new.len() {
            old[i] = new[i];
            i += 1;
        }

        Ok(i * size_of::<Color>())
    }

    pub fn path(&self, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let path_str = format!("orbital:/{}/{}/{}/{}/{}", self.x, self.y, self.width(), self.height(), self.title);
        let path = path_str.as_bytes();
        while i < buf.len() && i < path.len() {
            buf[i] = path[i];
            i += 1;
        }
        Ok(i)
    }
}
<|endoftext|>


<commit_before>use std::iter::Peekable;

/// An iterator that performs a lookahead of 1, utilizing the existing Peakable Iterator
/// Can be stacked to perform an even greater lookahead
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: Peekable<I>,
}

impl<I, A> Iterator for Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>
{
    type Item = (A, Option<A>);

    #[inline]
    fn next(&mut self) -> Option<(A, Option<A>)> {
        match self.iter.next() {
            Some(item) => Some((item,
                match self.iter.peek() {
                    Some(ref item) => Some((*item).clone()),
                    None => None,
                }
            )),
            None => None,
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

pub trait PeekingExt {
    fn peeking(self) -> Peeking<Self, Self::Item>
        where Self: Sized+Iterator,
              Self::Item: Clone;
}

impl<A: Clone, I: Sized+Iterator<Item=A>> PeekingExt for I {
    fn peeking(self) -> Peeking<Self, A>
        where Self: Sized+Iterator
    {
         Peeking { iter: self.peekable() }
    }
}

/// An iterator to maintain state while iterating another iterator and allows filtering
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct FilteringScan<I, St, F> {
    iter: I,
    f: F,
    state: St,
}

impl<B, I, St, F> Iterator for FilteringScan<I, St, F> where
    I: Iterator,
    F: FnMut(&mut St, I::Item) -> Option<B>,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter.next() {
                Some(next) => match (self.f)(&mut self.state, next) {
                    Some(result) => return Some(result),
                    None => continue,
                },
                None => return None,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper) // can't know a lower bound, due to the scan function
    }
}

pub trait FilteringScanExt {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, Self::Item) -> Option<B>;
}

impl<I: Sized+Iterator> FilteringScanExt for I {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, I::Item) -> Option<B>,
    {
        FilteringScan{iter: self, f: f, state: initial_state}
    }
}

#[test]
fn peeking_test() {
    let test = vec!["first", "second", "third"];
    let mut index = 0;
    for (elem, peek) in test.into_iter().peeking() {
        match elem {
            "first" => {
                assert_eq!(peek, Some("second"));
                index += 1;
            },
            "second" => {
                assert_eq!(peek, Some("third"));
                index += 1;
            },
            "third" => {
                assert_eq!(peek, None);
                index += 1;
            },
            _ => assert!(false),
        }
    }
    assert_eq!(index, 3);
}

#[test]
fn filtering_scan_test() {
    let test = vec![1, 3, 1, 3];
    let index = 0;
    let mut sum = 0;
    for elem in test.into_iter().scan_filter(index, |index, x| {
        *index += 1;
        if (*index % 2) == 1 {
            Some(x)
        } else {
            None
        }
    }) {
        sum += elem;
    }
    assert_eq!(sum, 2);
}
<commit_msg>Added parser extension to Iterator Extensions<commit_after>use std::iter::Peekable;

/// An iterator that performs a lookahead of 1, utilizing the existing Peakable Iterator
/// Can be stacked to perform an even greater lookahead
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: Peekable<I>,
}

impl<I, A> Iterator for Peeking<I, A> where
    A: Clone,
    I: Iterator<Item=A>
{
    type Item = (A, Option<A>);

    #[inline]
    fn next(&mut self) -> Option<(A, Option<A>)> {
        match self.iter.next() {
            Some(item) => Some((item,
                match self.iter.peek() {
                    Some(ref item) => Some((*item).clone()),
                    None => None,
                }
            )),
            None => None,
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

pub trait PeekingExt {
    fn peeking(self) -> Peeking<Self, Self::Item>
        where Self: Sized+Iterator,
              Self::Item: Clone;
}

impl<A: Clone, I: Sized+Iterator<Item=A>> PeekingExt for I {
    fn peeking(self) -> Peeking<Self, A>
        where Self: Sized+Iterator
    {
         Peeking { iter: self.peekable() }
    }
}

/// An iterator to maintain state while iterating another iterator and allows filtering
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct FilteringScan<I, St, F> {
    iter: I,
    f: F,
    state: St,
}

impl<B, I, St, F> Iterator for FilteringScan<I, St, F> where
    I: Iterator,
    F: FnMut(&mut St, I::Item) -> Option<B>,
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter.next() {
                Some(next) => match (self.f)(&mut self.state, next) {
                    Some(result) => return Some(result),
                    None => continue,
                },
                None => return None,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper) // can't know a lower bound, due to the scan function
    }
}

pub trait FilteringScanExt {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, Self::Item) -> Option<B>;
}

impl<I: Sized+Iterator> FilteringScanExt for I {
    fn scan_filter<St, B, F>(self, initial_state: St, f: F) -> FilteringScan<Self, St, F>
        where Self: Sized+Iterator, F: FnMut(&mut St, I::Item) -> Option<B>,
    {
        FilteringScan{iter: self, f: f, state: initial_state}
    }
}

#[derive(Clone)]
pub enum ParseResult {
    Continue,
    Halt,
    End,
}

/// An iterator to maintain state while iterating another iterator and allows more complex parsing
// (allowing holding the current iterator value, continue if its goes empty and filter the output)
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Parser<I, A, St, F> where
    A: Clone,
    I: Iterator<Item=A>,
{
    iter: I,
    f: F,
    state: St,

    iter_state: ParseResult,
    current_elem: Option<A>,
}

impl<B, I, St, F, A> Iterator for Parser<I, A, St, F> where
    A: Clone,
    I: Iterator<Item=A>,
    F: FnMut(&mut St, Option<I::Item>) -> (ParseResult, Option<B>),
{
    type Item = B;

    #[inline]
    fn next(&mut self) -> Option<B> {
        loop {
            match self.iter_state {
                ParseResult::Continue => self.current_elem = self.iter.next(),
                ParseResult::Halt => {},
                ParseResult::End => return None,
            };

            let (new_state, result) = (self.f) (&mut self.state, self.current_elem.clone());

            self.iter_state = new_state;

            match result {
                Some(result) => return Some(result),
                None => continue,
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None) // can't know a lower or upper bound, due to the parse function
    }
}

pub trait ParserExt {
    fn parsing<St, B, F>(self, initial_state: St, f: F) -> Parser<Self, Self::Item, St, F>
        where Self: Sized+Iterator, Self::Item: Clone, F: Fn(&mut St, Option<Self::Item>) -> (ParseResult, Option<B>);
}

impl<A:Clone, I: Sized+Iterator<Item=A>>ParserExt for I {
    fn parsing<St, B, F>(self, initial_state: St, f: F) -> Parser<Self, A, St, F>
        where F: FnMut(&mut St, Option<A>) -> (ParseResult, Option<B>),
    {
        Parser{iter: self, f: f, state: initial_state, iter_state: ParseResult::Continue, current_elem: None}
    }
}

#[test]
fn peeking_test() {
    let test = vec!["first", "second", "third"];
    let mut index = 0;
    for (elem, peek) in test.into_iter().peeking() {
        match elem {
            "first" => {
                assert_eq!(peek, Some("second"));
                index += 1;
            },
            "second" => {
                assert_eq!(peek, Some("third"));
                index += 1;
            },
            "third" => {
                assert_eq!(peek, None);
                index += 1;
            },
            _ => assert!(false),
        }
    }
    assert_eq!(index, 3);
}

#[test]
fn filtering_scan_test() {
    let test = vec![1, 3, 1, 3];
    let index = 0;
    let mut sum = 0;
    for elem in test.into_iter().scan_filter(index, |index, x| {
        *index += 1;
        if (*index % 2) == 1 {
            Some(x)
        } else {
            None
        }
    }) {
        sum += elem;
    }
    assert_eq!(sum, 2);
}

#[test]
fn parsing_test() {

    struct ParseState {
        one_halt_test: u32,
        two_counter: u32,
        one_more_test: bool,
    }

    let mut result = vec![];

    let test = vec![1, 2, 2, 3];
    for elem in test.into_iter().parsing(
        ParseState {
            one_halt_test: 3,
            two_counter: 1,
            one_more_test: true,
        },
        |state, elem| {
            match elem {
                Some(1) => {
                    state.one_halt_test -= 1;
                    if state.one_halt_test == 0 {
                        (ParseResult::Continue, Some(1))
                    } else {
                        (ParseResult::Halt, None)
                    }
                },
                Some(2) => {
                    state.two_counter += 1;
                    (ParseResult::Continue, Some(state.two_counter))
                },
                Some(3) => {
                    (ParseResult::Continue, Some(4))
                },
                Some(_) => { panic!("found a bug in rust") },
                None => {
                    if state.one_more_test {
                        state.one_more_test = false;
                        (ParseResult::Continue, Some(5))
                    } else {
                        (ParseResult::End, None)
                    }
                }
            }
        }
    ) {
        result.push(elem);
    }

    assert_eq!(result, vec![1, 2, 3, 4, 5]);
}
<|endoftext|>


<commit_before>#[doc = "A type representing either success or failure"];

import either::either;

#[doc = "The result type"]
enum result<T, U> {
    #[doc = "Contains the successful result value"]
    ok(T),
    #[doc = "Contains the error value"]
    err(U)
}

#[doc = "
Get the value out of a successful result

# Failure

If the result is an error
"]
pure fn get<T: copy, U>(res: result<T, U>) -> T {
    alt res {
      ok(t) { t }
      err(the_err) {
        unchecked{ fail #fmt("get called on error result: %?", the_err); }
      }
    }
}

#[doc = "
Get the value out of an error result

# Failure

If the result is not an error
"]
pure fn get_err<T, U: copy>(res: result<T, U>) -> U {
    alt res {
      err(u) { u }
      ok(_) {
        fail "get_error called on ok result";
      }
    }
}

#[doc = "Returns true if the result is `ok`"]
pure fn is_success<T, U>(res: result<T, U>) -> bool {
    alt res {
      ok(_) { true }
      err(_) { false }
    }
}

#[doc = "Returns true if the result is `error`"]
pure fn is_failure<T, U>(res: result<T, U>) -> bool {
    !is_success(res)
}

#[doc = "
Convert to the `either` type

`ok` result variants are converted to `either::right` variants, `err`
result variants are converted to `either::left`.
"]
pure fn to_either<T: copy, U: copy>(res: result<U, T>) -> either<T, U> {
    alt res {
      ok(res) { either::right(res) }
      err(fail_) { either::left(fail_) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `ok` then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is `err` then it is immediately returned.
This function can be used to compose the results of two functions.

Example:

    let res = chain(read_file(file)) { |buf|
        ok(parse_buf(buf))
    }
"]
fn chain<T, U: copy, V: copy>(res: result<T, V>, op: fn(T) -> result<U, V>)
    -> result<U, V> {
    alt res {
      ok(t) { op(t) }
      err(e) { err(e) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `err` then the value is extracted and passed to `op`
whereupon `op`s result is returned. if `res` is `ok` then it is
immediately returned.  This function can be used to pass through a
successful result while handling an error.
"]
fn chain_err<T: copy, U: copy, V: copy>(
    res: result<T, V>,
    op: fn(V) -> result<T, U>)
    -> result<T, U> {
    alt res {
      ok(t) { ok(t) }
      err(v) { op(v) }
    }
}

impl extensions<T:copy, E:copy> for result<T,E> {
    fn get() -> T { get(self) }

    fn get_err() -> E { get_err(self) }

    fn is_success() -> bool { is_success(self) }

    fn is_failure() -> bool { is_failure(self) }

    fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
        chain(self, op)
    }

    fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
        chain_err(self, op)
    }
}

#[doc = "
Maps each element in the vector `ts` using the operation `op`.  Should an
error occur, no further mappings are performed and the error is returned.
Should no error occur, a vector containing the result of each map is
returned.

Here is an example which increments every integer in a vector,
checking for overflow:

    fn inc_conditionally(x: uint) -> result<uint,str> {
        if x == uint::max_value { ret err(\"overflow\"); }
        else { ret ok(x+1u); }
    }
    map([1u, 2u, 3u], inc_conditionally).chain {|incd|
        assert incd == [2u, 3u, 4u];
    }
"]
fn map<T,U:copy,V:copy>(
    ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {

    let mut vs: [V] = [];
    vec::reserve(vs, vec::len(ts));
    for vec::each(ts) {|t|
        alt op(t) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
    }
    ret ok(vs);
}

fn map_opt<T,U:copy,V:copy>(
    o_t: option<T>, op: fn(T) -> result<V,U>) -> result<option<V>,U> {

    alt o_t {
      none { ok(none) }
      some(t) {
        alt op(t) {
          ok(v) { ok(some(v)) }
          err(e) { err(e) }
        }
      }
    }
}

#[doc = "Same as map, but it operates over two parallel vectors.

A precondition is used here to ensure that the vectors are the same
length.  While we do not often use preconditions in the standard
library, a precondition is used here because result::t is generally
used in 'careful' code contexts where it is both appropriate and easy
to accommodate an error like the vectors being of different lengths."]
fn map2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
    : vec::same_length(ss, ts) -> result<[V],U> {

    let n = vec::len(ts);
    let mut vs = [];
    vec::reserve(vs, n);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(vs);
}

#[doc = "
Applies op to the pairwise elements from `ss` and `ts`, aborting on
error.  This could be implemented using `map2()` but it is more efficient
on its own as no result vector is built.
"]
fn iter2<S,T,U:copy>(ss: [S], ts: [T],
                     op: fn(S,T) -> result<(),U>)
    : vec::same_length(ss, ts)
    -> result<(),U> {

    let n = vec::len(ts);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(()) { }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(());
}

#[doc="
Unwraps a result, assuming it is an `ok(T)`

This operation is unsafe.
"]
fn unwrap<T, U>(-res: result<T, U>) -> T unsafe {
    let addr = alt res {
      ok(x) { ptr::addr_of(x) }
      err(_) { fail "option none" }
    };
    let liberated_value = unsafe::reinterpret_cast(*addr);
    unsafe::forget(res);
    ret liberated_value;
}

#[cfg(test)]
mod tests {
    fn op1() -> result::result<int, str> { result::ok(666) }

    fn op2(&&i: int) -> result::result<uint, str> {
        result::ok(i as uint + 1u)
    }

    fn op3() -> result::result<int, str> { result::err("sadface") }

    #[test]
    fn chain_success() {
        assert get(chain(op1(), op2)) == 667u;
    }

    #[test]
    fn chain_failure() {
        assert get_err(chain(op3(), op2)) == "sadface";
    }
}
<commit_msg>core: doc/err feedback tweeks for result::unwrap<commit_after>#[doc = "A type representing either success or failure"];

import either::either;

#[doc = "The result type"]
enum result<T, U> {
    #[doc = "Contains the successful result value"]
    ok(T),
    #[doc = "Contains the error value"]
    err(U)
}

#[doc = "
Get the value out of a successful result

# Failure

If the result is an error
"]
pure fn get<T: copy, U>(res: result<T, U>) -> T {
    alt res {
      ok(t) { t }
      err(the_err) {
        unchecked{ fail #fmt("get called on error result: %?", the_err); }
      }
    }
}

#[doc = "
Get the value out of an error result

# Failure

If the result is not an error
"]
pure fn get_err<T, U: copy>(res: result<T, U>) -> U {
    alt res {
      err(u) { u }
      ok(_) {
        fail "get_error called on ok result";
      }
    }
}

#[doc = "Returns true if the result is `ok`"]
pure fn is_success<T, U>(res: result<T, U>) -> bool {
    alt res {
      ok(_) { true }
      err(_) { false }
    }
}

#[doc = "Returns true if the result is `error`"]
pure fn is_failure<T, U>(res: result<T, U>) -> bool {
    !is_success(res)
}

#[doc = "
Convert to the `either` type

`ok` result variants are converted to `either::right` variants, `err`
result variants are converted to `either::left`.
"]
pure fn to_either<T: copy, U: copy>(res: result<U, T>) -> either<T, U> {
    alt res {
      ok(res) { either::right(res) }
      err(fail_) { either::left(fail_) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `ok` then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is `err` then it is immediately returned.
This function can be used to compose the results of two functions.

Example:

    let res = chain(read_file(file)) { |buf|
        ok(parse_buf(buf))
    }
"]
fn chain<T, U: copy, V: copy>(res: result<T, V>, op: fn(T) -> result<U, V>)
    -> result<U, V> {
    alt res {
      ok(t) { op(t) }
      err(e) { err(e) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `err` then the value is extracted and passed to `op`
whereupon `op`s result is returned. if `res` is `ok` then it is
immediately returned.  This function can be used to pass through a
successful result while handling an error.
"]
fn chain_err<T: copy, U: copy, V: copy>(
    res: result<T, V>,
    op: fn(V) -> result<T, U>)
    -> result<T, U> {
    alt res {
      ok(t) { ok(t) }
      err(v) { op(v) }
    }
}

impl extensions<T:copy, E:copy> for result<T,E> {
    fn get() -> T { get(self) }

    fn get_err() -> E { get_err(self) }

    fn is_success() -> bool { is_success(self) }

    fn is_failure() -> bool { is_failure(self) }

    fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
        chain(self, op)
    }

    fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
        chain_err(self, op)
    }
}

#[doc = "
Maps each element in the vector `ts` using the operation `op`.  Should an
error occur, no further mappings are performed and the error is returned.
Should no error occur, a vector containing the result of each map is
returned.

Here is an example which increments every integer in a vector,
checking for overflow:

    fn inc_conditionally(x: uint) -> result<uint,str> {
        if x == uint::max_value { ret err(\"overflow\"); }
        else { ret ok(x+1u); }
    }
    map([1u, 2u, 3u], inc_conditionally).chain {|incd|
        assert incd == [2u, 3u, 4u];
    }
"]
fn map<T,U:copy,V:copy>(
    ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {

    let mut vs: [V] = [];
    vec::reserve(vs, vec::len(ts));
    for vec::each(ts) {|t|
        alt op(t) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
    }
    ret ok(vs);
}

fn map_opt<T,U:copy,V:copy>(
    o_t: option<T>, op: fn(T) -> result<V,U>) -> result<option<V>,U> {

    alt o_t {
      none { ok(none) }
      some(t) {
        alt op(t) {
          ok(v) { ok(some(v)) }
          err(e) { err(e) }
        }
      }
    }
}

#[doc = "Same as map, but it operates over two parallel vectors.

A precondition is used here to ensure that the vectors are the same
length.  While we do not often use preconditions in the standard
library, a precondition is used here because result::t is generally
used in 'careful' code contexts where it is both appropriate and easy
to accommodate an error like the vectors being of different lengths."]
fn map2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
    : vec::same_length(ss, ts) -> result<[V],U> {

    let n = vec::len(ts);
    let mut vs = [];
    vec::reserve(vs, n);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(vs);
}

#[doc = "
Applies op to the pairwise elements from `ss` and `ts`, aborting on
error.  This could be implemented using `map2()` but it is more efficient
on its own as no result vector is built.
"]
fn iter2<S,T,U:copy>(ss: [S], ts: [T],
                     op: fn(S,T) -> result<(),U>)
    : vec::same_length(ss, ts)
    -> result<(),U> {

    let n = vec::len(ts);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(()) { }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(());
}

#[doc="
Unwraps a result, assuming it is an `ok(T)`
"]
fn unwrap<T, U>(-res: result<T, U>) -> T unsafe {
    let addr = alt res {
      ok(x) { ptr::addr_of(x) }
      err(_) { fail "error result" }
    };
    let liberated_value = unsafe::reinterpret_cast(*addr);
    unsafe::forget(res);
    ret liberated_value;
}

#[cfg(test)]
mod tests {
    fn op1() -> result::result<int, str> { result::ok(666) }

    fn op2(&&i: int) -> result::result<uint, str> {
        result::ok(i as uint + 1u)
    }

    fn op3() -> result::result<int, str> { result::err("sadface") }

    #[test]
    fn chain_success() {
        assert get(chain(op1(), op2)) == 667u;
    }

    #[test]
    fn chain_failure() {
        assert get_err(chain(op3(), op2)) == "sadface";
    }
}
<|endoftext|>