<commit_before>//! Random number generation

// NB: transitional, de-mode-ing.
#[warn(deprecated_mode)];
#[forbid(deprecated_pattern)];

#[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
pub trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
pub 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| {
                r.push(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
pub fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
pub 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.
 */
pub 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
    }
}

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

pub 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)]
pub mod tests {
    #[test]
    pub 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]
    pub 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]
    pub 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]
    pub 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))]
    pub fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    pub 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))]
    pub fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

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

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

    #[test]
    pub 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]
    pub 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]
    pub fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    pub 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]
    pub 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]
    pub 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]
    pub 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]
    pub 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>Finish de-exporting path, rand, run, sys. Part of #3583.<commit_after>//! Random number generation

// NB: transitional, de-mode-ing.
#[warn(deprecated_mode)];
#[forbid(deprecated_pattern)];

#[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
pub trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
pub 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| {
                r.push(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
pub fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
pub 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.
 */
pub 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
    }
}

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

pub 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)]
pub mod tests {
    #[test]
    pub 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]
    pub 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]
    pub 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]
    pub 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))]
    pub fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    pub 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))]
    pub fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

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

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

    #[test]
    pub 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]
    pub 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]
    pub fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    pub 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]
    pub 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]
    pub 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]
    pub 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]
    pub 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>// Some temporary libuv hacks for servo

#[cfg(target_os = "linux")];
#[cfg(target_os = "macos")];
#[cfg(target_os = "freebsd")];

#[nolink]
native mod rustrt {
    fn rust_uvtmp_create_thread() -> thread;
    fn rust_uvtmp_start_thread(thread: thread);
    fn rust_uvtmp_join_thread(thread: thread);
    fn rust_uvtmp_delete_thread(thread: thread);
    fn rust_uvtmp_connect(
        thread: thread,
        req_id: u32,
        ip: str::sbuf,
        chan: comm::chan<iomsg>) -> connect_data;
    fn rust_uvtmp_close_connection(thread: thread, req_id: u32);
    fn rust_uvtmp_write(
        thread: thread,
        req_id: u32,
        buf: *u8,
        len: ctypes::size_t,
        chan: comm::chan<iomsg>);
    fn rust_uvtmp_read_start(
        thread: thread,
        req_id: u32,
        chan: comm::chan<iomsg>);
    fn rust_uvtmp_timer(
        thread: thread,
        timeout: u32,
        req_id: u32,
        chan: comm::chan<iomsg>);
    fn rust_uvtmp_delete_buf(buf: *u8);
    fn rust_uvtmp_get_req_id(cd: connect_data) -> u32;
}

type thread = *ctypes::void;

type connect_data = *ctypes::void;

enum iomsg {
    whatever,
    connected(connect_data),
    wrote(connect_data),
    read(connect_data, *u8, ctypes::ssize_t),
    timer(u32),
    exit
}

fn create_thread() -> thread {
    rustrt::rust_uvtmp_create_thread()
}

fn start_thread(thread: thread) {
    rustrt::rust_uvtmp_start_thread(thread)
}

fn join_thread(thread: thread) {
    rustrt::rust_uvtmp_join_thread(thread)
}

fn delete_thread(thread: thread) {
    rustrt::rust_uvtmp_delete_thread(thread)
}

fn connect(thread: thread, req_id: u32, ip: str, ch: comm::chan<iomsg>) -> connect_data {
    str::as_buf(ip) {|ipbuf|
        rustrt::rust_uvtmp_connect(thread, req_id, ipbuf, ch)
    }
}

fn close_connection(thread: thread, req_id: u32) {
    rustrt::rust_uvtmp_close_connection(thread, req_id);
}

fn write(thread: thread, req_id: u32, bytes: [u8],
         chan: comm::chan<iomsg>) unsafe {
    rustrt::rust_uvtmp_write(
        thread, req_id, vec::to_ptr(bytes), vec::len(bytes), chan);
}

fn read_start(thread: thread, req_id: u32,
              chan: comm::chan<iomsg>) {
    rustrt::rust_uvtmp_read_start(thread, req_id, chan);
}

fn timer_start(thread: thread, timeout: u32, req_id: u32,
              chan: comm::chan<iomsg>) {
    rustrt::rust_uvtmp_timer(thread, timeout, req_id, chan);
}

fn delete_buf(buf: *u8) {
    rustrt::rust_uvtmp_delete_buf(buf);
}

fn get_req_id(cd: connect_data) -> u32 {
    ret rustrt::rust_uvtmp_get_req_id(cd);
}

#[test]
fn test_start_stop() {
    let thread = create_thread();
    start_thread(thread);
    join_thread(thread);
    delete_thread(thread);
}

#[test]
#[ignore]
fn test_connect() {
    let thread = create_thread();
    start_thread(thread);
    let port = comm::port();
    let chan = comm::chan(port);
    connect(thread, 0u32, "74.125.224.146", chan);
    alt comm::recv(port) {
      connected(cd) {
        close_connection(thread, 0u32);
      }
    }
    join_thread(thread);
    delete_thread(thread);
}

#[test]
#[ignore]
fn test_http() {
    let thread = create_thread();
    start_thread(thread);
    let port = comm::port();
    let chan = comm::chan(port);
    connect(thread, 0u32, "74.125.224.146", chan);
    alt comm::recv(port) {
      connected(cd) {
        write(thread, 0u32, str::bytes("GET / HTTP/1.0\n\n"), chan);
        alt comm::recv(port) {
          wrote(cd) {
            read_start(thread, 0u32, chan);
            let keep_going = true;
            while keep_going {
                alt comm::recv(port) {
                  read(_, buf, -1) {
                    keep_going = false;
                    delete_buf(buf);
                  }
                  read(_, buf, len) {
                    unsafe {
                        log(error, len);
                        let buf = vec::unsafe::from_buf(buf, len as uint);
                        let str = str::unsafe_from_bytes(buf);
                        #error("read something");
                        io::println(str);
                    }
                    delete_buf(buf);
                  }
                }
            }
            close_connection(thread, 0u32);
          }
        }
      }
    }
    join_thread(thread);
    delete_thread(thread);
}<commit_msg>std: Long lines<commit_after>// Some temporary libuv hacks for servo

#[cfg(target_os = "linux")];
#[cfg(target_os = "macos")];
#[cfg(target_os = "freebsd")];

#[nolink]
native mod rustrt {
    fn rust_uvtmp_create_thread() -> thread;
    fn rust_uvtmp_start_thread(thread: thread);
    fn rust_uvtmp_join_thread(thread: thread);
    fn rust_uvtmp_delete_thread(thread: thread);
    fn rust_uvtmp_connect(
        thread: thread,
        req_id: u32,
        ip: str::sbuf,
        chan: comm::chan<iomsg>) -> connect_data;
    fn rust_uvtmp_close_connection(thread: thread, req_id: u32);
    fn rust_uvtmp_write(
        thread: thread,
        req_id: u32,
        buf: *u8,
        len: ctypes::size_t,
        chan: comm::chan<iomsg>);
    fn rust_uvtmp_read_start(
        thread: thread,
        req_id: u32,
        chan: comm::chan<iomsg>);
    fn rust_uvtmp_timer(
        thread: thread,
        timeout: u32,
        req_id: u32,
        chan: comm::chan<iomsg>);
    fn rust_uvtmp_delete_buf(buf: *u8);
    fn rust_uvtmp_get_req_id(cd: connect_data) -> u32;
}

type thread = *ctypes::void;

type connect_data = *ctypes::void;

enum iomsg {
    whatever,
    connected(connect_data),
    wrote(connect_data),
    read(connect_data, *u8, ctypes::ssize_t),
    timer(u32),
    exit
}

fn create_thread() -> thread {
    rustrt::rust_uvtmp_create_thread()
}

fn start_thread(thread: thread) {
    rustrt::rust_uvtmp_start_thread(thread)
}

fn join_thread(thread: thread) {
    rustrt::rust_uvtmp_join_thread(thread)
}

fn delete_thread(thread: thread) {
    rustrt::rust_uvtmp_delete_thread(thread)
}

fn connect(thread: thread, req_id: u32,
           ip: str, ch: comm::chan<iomsg>) -> connect_data {
    str::as_buf(ip) {|ipbuf|
        rustrt::rust_uvtmp_connect(thread, req_id, ipbuf, ch)
    }
}

fn close_connection(thread: thread, req_id: u32) {
    rustrt::rust_uvtmp_close_connection(thread, req_id);
}

fn write(thread: thread, req_id: u32, bytes: [u8],
         chan: comm::chan<iomsg>) unsafe {
    rustrt::rust_uvtmp_write(
        thread, req_id, vec::to_ptr(bytes), vec::len(bytes), chan);
}

fn read_start(thread: thread, req_id: u32,
              chan: comm::chan<iomsg>) {
    rustrt::rust_uvtmp_read_start(thread, req_id, chan);
}

fn timer_start(thread: thread, timeout: u32, req_id: u32,
              chan: comm::chan<iomsg>) {
    rustrt::rust_uvtmp_timer(thread, timeout, req_id, chan);
}

fn delete_buf(buf: *u8) {
    rustrt::rust_uvtmp_delete_buf(buf);
}

fn get_req_id(cd: connect_data) -> u32 {
    ret rustrt::rust_uvtmp_get_req_id(cd);
}

#[test]
fn test_start_stop() {
    let thread = create_thread();
    start_thread(thread);
    join_thread(thread);
    delete_thread(thread);
}

#[test]
#[ignore]
fn test_connect() {
    let thread = create_thread();
    start_thread(thread);
    let port = comm::port();
    let chan = comm::chan(port);
    connect(thread, 0u32, "74.125.224.146", chan);
    alt comm::recv(port) {
      connected(cd) {
        close_connection(thread, 0u32);
      }
    }
    join_thread(thread);
    delete_thread(thread);
}

#[test]
#[ignore]
fn test_http() {
    let thread = create_thread();
    start_thread(thread);
    let port = comm::port();
    let chan = comm::chan(port);
    connect(thread, 0u32, "74.125.224.146", chan);
    alt comm::recv(port) {
      connected(cd) {
        write(thread, 0u32, str::bytes("GET / HTTP/1.0\n\n"), chan);
        alt comm::recv(port) {
          wrote(cd) {
            read_start(thread, 0u32, chan);
            let keep_going = true;
            while keep_going {
                alt comm::recv(port) {
                  read(_, buf, -1) {
                    keep_going = false;
                    delete_buf(buf);
                  }
                  read(_, buf, len) {
                    unsafe {
                        log(error, len);
                        let buf = vec::unsafe::from_buf(buf, len as uint);
                        let str = str::unsafe_from_bytes(buf);
                        #error("read something");
                        io::println(str);
                    }
                    delete_buf(buf);
                  }
                }
            }
            close_connection(thread, 0u32);
          }
        }
      }
    }
    join_thread(thread);
    delete_thread(thread);
}<|endoftext|>


<commit_before>#[macro_use]
extern crate rustfbp;
extern crate capnp;

use std::fs;
use std::process::Command;
use std::process;
use std::path::Path;
use std::env;

agent! {
    input(path: fs_path, edge: prim_text, input: prim_text),
    output(output: any),
    fn run(&mut self) -> Result<Signal>{

        let mut path_msg = self.input.path.recv()?;
        let path: fs_path::Reader = path_msg.read_schema()?;
        let path = path.get_path()?;

        let mut edge_msg = self.input.edge.recv()?;
        let edge: prim_text::Reader = edge_msg.read_schema()?;
        let f_edge = edge.get_text()?;

        let mut input_msg = self.input.input.recv()?;
        let input: prim_text::Reader = input_msg.read_schema()?;
        let input = input.get_text()?;

        let mut child = Command::new("capnp_path" )
            .arg("encode")
            .arg(path)
            .arg(f_edge)
            .stdin(process::Stdio::piped())
            .stdout(process::Stdio::piped())
            .spawn()
            ?;

        if let Some(ref mut stdin) = child.stdin {
            stdin.write_all(input.as_bytes())?;
        } else {
            unreachable!();
        }
        let output = child.wait_with_output()?;

        if !output.status.success() {
            return Err(result::Error::Misc("capnp encode command doesn't work".into()));
        }

        let mut send_msg = Msg::new();
        send_msg.vec = output.stdout;
        let _ = self.output.output.send(send_msg);
        Ok(End)
    }
}
<commit_msg>[FIX] prob: Composite schema not allowed<commit_after>#[macro_use]
extern crate rustfbp;
extern crate capnp;

use std::fs;
use std::process::Command;
use std::process;
use std::path::Path;
use std::env;

agent! {
    input(path: fs_path, edge: prim_text, input: prim_text),
    output(output: any),
    fn run(&mut self) -> Result<Signal>{

        let mut path_msg = self.input.path.recv()?;
        let path: fs_path::Reader = path_msg.read_schema()?;
        let path = path.get_path()?;

        let mut edge_msg = self.input.edge.recv()?;
        let edge: prim_text::Reader = edge_msg.read_schema()?;
        let f_edge = edge.get_text()?;

        let mut input_msg = self.input.input.recv()?;
        let input: prim_text::Reader = input_msg.read_schema()?;
        let input = input.get_text()?;

        let mut child = Command::new("capnp_path" )
            .arg("-I")
            .arg("/")
            .arg("encode")
            .arg(path)
            .arg(f_edge)
            .stdin(process::Stdio::piped())
            .stdout(process::Stdio::piped())
            .spawn()
            ?;

        if let Some(ref mut stdin) = child.stdin {
            stdin.write_all(input.as_bytes())?;
        } else {
            unreachable!();
        }
        let output = child.wait_with_output()?;

        if !output.status.success() {
            return Err(result::Error::Misc("capnp encode command doesn't work".into()));
        }

        let mut send_msg = Msg::new();
        send_msg.vec = output.stdout;
        let _ = self.output.output.send(send_msg);
        Ok(End)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

/*!
 *
 * Traits representing built-in operators, useful for overloading
 *
 * Implementing these traits allows you to get an effect similar to
 * overloading operators.
 *
 * The values for the right hand side of an operator are automatically
 * borrowed, so `a + b` is sugar for `a.add(&b)`.
 *
 * All of these traits are imported by the prelude, so they are available in
 * every Rust program.
 *
 * # Example
 *
 * This example creates a `Point` struct that implements `Add` and `Sub`, and then
 * demonstrates adding and subtracting two `Point`s.
 *
 * ```rust
 * struct Point {
 *     x: int,
 *     y: int
 * }
 *
 * impl Add<Point, Point> for Point {
 *     fn add(&self, other: &Point) -> Point {
 *         Point {x: self.x + other.x, y: self.y + other.y}
 *     }
 * }
 *
 * impl Sub<Point, Point> for Point {
 *     fn sub(&self, other: &Point) -> Point {
 *         Point {x: self.x - other.x, y: self.y - other.y}
 *     }
 * }
 * fn main() {
 *     println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3});
 *     println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3});
 * }
 * ```
 *
 * See the documentation for each trait for a minimum implementation that prints
 * something to the screen.
 *
 */

/**
 *
 * The `Drop` trait is used to run some code when a value goes out of scope. This
 * is sometimes called a 'destructor'.
 *
 * # Example
 *
 * A trivial implementation of `Drop`. The `drop` method is called when `_x` goes
 * out of scope, and therefore `main` prints `Dropping!`.
 *
 * ```rust
 * struct HasDrop;
 *
 * impl Drop for HasDrop {
 *   fn drop(&mut self) {
 *       println!("Dropping!");
 *   }
 * }
 *
 * fn main() {
 *   let _x = HasDrop;
 * }
 * ```
 */
#[lang="drop"]
pub trait Drop {
    /// The `drop` method, called when the value goes out of scope.
    fn drop(&mut self);
}

/**
 *
 * The `Add` trait is used to specify the functionality of `+`.
 *
 * # Example
 *
 * A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up
 * calling `add`, and therefore, `main` prints `Adding!`.
 *
 * ```rust
 * struct Foo;
 *
 * impl Add<Foo, Foo> for Foo {
 *     fn add(&self, _rhs: &Foo) -> Foo {
 *       println!("Adding!");
 *       *self
 *   }
 * }
 *
 * fn main() {
 *   Foo + Foo;
 * }
 * ```
 */
#[lang="add"]
pub trait Add<RHS,Result> {
    /// The method for the `+` operator
    fn add(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Sub` trait is used to specify the functionality of `-`.
 *
 * # Example
 *
 * A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up
 * calling `sub`, and therefore, `main` prints `Subtracting!`.
 *
 * ```rust
 * struct Foo;
 *
 * impl Sub<Foo, Foo> for Foo {
 *     fn sub(&self, _rhs: &Foo) -> Foo {
 *         println!("Subtracting!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo - Foo;
 * }
 * ```
 */
#[lang="sub"]
pub trait Sub<RHS,Result> {
    /// The method for the `-` operator
    fn sub(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Mul` trait is used to specify the functionality of `*`.
 *
 * # Example
 *
 * A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up
 * calling `mul`, and therefore, `main` prints `Multiplying!`.
 *
 * ```rust
 * struct Foo;
 *
 * impl Mul<Foo, Foo> for Foo {
 *     fn mul(&self, _rhs: &Foo) -> Foo {
 *         println!("Multiplying!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo * Foo;
 * }
 * ```
 */
#[lang="mul"]
pub trait Mul<RHS,Result> {
    /// The method for the `*` operator
    fn mul(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Div` trait is used to specify the functionality of `/`.
 *
 * # Example
 *
 * A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up
 * calling `div`, and therefore, `main` prints `Dividing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Div<Foo, Foo> for Foo {
 *     fn div(&self, _rhs: &Foo) -> Foo {
 *         println!("Dividing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo / Foo;
 * }
 * ```
 */
#[lang="div"]
pub trait Div<RHS,Result> {
    /// The method for the `/` operator
    fn div(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Rem` trait is used to specify the functionality of `%`.
 *
 * # Example
 *
 * A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up
 * calling `rem`, and therefore, `main` prints `Remainder-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Rem<Foo, Foo> for Foo {
 *     fn rem(&self, _rhs: &Foo) -> Foo {
 *         println!("Remainder-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo % Foo;
 * }
 * ```
 */
#[lang="rem"]
pub trait Rem<RHS,Result> {
    /// The method for the `%` operator
    fn rem(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Neg` trait is used to specify the functionality of unary `-`.
 *
 * # Example
 *
 * A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling
 * `neg`, and therefore, `main` prints `Negating!`.
 *
 * ```
 * struct Foo;
 *
 * impl Neg<Foo> for Foo {
 *     fn neg(&self) -> Foo {
 *         println!("Negating!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     -Foo;
 * }
 * ```
 */
#[lang="neg"]
pub trait Neg<Result> {
    /// The method for the unary `-` operator
    fn neg(&self) -> Result;
}

/**
 *
 * The `Not` trait is used to specify the functionality of unary `!`.
 *
 * # Example
 *
 * A trivial implementation of `Not`. When `!Foo` happens, it ends up calling
 * `not`, and therefore, `main` prints `Not-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Not<Foo> for Foo {
 *     fn not(&self) -> Foo {
 *         println!("Not-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     !Foo;
 * }
 * ```
 */
#[lang="not"]
pub trait Not<Result> {
    /// The method for the unary `!` operator
    fn not(&self) -> Result;
}

/**
 *
 * The `BitAnd` trait is used to specify the functionality of `&`.
 *
 * # Example
 *
 * A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up
 * calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl BitAnd<Foo, Foo> for Foo {
 *     fn bitand(&self, _rhs: &Foo) -> Foo {
 *         println!("Bitwise And-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo & Foo;
 * }
 * ```
 */
#[lang="bitand"]
pub trait BitAnd<RHS,Result> {
    /// The method for the `&` operator
    fn bitand(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `BitOr` trait is used to specify the functionality of `|`.
 *
 * # Example
 *
 * A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up
 * calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl BitOr<Foo, Foo> for Foo {
 *     fn bitor(&self, _rhs: &Foo) -> Foo {
 *         println!("Bitwise Or-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo | Foo;
 * }
 * ```
 */
#[lang="bitor"]
pub trait BitOr<RHS,Result> {
    /// The method for the `|` operator
    fn bitor(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `BitXor` trait is used to specify the functionality of `^`.
 *
 * # Example
 *
 * A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up
 * calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl BitXor<Foo, Foo> for Foo {
 *     fn bitxor(&self, _rhs: &Foo) -> Foo {
 *         println!("Bitwise Xor-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo ^ Foo;
 * }
 * ```
 */
#[lang="bitxor"]
pub trait BitXor<RHS,Result> {
    /// The method for the `^` operator
    fn bitxor(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Shl` trait is used to specify the functionality of `<<`.
 *
 * # Example
 *
 * A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up
 * calling `shl`, and therefore, `main` prints `Shifting left!`.
 *
 * ```
 * struct Foo;
 *
 * impl Shl<Foo, Foo> for Foo {
 *     fn shl(&self, _rhs: &Foo) -> Foo {
 *         println!("Shifting left!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo << Foo;
 * }
 * ```
 */
#[lang="shl"]
pub trait Shl<RHS,Result> {
    /// The method for the `<<` operator
    fn shl(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Shr` trait is used to specify the functionality of `>>`.
 *
 * # Example
 *
 * A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up
 * calling `shr`, and therefore, `main` prints `Shifting right!`.
 *
 * ```
 * struct Foo;
 *
 * impl Shr<Foo, Foo> for Foo {
 *     fn shr(&self, _rhs: &Foo) -> Foo {
 *         println!("Shifting right!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo >> Foo;
 * }
 * ```
 */
#[lang="shr"]
pub trait Shr<RHS,Result> {
    /// The method for the `>>` operator
    fn shr(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Index` trait is used to specify the functionality of indexing operations
 * like `arr[idx]`.
 *
 * # Example
 *
 * A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up
 * calling `index`, and therefore, `main` prints `Indexing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Index<Foo, Foo> for Foo {
 *     fn index(&self, _rhs: &Foo) -> Foo {
 *         println!("Indexing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo[Foo];
 * }
 * ```
 */
#[lang="index"]
pub trait Index<Index,Result> {
    /// The method for the indexing (`Foo[Bar]`) operation
    fn index(&self, index: &Index) -> Result;
}

/**
 *
 * The `Deref` trait is used to specify the functionality of dereferencing
 * operations like `*v`.
 *
 * # Example
 *
 * A struct with a single field which is accessible via dereferencing the
 * struct.
 *
 * ```
 * struct DerefExample<T> {
 *     value: T
 * }
 *
 * impl<T> Deref<T> for DerefExample<T> {
 *     fn deref<'a>(&'a self) -> &'a T {
 *         &self.value
 *     }
 * }
 *
 * fn main() {
 *     let x = DerefExample { value: 'a' };
 *     assert_eq!('a', *x);
 * }
 * ```
 */
#[lang="deref"]
pub trait Deref<Result> {
    /// The method called to dereference a value
    fn deref<'a>(&'a self) -> &'a Result;
}

/**
 *
 * The `DerefMut` trait is used to specify the functionality of dereferencing
 * mutably like `*v = 1;`
 *
 * # Example
 *
 * A struct with a single field which is modifiable via dereferencing the
 * struct.
 *
 * ```
 * struct DerefMutExample<T> {
 *     value: T
 * }
 *
 * impl<T> Deref<T> for DerefMutExample<T> {
 *     fn deref<'a>(&'a self) -> &'a T {
 *         &self.value
 *     }
 * }
 *
 * impl<T> DerefMut<T> for DerefMutExample<T> {
 *     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
 *         &mut self.value
 *     }
 * }
 *
 * fn main() {
 *     let mut x = DerefMutExample { value: 'a' };
 *     *x = 'b';
 *     assert_eq!('b', *x);
 * }
 * ```
 */
#[lang="deref_mut"]
pub trait DerefMut<Result>: Deref<Result> {
    /// The method called to mutably dereference a value
    fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
}

#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::Bencher;
    use ops::Drop;

    // Overhead of dtors

    struct HasDtor {
        x: int
    }

    impl Drop for HasDtor {
        fn drop(&mut self) {
        }
    }

    #[bench]
    fn alloc_obj_with_dtor(b: &mut Bencher) {
        b.iter(|| {
            HasDtor { x : 10 };
        })
    }
}
<commit_msg>core: More concise description for mod ops<commit_after>// Copyright 2012 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.

/*!
 *
 * Overloadable operators
 *
 * Implementing these traits allows you to get an effect similar to
 * overloading operators.
 *
 * The values for the right hand side of an operator are automatically
 * borrowed, so `a + b` is sugar for `a.add(&b)`.
 *
 * All of these traits are imported by the prelude, so they are available in
 * every Rust program.
 *
 * # Example
 *
 * This example creates a `Point` struct that implements `Add` and `Sub`, and then
 * demonstrates adding and subtracting two `Point`s.
 *
 * ```rust
 * struct Point {
 *     x: int,
 *     y: int
 * }
 *
 * impl Add<Point, Point> for Point {
 *     fn add(&self, other: &Point) -> Point {
 *         Point {x: self.x + other.x, y: self.y + other.y}
 *     }
 * }
 *
 * impl Sub<Point, Point> for Point {
 *     fn sub(&self, other: &Point) -> Point {
 *         Point {x: self.x - other.x, y: self.y - other.y}
 *     }
 * }
 * fn main() {
 *     println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3});
 *     println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3});
 * }
 * ```
 *
 * See the documentation for each trait for a minimum implementation that prints
 * something to the screen.
 *
 */

/**
 *
 * The `Drop` trait is used to run some code when a value goes out of scope. This
 * is sometimes called a 'destructor'.
 *
 * # Example
 *
 * A trivial implementation of `Drop`. The `drop` method is called when `_x` goes
 * out of scope, and therefore `main` prints `Dropping!`.
 *
 * ```rust
 * struct HasDrop;
 *
 * impl Drop for HasDrop {
 *   fn drop(&mut self) {
 *       println!("Dropping!");
 *   }
 * }
 *
 * fn main() {
 *   let _x = HasDrop;
 * }
 * ```
 */
#[lang="drop"]
pub trait Drop {
    /// The `drop` method, called when the value goes out of scope.
    fn drop(&mut self);
}

/**
 *
 * The `Add` trait is used to specify the functionality of `+`.
 *
 * # Example
 *
 * A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up
 * calling `add`, and therefore, `main` prints `Adding!`.
 *
 * ```rust
 * struct Foo;
 *
 * impl Add<Foo, Foo> for Foo {
 *     fn add(&self, _rhs: &Foo) -> Foo {
 *       println!("Adding!");
 *       *self
 *   }
 * }
 *
 * fn main() {
 *   Foo + Foo;
 * }
 * ```
 */
#[lang="add"]
pub trait Add<RHS,Result> {
    /// The method for the `+` operator
    fn add(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Sub` trait is used to specify the functionality of `-`.
 *
 * # Example
 *
 * A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up
 * calling `sub`, and therefore, `main` prints `Subtracting!`.
 *
 * ```rust
 * struct Foo;
 *
 * impl Sub<Foo, Foo> for Foo {
 *     fn sub(&self, _rhs: &Foo) -> Foo {
 *         println!("Subtracting!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo - Foo;
 * }
 * ```
 */
#[lang="sub"]
pub trait Sub<RHS,Result> {
    /// The method for the `-` operator
    fn sub(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Mul` trait is used to specify the functionality of `*`.
 *
 * # Example
 *
 * A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up
 * calling `mul`, and therefore, `main` prints `Multiplying!`.
 *
 * ```rust
 * struct Foo;
 *
 * impl Mul<Foo, Foo> for Foo {
 *     fn mul(&self, _rhs: &Foo) -> Foo {
 *         println!("Multiplying!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo * Foo;
 * }
 * ```
 */
#[lang="mul"]
pub trait Mul<RHS,Result> {
    /// The method for the `*` operator
    fn mul(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Div` trait is used to specify the functionality of `/`.
 *
 * # Example
 *
 * A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up
 * calling `div`, and therefore, `main` prints `Dividing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Div<Foo, Foo> for Foo {
 *     fn div(&self, _rhs: &Foo) -> Foo {
 *         println!("Dividing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo / Foo;
 * }
 * ```
 */
#[lang="div"]
pub trait Div<RHS,Result> {
    /// The method for the `/` operator
    fn div(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Rem` trait is used to specify the functionality of `%`.
 *
 * # Example
 *
 * A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up
 * calling `rem`, and therefore, `main` prints `Remainder-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Rem<Foo, Foo> for Foo {
 *     fn rem(&self, _rhs: &Foo) -> Foo {
 *         println!("Remainder-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo % Foo;
 * }
 * ```
 */
#[lang="rem"]
pub trait Rem<RHS,Result> {
    /// The method for the `%` operator
    fn rem(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Neg` trait is used to specify the functionality of unary `-`.
 *
 * # Example
 *
 * A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling
 * `neg`, and therefore, `main` prints `Negating!`.
 *
 * ```
 * struct Foo;
 *
 * impl Neg<Foo> for Foo {
 *     fn neg(&self) -> Foo {
 *         println!("Negating!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     -Foo;
 * }
 * ```
 */
#[lang="neg"]
pub trait Neg<Result> {
    /// The method for the unary `-` operator
    fn neg(&self) -> Result;
}

/**
 *
 * The `Not` trait is used to specify the functionality of unary `!`.
 *
 * # Example
 *
 * A trivial implementation of `Not`. When `!Foo` happens, it ends up calling
 * `not`, and therefore, `main` prints `Not-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Not<Foo> for Foo {
 *     fn not(&self) -> Foo {
 *         println!("Not-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     !Foo;
 * }
 * ```
 */
#[lang="not"]
pub trait Not<Result> {
    /// The method for the unary `!` operator
    fn not(&self) -> Result;
}

/**
 *
 * The `BitAnd` trait is used to specify the functionality of `&`.
 *
 * # Example
 *
 * A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up
 * calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl BitAnd<Foo, Foo> for Foo {
 *     fn bitand(&self, _rhs: &Foo) -> Foo {
 *         println!("Bitwise And-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo & Foo;
 * }
 * ```
 */
#[lang="bitand"]
pub trait BitAnd<RHS,Result> {
    /// The method for the `&` operator
    fn bitand(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `BitOr` trait is used to specify the functionality of `|`.
 *
 * # Example
 *
 * A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up
 * calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl BitOr<Foo, Foo> for Foo {
 *     fn bitor(&self, _rhs: &Foo) -> Foo {
 *         println!("Bitwise Or-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo | Foo;
 * }
 * ```
 */
#[lang="bitor"]
pub trait BitOr<RHS,Result> {
    /// The method for the `|` operator
    fn bitor(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `BitXor` trait is used to specify the functionality of `^`.
 *
 * # Example
 *
 * A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up
 * calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`.
 *
 * ```
 * struct Foo;
 *
 * impl BitXor<Foo, Foo> for Foo {
 *     fn bitxor(&self, _rhs: &Foo) -> Foo {
 *         println!("Bitwise Xor-ing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo ^ Foo;
 * }
 * ```
 */
#[lang="bitxor"]
pub trait BitXor<RHS,Result> {
    /// The method for the `^` operator
    fn bitxor(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Shl` trait is used to specify the functionality of `<<`.
 *
 * # Example
 *
 * A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up
 * calling `shl`, and therefore, `main` prints `Shifting left!`.
 *
 * ```
 * struct Foo;
 *
 * impl Shl<Foo, Foo> for Foo {
 *     fn shl(&self, _rhs: &Foo) -> Foo {
 *         println!("Shifting left!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo << Foo;
 * }
 * ```
 */
#[lang="shl"]
pub trait Shl<RHS,Result> {
    /// The method for the `<<` operator
    fn shl(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Shr` trait is used to specify the functionality of `>>`.
 *
 * # Example
 *
 * A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up
 * calling `shr`, and therefore, `main` prints `Shifting right!`.
 *
 * ```
 * struct Foo;
 *
 * impl Shr<Foo, Foo> for Foo {
 *     fn shr(&self, _rhs: &Foo) -> Foo {
 *         println!("Shifting right!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo >> Foo;
 * }
 * ```
 */
#[lang="shr"]
pub trait Shr<RHS,Result> {
    /// The method for the `>>` operator
    fn shr(&self, rhs: &RHS) -> Result;
}

/**
 *
 * The `Index` trait is used to specify the functionality of indexing operations
 * like `arr[idx]`.
 *
 * # Example
 *
 * A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up
 * calling `index`, and therefore, `main` prints `Indexing!`.
 *
 * ```
 * struct Foo;
 *
 * impl Index<Foo, Foo> for Foo {
 *     fn index(&self, _rhs: &Foo) -> Foo {
 *         println!("Indexing!");
 *         *self
 *     }
 * }
 *
 * fn main() {
 *     Foo[Foo];
 * }
 * ```
 */
#[lang="index"]
pub trait Index<Index,Result> {
    /// The method for the indexing (`Foo[Bar]`) operation
    fn index(&self, index: &Index) -> Result;
}

/**
 *
 * The `Deref` trait is used to specify the functionality of dereferencing
 * operations like `*v`.
 *
 * # Example
 *
 * A struct with a single field which is accessible via dereferencing the
 * struct.
 *
 * ```
 * struct DerefExample<T> {
 *     value: T
 * }
 *
 * impl<T> Deref<T> for DerefExample<T> {
 *     fn deref<'a>(&'a self) -> &'a T {
 *         &self.value
 *     }
 * }
 *
 * fn main() {
 *     let x = DerefExample { value: 'a' };
 *     assert_eq!('a', *x);
 * }
 * ```
 */
#[lang="deref"]
pub trait Deref<Result> {
    /// The method called to dereference a value
    fn deref<'a>(&'a self) -> &'a Result;
}

/**
 *
 * The `DerefMut` trait is used to specify the functionality of dereferencing
 * mutably like `*v = 1;`
 *
 * # Example
 *
 * A struct with a single field which is modifiable via dereferencing the
 * struct.
 *
 * ```
 * struct DerefMutExample<T> {
 *     value: T
 * }
 *
 * impl<T> Deref<T> for DerefMutExample<T> {
 *     fn deref<'a>(&'a self) -> &'a T {
 *         &self.value
 *     }
 * }
 *
 * impl<T> DerefMut<T> for DerefMutExample<T> {
 *     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
 *         &mut self.value
 *     }
 * }
 *
 * fn main() {
 *     let mut x = DerefMutExample { value: 'a' };
 *     *x = 'b';
 *     assert_eq!('b', *x);
 * }
 * ```
 */
#[lang="deref_mut"]
pub trait DerefMut<Result>: Deref<Result> {
    /// The method called to mutably dereference a value
    fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
}

#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::Bencher;
    use ops::Drop;

    // Overhead of dtors

    struct HasDtor {
        x: int
    }

    impl Drop for HasDtor {
        fn drop(&mut self) {
        }
    }

    #[bench]
    fn alloc_obj_with_dtor(b: &mut Bencher) {
        b.iter(|| {
            HasDtor { x : 10 };
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

//! This module implements the check that the lifetime of a borrow
//! does not exceed the lifetime of the value being borrowed.

use core::prelude::*;
use middle::borrowck::*;
use mc = middle::mem_categorization;
use middle::ty;
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast;
use syntax::codemap::span;
use util::ppaux::{note_and_explain_region};

pub fn guarantee_lifetime(bccx: @BorrowckCtxt,
                          item_scope_id: ast::node_id,
                          root_scope_id: ast::node_id,
                          span: span,
                          cmt: mc::cmt,
                          loan_region: ty::Region,
                          loan_mutbl: ast::mutability) {
    debug!("guarantee_lifetime(cmt=%s, loan_region=%s)",
           cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
    let ctxt = GuaranteeLifetimeContext {bccx: bccx,
                                         item_scope_id: item_scope_id,
                                         span: span,
                                         loan_region: loan_region,
                                         loan_mutbl: loan_mutbl,
                                         cmt_original: cmt,
                                         root_scope_id: root_scope_id};
    ctxt.check(cmt, None);
}

///////////////////////////////////////////////////////////////////////////
// Private

struct GuaranteeLifetimeContext {
    bccx: @BorrowckCtxt,

    // the node id of the function body for the enclosing item
    item_scope_id: ast::node_id,

    // the node id of the innermost loop / function body; this is the
    // longest scope for which we can root managed boxes
    root_scope_id: ast::node_id,

    span: span,
    loan_region: ty::Region,
    loan_mutbl: ast::mutability,
    cmt_original: mc::cmt
}

impl GuaranteeLifetimeContext {
    fn tcx(&self) -> ty::ctxt {
        self.bccx.tcx
    }

    fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::node_id>) {
        //! Main routine. Walks down `cmt` until we find the "guarantor".

        match cmt.cat {
            mc::cat_rvalue |
            mc::cat_implicit_self |
            mc::cat_copied_upvar(*) |
            mc::cat_local(*) |
            mc::cat_arg(*) |
            mc::cat_self(*) |
            mc::cat_deref(_, _, mc::region_ptr(*)) |
            mc::cat_deref(_, _, mc::unsafe_ptr) => {
                let scope = self.scope(cmt);
                self.check_scope(scope)
            }

            mc::cat_stack_upvar(cmt) => {
                self.check(cmt, discr_scope)
            }

            mc::cat_static_item => {
            }

            mc::cat_deref(base, derefs, mc::gc_ptr(ptr_mutbl)) => {
                let base_scope = self.scope(base);

                // See rule Freeze-Imm-Managed-Ptr-2 in doc.rs
                let omit_root = (
                    ptr_mutbl == m_imm &&
                    self.bccx.is_subregion_of(self.loan_region, base_scope) &&
                    self.is_rvalue_or_immutable(base) &&
                    !self.is_moved(base)
                );

                if !omit_root {
                    self.check_root(cmt, base, derefs, ptr_mutbl, discr_scope);
                } else {
                    debug!("omitting root, base=%s, base_scope=%?",
                           base.repr(self.tcx()), base_scope);
                }
            }

            mc::cat_deref(base, _, mc::uniq_ptr(*)) |
            mc::cat_interior(base, _) => {
                self.check(base, discr_scope)
            }

            mc::cat_discr(base, new_discr_scope) => {
                // Subtle: in a match, we must ensure that each binding
                // variable remains valid for the duration of the arm in
                // which it appears, presuming that this arm is taken.
                // But it is inconvenient in trans to root something just
                // for one arm.  Therefore, we insert a cat_discr(),
                // basically a special kind of category that says "if this
                // value must be dynamically rooted, root it for the scope
                // `match_id`.
                //
                // As an example, consider this scenario:
                //
                //    let mut x = @Some(3);
                //    match *x { Some(y) {...} None {...} }
                //
                // Technically, the value `x` need only be rooted
                // in the `some` arm.  However, we evaluate `x` in trans
                // before we know what arm will be taken, so we just
                // always root it for the duration of the match.
                //
                // As a second example, consider *this* scenario:
                //
                //    let x = @mut @Some(3);
                //    match x { @@Some(y) {...} @@None {...} }
                //
                // Here again, `x` need only be rooted in the `some` arm.
                // In this case, the value which needs to be rooted is
                // found only when checking which pattern matches: but
                // this check is done before entering the arm.  Therefore,
                // even in this case we just choose to keep the value
                // rooted for the entire match.  This means the value will be
                // rooted even if the none arm is taken.  Oh well.
                //
                // At first, I tried to optimize the second case to only
                // root in one arm, but the result was suboptimal: first,
                // it interfered with the construction of phi nodes in the
                // arm, as we were adding code to root values before the
                // phi nodes were added.  This could have been addressed
                // with a second basic block.  However, the naive approach
                // also yielded suboptimal results for patterns like:
                //
                //    let x = @mut @...;
                //    match x { @@some_variant(y) | @@some_other_variant(y) =>
                //
                // The reason is that we would root the value once for
                // each pattern and not once per arm.  This is also easily
                // fixed, but it's yet more code for what is really quite
                // the corner case.
                //
                // Nonetheless, if you decide to optimize this case in the
                // future, you need only adjust where the cat_discr()
                // node appears to draw the line between what will be rooted
                // in the *arm* vs the *match*.
                self.check(base, Some(new_discr_scope))
            }
        }
    }

    fn is_rvalue_or_immutable(&self,
                              cmt: mc::cmt) -> bool {
        //! We can omit the root on an `@T` value if the location
        //! that holds the box is either (1) an rvalue, in which case
        //! is is in a non-user-accessible temporary, or (2) an immutable
        //! lvalue.

        cmt.mutbl.is_immutable() || match cmt.guarantor().cat {
            mc::cat_rvalue => true,
            _ => false
        }
    }

    fn check_root(&self,
                  cmt_deref: mc::cmt,
                  cmt_base: mc::cmt,
                  derefs: uint,
                  ptr_mutbl: ast::mutability,
                  discr_scope: Option<ast::node_id>) {
        debug!("check_root(cmt_deref=%s, cmt_base=%s, derefs=%?, ptr_mutbl=%?, \
                discr_scope=%?)",
               cmt_deref.repr(self.tcx()),
               cmt_base.repr(self.tcx()),
               derefs,
               ptr_mutbl,
               discr_scope);

        // Make sure that the loan does not exceed the maximum time
        // that we can root the value, dynamically.
        let root_region = ty::re_scope(self.root_scope_id);
        if !self.bccx.is_subregion_of(self.loan_region, root_region) {
            self.report_error(
                err_out_of_root_scope(root_region, self.loan_region));
            return;
        }

        // Extract the scope id that indicates how long the rooting is required
        let root_scope = match self.loan_region {
            ty::re_scope(id) => id,
            _ => {
                // the check above should fail for anything is not re_scope
                self.bccx.tcx.sess.span_bug(
                    cmt_base.span,
                    fmt!("Cannot issue root for scope region: %?",
                         self.loan_region));
            }
        };

        // If inside of a match arm, expand the rooting to the entire
        // match. See the detailed discussion in `check()` above.
        let mut root_scope = match discr_scope {
            None => root_scope,
            Some(id) => {
                if self.bccx.is_subscope_of(root_scope, id) {
                    id
                } else {
                    root_scope
                }
            }
        };

        // If we are borrowing the inside of an `@mut` box,
        // we need to dynamically mark it to prevent incompatible
        // borrows from happening later.
        let opt_dyna = match ptr_mutbl {
            m_imm | m_const => None,
            m_mutbl => {
                match self.loan_mutbl {
                    m_mutbl => Some(DynaMut),
                    m_imm | m_const => Some(DynaImm)
                }
            }
        };

        // FIXME(#3511) grow to the nearest cleanup scope---this can
        // cause observable errors if freezing!
        if !self.bccx.tcx.region_maps.is_cleanup_scope(root_scope) {
            debug!("%? is not a cleanup scope, adjusting", root_scope);

            let cleanup_scope =
                self.bccx.tcx.region_maps.cleanup_scope(root_scope);

            if opt_dyna.is_some() {
                self.tcx().sess.span_warn(
                    self.span,
                    fmt!("Dynamic freeze scope artifically extended \
                          (see Issue #6248)"));
                note_and_explain_region(
                    self.bccx.tcx,
                    "managed value only needs to be frozen for ",
                    ty::re_scope(root_scope),
                    "...");
                note_and_explain_region(
                    self.bccx.tcx,
                    "...but due to Issue #6248, it will be frozen for ",
                    ty::re_scope(cleanup_scope),
                    "");
            }

            root_scope = cleanup_scope;
        }

        // Add a record of what is required
        let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
        let root_info = RootInfo {scope: root_scope, freeze: opt_dyna};
        self.bccx.root_map.insert(rm_key, root_info);

        debug!("root_key: %? root_info: %?", rm_key, root_info);
    }

    fn check_scope(&self, max_scope: ty::Region) {
        //! Reports an error if `loan_region` is larger than `valid_scope`

        if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
            self.report_error(err_out_of_scope(max_scope, self.loan_region));
        }
    }

    fn is_moved(&self, cmt: mc::cmt) -> bool {
        //! True if `cmt` is something that is potentially moved
        //! out of the current stack frame.

        match cmt.guarantor().cat {
            mc::cat_local(id) |
            mc::cat_self(id) |
            mc::cat_arg(id) => {
                self.bccx.moved_variables_set.contains(&id)
            }
            mc::cat_rvalue |
            mc::cat_static_item |
            mc::cat_implicit_self |
            mc::cat_copied_upvar(*) |
            mc::cat_deref(*) => {
                false
            }
            r @ mc::cat_interior(*) |
            r @ mc::cat_stack_upvar(*) |
            r @ mc::cat_discr(*) => {
                self.tcx().sess.span_bug(
                    cmt.span,
                    fmt!("illegal guarantor category: %?", r));
            }
        }
    }

    fn scope(&self, cmt: mc::cmt) -> ty::Region {
        //! Returns the maximal region scope for the which the
        //! lvalue `cmt` is guaranteed to be valid without any
        //! rooting etc, and presuming `cmt` is not mutated.

        match cmt.cat {
            mc::cat_rvalue => {
                ty::re_scope(self.bccx.tcx.region_maps.cleanup_scope(cmt.id))
            }
            mc::cat_implicit_self |
            mc::cat_copied_upvar(_) => {
                ty::re_scope(self.item_scope_id)
            }
            mc::cat_static_item => {
                ty::re_static
            }
            mc::cat_local(local_id) |
            mc::cat_arg(local_id) |
            mc::cat_self(local_id) => {
                self.bccx.tcx.region_maps.encl_region(local_id)
            }
            mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
                ty::re_static
            }
            mc::cat_deref(_, _, mc::region_ptr(_, r)) => {
                r
            }
            mc::cat_deref(cmt, _, mc::uniq_ptr(*)) |
            mc::cat_deref(cmt, _, mc::gc_ptr(*)) |
            mc::cat_interior(cmt, _) |
            mc::cat_stack_upvar(cmt) |
            mc::cat_discr(cmt, _) => {
                self.scope(cmt)
            }
        }
    }

    fn report_error(&self, code: bckerr_code) {
        self.bccx.report(BckError {
            cmt: self.cmt_original,
            span: self.span,
            code: code
        });
    }
}
<commit_msg>correct typo<commit_after>// Copyright 2012 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.

//! This module implements the check that the lifetime of a borrow
//! does not exceed the lifetime of the value being borrowed.

use core::prelude::*;
use middle::borrowck::*;
use mc = middle::mem_categorization;
use middle::ty;
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast;
use syntax::codemap::span;
use util::ppaux::{note_and_explain_region};

pub fn guarantee_lifetime(bccx: @BorrowckCtxt,
                          item_scope_id: ast::node_id,
                          root_scope_id: ast::node_id,
                          span: span,
                          cmt: mc::cmt,
                          loan_region: ty::Region,
                          loan_mutbl: ast::mutability) {
    debug!("guarantee_lifetime(cmt=%s, loan_region=%s)",
           cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
    let ctxt = GuaranteeLifetimeContext {bccx: bccx,
                                         item_scope_id: item_scope_id,
                                         span: span,
                                         loan_region: loan_region,
                                         loan_mutbl: loan_mutbl,
                                         cmt_original: cmt,
                                         root_scope_id: root_scope_id};
    ctxt.check(cmt, None);
}

///////////////////////////////////////////////////////////////////////////
// Private

struct GuaranteeLifetimeContext {
    bccx: @BorrowckCtxt,

    // the node id of the function body for the enclosing item
    item_scope_id: ast::node_id,

    // the node id of the innermost loop / function body; this is the
    // longest scope for which we can root managed boxes
    root_scope_id: ast::node_id,

    span: span,
    loan_region: ty::Region,
    loan_mutbl: ast::mutability,
    cmt_original: mc::cmt
}

impl GuaranteeLifetimeContext {
    fn tcx(&self) -> ty::ctxt {
        self.bccx.tcx
    }

    fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::node_id>) {
        //! Main routine. Walks down `cmt` until we find the "guarantor".

        match cmt.cat {
            mc::cat_rvalue |
            mc::cat_implicit_self |
            mc::cat_copied_upvar(*) |
            mc::cat_local(*) |
            mc::cat_arg(*) |
            mc::cat_self(*) |
            mc::cat_deref(_, _, mc::region_ptr(*)) |
            mc::cat_deref(_, _, mc::unsafe_ptr) => {
                let scope = self.scope(cmt);
                self.check_scope(scope)
            }

            mc::cat_stack_upvar(cmt) => {
                self.check(cmt, discr_scope)
            }

            mc::cat_static_item => {
            }

            mc::cat_deref(base, derefs, mc::gc_ptr(ptr_mutbl)) => {
                let base_scope = self.scope(base);

                // See rule Freeze-Imm-Managed-Ptr-2 in doc.rs
                let omit_root = (
                    ptr_mutbl == m_imm &&
                    self.bccx.is_subregion_of(self.loan_region, base_scope) &&
                    self.is_rvalue_or_immutable(base) &&
                    !self.is_moved(base)
                );

                if !omit_root {
                    self.check_root(cmt, base, derefs, ptr_mutbl, discr_scope);
                } else {
                    debug!("omitting root, base=%s, base_scope=%?",
                           base.repr(self.tcx()), base_scope);
                }
            }

            mc::cat_deref(base, _, mc::uniq_ptr(*)) |
            mc::cat_interior(base, _) => {
                self.check(base, discr_scope)
            }

            mc::cat_discr(base, new_discr_scope) => {
                // Subtle: in a match, we must ensure that each binding
                // variable remains valid for the duration of the arm in
                // which it appears, presuming that this arm is taken.
                // But it is inconvenient in trans to root something just
                // for one arm.  Therefore, we insert a cat_discr(),
                // basically a special kind of category that says "if this
                // value must be dynamically rooted, root it for the scope
                // `match_id`.
                //
                // As an example, consider this scenario:
                //
                //    let mut x = @Some(3);
                //    match *x { Some(y) {...} None {...} }
                //
                // Technically, the value `x` need only be rooted
                // in the `some` arm.  However, we evaluate `x` in trans
                // before we know what arm will be taken, so we just
                // always root it for the duration of the match.
                //
                // As a second example, consider *this* scenario:
                //
                //    let x = @mut @Some(3);
                //    match x { @@Some(y) {...} @@None {...} }
                //
                // Here again, `x` need only be rooted in the `some` arm.
                // In this case, the value which needs to be rooted is
                // found only when checking which pattern matches: but
                // this check is done before entering the arm.  Therefore,
                // even in this case we just choose to keep the value
                // rooted for the entire match.  This means the value will be
                // rooted even if the none arm is taken.  Oh well.
                //
                // At first, I tried to optimize the second case to only
                // root in one arm, but the result was suboptimal: first,
                // it interfered with the construction of phi nodes in the
                // arm, as we were adding code to root values before the
                // phi nodes were added.  This could have been addressed
                // with a second basic block.  However, the naive approach
                // also yielded suboptimal results for patterns like:
                //
                //    let x = @mut @...;
                //    match x { @@some_variant(y) | @@some_other_variant(y) =>
                //
                // The reason is that we would root the value once for
                // each pattern and not once per arm.  This is also easily
                // fixed, but it's yet more code for what is really quite
                // the corner case.
                //
                // Nonetheless, if you decide to optimize this case in the
                // future, you need only adjust where the cat_discr()
                // node appears to draw the line between what will be rooted
                // in the *arm* vs the *match*.
                self.check(base, Some(new_discr_scope))
            }
        }
    }

    fn is_rvalue_or_immutable(&self,
                              cmt: mc::cmt) -> bool {
        //! We can omit the root on an `@T` value if the location
        //! that holds the box is either (1) an rvalue, in which case
        //! it is in a non-user-accessible temporary, or (2) an immutable
        //! lvalue.

        cmt.mutbl.is_immutable() || match cmt.guarantor().cat {
            mc::cat_rvalue => true,
            _ => false
        }
    }

    fn check_root(&self,
                  cmt_deref: mc::cmt,
                  cmt_base: mc::cmt,
                  derefs: uint,
                  ptr_mutbl: ast::mutability,
                  discr_scope: Option<ast::node_id>) {
        debug!("check_root(cmt_deref=%s, cmt_base=%s, derefs=%?, ptr_mutbl=%?, \
                discr_scope=%?)",
               cmt_deref.repr(self.tcx()),
               cmt_base.repr(self.tcx()),
               derefs,
               ptr_mutbl,
               discr_scope);

        // Make sure that the loan does not exceed the maximum time
        // that we can root the value, dynamically.
        let root_region = ty::re_scope(self.root_scope_id);
        if !self.bccx.is_subregion_of(self.loan_region, root_region) {
            self.report_error(
                err_out_of_root_scope(root_region, self.loan_region));
            return;
        }

        // Extract the scope id that indicates how long the rooting is required
        let root_scope = match self.loan_region {
            ty::re_scope(id) => id,
            _ => {
                // the check above should fail for anything is not re_scope
                self.bccx.tcx.sess.span_bug(
                    cmt_base.span,
                    fmt!("Cannot issue root for scope region: %?",
                         self.loan_region));
            }
        };

        // If inside of a match arm, expand the rooting to the entire
        // match. See the detailed discussion in `check()` above.
        let mut root_scope = match discr_scope {
            None => root_scope,
            Some(id) => {
                if self.bccx.is_subscope_of(root_scope, id) {
                    id
                } else {
                    root_scope
                }
            }
        };

        // If we are borrowing the inside of an `@mut` box,
        // we need to dynamically mark it to prevent incompatible
        // borrows from happening later.
        let opt_dyna = match ptr_mutbl {
            m_imm | m_const => None,
            m_mutbl => {
                match self.loan_mutbl {
                    m_mutbl => Some(DynaMut),
                    m_imm | m_const => Some(DynaImm)
                }
            }
        };

        // FIXME(#3511) grow to the nearest cleanup scope---this can
        // cause observable errors if freezing!
        if !self.bccx.tcx.region_maps.is_cleanup_scope(root_scope) {
            debug!("%? is not a cleanup scope, adjusting", root_scope);

            let cleanup_scope =
                self.bccx.tcx.region_maps.cleanup_scope(root_scope);

            if opt_dyna.is_some() {
                self.tcx().sess.span_warn(
                    self.span,
                    fmt!("Dynamic freeze scope artifically extended \
                          (see Issue #6248)"));
                note_and_explain_region(
                    self.bccx.tcx,
                    "managed value only needs to be frozen for ",
                    ty::re_scope(root_scope),
                    "...");
                note_and_explain_region(
                    self.bccx.tcx,
                    "...but due to Issue #6248, it will be frozen for ",
                    ty::re_scope(cleanup_scope),
                    "");
            }

            root_scope = cleanup_scope;
        }

        // Add a record of what is required
        let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
        let root_info = RootInfo {scope: root_scope, freeze: opt_dyna};
        self.bccx.root_map.insert(rm_key, root_info);

        debug!("root_key: %? root_info: %?", rm_key, root_info);
    }

    fn check_scope(&self, max_scope: ty::Region) {
        //! Reports an error if `loan_region` is larger than `valid_scope`

        if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
            self.report_error(err_out_of_scope(max_scope, self.loan_region));
        }
    }

    fn is_moved(&self, cmt: mc::cmt) -> bool {
        //! True if `cmt` is something that is potentially moved
        //! out of the current stack frame.

        match cmt.guarantor().cat {
            mc::cat_local(id) |
            mc::cat_self(id) |
            mc::cat_arg(id) => {
                self.bccx.moved_variables_set.contains(&id)
            }
            mc::cat_rvalue |
            mc::cat_static_item |
            mc::cat_implicit_self |
            mc::cat_copied_upvar(*) |
            mc::cat_deref(*) => {
                false
            }
            r @ mc::cat_interior(*) |
            r @ mc::cat_stack_upvar(*) |
            r @ mc::cat_discr(*) => {
                self.tcx().sess.span_bug(
                    cmt.span,
                    fmt!("illegal guarantor category: %?", r));
            }
        }
    }

    fn scope(&self, cmt: mc::cmt) -> ty::Region {
        //! Returns the maximal region scope for the which the
        //! lvalue `cmt` is guaranteed to be valid without any
        //! rooting etc, and presuming `cmt` is not mutated.

        match cmt.cat {
            mc::cat_rvalue => {
                ty::re_scope(self.bccx.tcx.region_maps.cleanup_scope(cmt.id))
            }
            mc::cat_implicit_self |
            mc::cat_copied_upvar(_) => {
                ty::re_scope(self.item_scope_id)
            }
            mc::cat_static_item => {
                ty::re_static
            }
            mc::cat_local(local_id) |
            mc::cat_arg(local_id) |
            mc::cat_self(local_id) => {
                self.bccx.tcx.region_maps.encl_region(local_id)
            }
            mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
                ty::re_static
            }
            mc::cat_deref(_, _, mc::region_ptr(_, r)) => {
                r
            }
            mc::cat_deref(cmt, _, mc::uniq_ptr(*)) |
            mc::cat_deref(cmt, _, mc::gc_ptr(*)) |
            mc::cat_interior(cmt, _) |
            mc::cat_stack_upvar(cmt) |
            mc::cat_discr(cmt, _) => {
                self.scope(cmt)
            }
        }
    }

    fn report_error(&self, code: bckerr_code) {
        self.bccx.report(BckError {
            cmt: self.cmt_original,
            span: self.span,
            code: code
        });
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

//! Boolean logic

#[cfg(not(test))]
use cmp::{Eq, Ord, TotalOrd, Ordering};
use option::{None, Option, Some};
use from_str::FromStr;

/// Negation / inverse
pub fn not(v: bool) -> bool { !v }

/// Conjunction
pub fn and(a: bool, b: bool) -> bool { a && b }

/// Disjunction
pub fn or(a: bool, b: bool) -> bool { a || b }

/**
 * Exclusive or
 *
 * Identical to `or(and(a, not(b)), and(not(a), b))`
 */
pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }

/// Implication in the logic, i.e. from `a` follows `b`
pub fn implies(a: bool, b: bool) -> bool { !a || b }

/// true if truth values `a` and `b` are indistinguishable in the logic
pub fn eq(a: bool, b: bool) -> bool { a == b }

/// true if truth values `a` and `b` are distinguishable in the logic
pub fn ne(a: bool, b: bool) -> bool { a != b }

/// true if `v` represents truth in the logic
pub fn is_true(v: bool) -> bool { v }

/// true if `v` represents falsehood in the logic
pub fn is_false(v: bool) -> bool { !v }

/// Parse logic value from `s`
impl FromStr for bool {
    fn from_str(s: &str) -> Option<bool> {
        match s {
            "true"  => Some(true),
            "false" => Some(false),
            _       => None,
        }
    }
}

/// Convert `v` into a string
pub fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }

/**
 * Iterates over all truth values by passing them to `blk` in an unspecified
 * order
 */
pub fn all_values(blk: &fn(v: bool)) {
    blk(true);
    blk(false);
}

/// converts truth value to an 8 bit byte
#[inline(always)]
pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }

#[cfg(not(test))]
impl Ord for bool {
    #[inline(always)]
    fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
    #[inline(always)]
    fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
    #[inline(always)]
    fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
    #[inline(always)]
    fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
}

#[cfg(not(test))]
impl TotalOrd for bool {
    #[inline(always)]
    fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) }
}

#[cfg(not(test))]
impl Eq for bool {
    #[inline(always)]
    fn eq(&self, other: &bool) -> bool { (*self) == (*other) }
    #[inline(always)]
    fn ne(&self, other: &bool) -> bool { (*self) != (*other) }
}

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

    #[test]
    fn test_bool_from_str() {
        do all_values |v| {
            assert!(Some(v) == FromStr::from_str(to_str(v)))
        }
    }

    #[test]
    fn test_bool_to_str() {
        assert_eq!(to_str(false), ~"false");
        assert_eq!(to_str(true), ~"true");
    }

    #[test]
    fn test_bool_to_bit() {
        do all_values |v| {
            assert_eq!(to_bit(v), if is_true(v) { 1u8 } else { 0u8 });
        }
    }

    #[test]
    fn test_bool_ord() {
        assert!(true > false);
        assert!(!(false > true));

        assert!(false < true);
        assert!(!(true < false));

        assert!(false <= false);
        assert!(false >= false);
        assert!(true <= true);
        assert!(true >= true);

        assert!(false <= true);
        assert!(!(false >= true));
        assert!(true >= false);
        assert!(!(true <= false));
    }

    #[test]
    fn test_bool_totalord() {
        assert_eq!(true.cmp(&true), Equal);
        assert_eq!(false.cmp(&false), Equal);
        assert_eq!(true.cmp(&false), Greater);
        assert_eq!(false.cmp(&true), Less);
    }
}
<commit_msg>Add documentation for libstd/bool.rs.<commit_after>// Copyright 2012 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.

/*!

The `bool` module contains useful code to help work with boolean values.

A quick summary:

## Trait implementations for `bool`

Implementations of the following traits:

* `FromStr`
* `Ord`
* `TotalOrd`
* `Eq`

## Various functions to compare `bool`s

All of the standard comparison functions one would expect: `and`, `eq`, `or`,
and more.

Also, a few conversion functions: `to_bit` and `to_str`.

Finally, some inquries into the nature of truth: `is_true` and `is_false`.

*/

#[cfg(not(test))]
use cmp::{Eq, Ord, TotalOrd, Ordering};
use option::{None, Option, Some};
use from_str::FromStr;

/**
* Negation of a boolean value.
*
* # Examples
* ~~~
* rusti> core::bool::not(true)
* false
* ~~~
* rusti> core::bool::not(false)
* true
* ~~~
*/
pub fn not(v: bool) -> bool { !v }

/**
* Conjunction of two boolean values.
*
* # Examples
* ~~~
* rusti> core::bool::and(true, false)
* false
* ~~~
* rusti> core::bool::and(true, true)
* true
* ~~~
*/
pub fn and(a: bool, b: bool) -> bool { a && b }

/**
* Disjunction of two boolean values.
*
* # Examples
* ~~~
* rusti> core::bool::or(true, false)
* true
* ~~~
* rusti> core::bool::or(false, false)
* false
* ~~~
*/
pub fn or(a: bool, b: bool) -> bool { a || b }

/**
* An 'exclusive or' of two boolean values.
*
* 'exclusive or' is identical to `or(and(a, not(b)), and(not(a), b))`.
*
* # Examples
* ~~~
* rusti> core::bool::xor(true, false)
* true
* ~~~
* rusti> core::bool::xor(true, true)
* false
* ~~~
*/
pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }

/**
* Implication between two boolean values.
*
* Implication is often phrased as 'if a then b.'
*
* 'if a then b' is equivalent to `!a || b`.
*
* # Examples
* ~~~
* rusti> core::bool::implies(true, true)
* true
* ~~~
* rusti> core::bool::implies(true, false)
* false
* ~~~
*/
pub fn implies(a: bool, b: bool) -> bool { !a || b }

/**
* Equality between two boolean values.
*
* Two booleans are equal if they have the same value.
*
* # Examples
* ~~~
* rusti> core::bool::eq(false, true)
* false
* ~~~
* rusti> core::bool::eq(false, false)
* true
* ~~~
*/
pub fn eq(a: bool, b: bool) -> bool { a == b }

/**
* Non-equality between two boolean values.
*
* Two booleans are not equal if they have different values.
*
* # Examples
* ~~~
* rusti> core::bool::ne(false, true)
* true
* ~~~
* rusti> core::bool::ne(false, false)
* false
* ~~~
*/
pub fn ne(a: bool, b: bool) -> bool { a != b }

/**
* Is a given boolean value true?
*
* # Examples
* ~~~
* rusti> core::bool::is_true(true)
* true
* ~~~
* rusti> core::bool::is_true(false)
* false
* ~~~
*/
pub fn is_true(v: bool) -> bool { v }

/**
* Is a given boolean value false?
*
* # Examples
* ~~~
* rusti> core::bool::is_false(false)
* true
* ~~~
* rusti> core::bool::is_false(true)
* false
* ~~~
*/
pub fn is_false(v: bool) -> bool { !v }

/**
* Parse a `bool` from a `str`.
*
* Yields an `Option<bool>`, because `str` may or may not actually be parseable.
*
* # Examples
* ~~~
* rusti> FromStr::from_str::<bool>("true")
* Some(true)
* ~~~
* rusti> FromStr::from_str::<bool>("false")
* Some(false)
* ~~~
* rusti> FromStr::from_str::<bool>("not even a boolean")
* None
* ~~~
*/
impl FromStr for bool {
    fn from_str(s: &str) -> Option<bool> {
        match s {
            "true"  => Some(true),
            "false" => Some(false),
            _       => None,
        }
    }
}

/**
* Convert a `bool` to a `str`.
*
* # Examples
* ~~~
* rusti> std::bool::to_str(true)
* "true"
* ~~~
* rusti> std::bool::to_str(false)
* "false"
* ~~~
*/
pub fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }

/**
* Iterates over all truth values, passing them to the given block.
*
* There are no guarantees about the order values will be given.
*
* # Examples
* ~~~
* do core::bool::all_values |x: bool| {
*     println(core::bool::to_str(x));
* }
* ~~~
*/
pub fn all_values(blk: &fn(v: bool)) {
    blk(true);
    blk(false);
}

/**
* Convert a `bool` to a `u8`.
*
* # Examples
* ~~~
* rusti> std::bool::to_bit(true)
* 1
* ~~~
* rusti> std::bool::to_bit(false)
* 0
* ~~~
*/
#[inline(always)]
pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }

#[cfg(not(test))]
impl Ord for bool {
    #[inline(always)]
    fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
    #[inline(always)]
    fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
    #[inline(always)]
    fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
    #[inline(always)]
    fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
}

#[cfg(not(test))]
impl TotalOrd for bool {
    #[inline(always)]
    fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) }
}

#[cfg(not(test))]
impl Eq for bool {
    #[inline(always)]
    fn eq(&self, other: &bool) -> bool { (*self) == (*other) }
    #[inline(always)]
    fn ne(&self, other: &bool) -> bool { (*self) != (*other) }
}

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

    #[test]
    fn test_bool_from_str() {
        do all_values |v| {
            assert!(Some(v) == FromStr::from_str(to_str(v)))
        }
    }

    #[test]
    fn test_bool_to_str() {
        assert_eq!(to_str(false), ~"false");
        assert_eq!(to_str(true), ~"true");
    }

    #[test]
    fn test_bool_to_bit() {
        do all_values |v| {
            assert_eq!(to_bit(v), if is_true(v) { 1u8 } else { 0u8 });
        }
    }

    #[test]
    fn test_bool_ord() {
        assert!(true > false);
        assert!(!(false > true));

        assert!(false < true);
        assert!(!(true < false));

        assert!(false <= false);
        assert!(false >= false);
        assert!(true <= true);
        assert!(true >= true);

        assert!(false <= true);
        assert!(!(false >= true));
        assert!(true >= false);
        assert!(!(true <= false));
    }

    #[test]
    fn test_bool_totalord() {
        assert_eq!(true.cmp(&true), Equal);
        assert_eq!(false.cmp(&false), Equal);
        assert_eq!(true.cmp(&false), Greater);
        assert_eq!(false.cmp(&true), Less);
    }
}
<|endoftext|>