<commit_before>use cmp::{ Ord, Eq };
use bounded::{ Bounded, max_value, min_value };

pub trait Monoid {
    static pure fn mempty() -> self;
    pure fn mappend(&self, other: &self) -> self;
}

pub struct Sum<T> { repr: T }
pub pure fn Sum<T>(val: T) -> Sum<T> { Sum { repr: val } }

impl<T: Num> Sum<T> : Monoid {
    static pure fn mempty() -> Sum<T> { Sum(num::from_int(0)) }
    pure fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum(self.repr.add(other.repr)) }
}

impl<T: cmp::Eq> Sum<T> : cmp::Eq {
    pure fn eq(other: &Sum<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Sum<T>) -> bool { self.repr != other.repr }
}

pub struct Prod<T> { repr: T }
pub pure fn Prod<T>(val: T) -> Prod<T> { Prod { repr: val }}

impl<T: Num> Prod<T> : Monoid {
    static pure fn mempty() -> Prod<T> { Prod(num::from_int(1)) }
    pure fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod(self.repr.mul(other.repr)) }
}

impl<T: cmp::Eq> Prod<T> : cmp::Eq {
    pure fn eq(other: &Prod<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Prod<T>) -> bool { self.repr != other.repr }
}

pub struct Max<T> { repr: T }
pub pure fn Max<T>(val: T) -> Max<T> { Max{ repr: val } }

impl<T: Copy Bounded Ord> Max<T> : Monoid {
    static pure fn mempty() -> Max<T> { Max(min_value()) }
    pure fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr < other.repr { *other } else { *self }
    }
}

impl<T: Eq> Max<T> : Eq {
    pure fn eq(other: &Max<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Max<T>) -> bool { self.repr != other.repr }
}

pub struct Min<T> { repr: T }
pub pure fn Min<T>(val: T) -> Min<T> { Min { repr: val } }

impl<T: Copy Bounded Ord> Min<T> : Monoid {
    static pure fn mempty() -> Min<T> { Min(max_value()) }
    pure fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr > other.repr { *other } else { *self }
    }
}

impl<T: Eq> Min<T> : Eq {
    pure fn eq(other: &Min<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Min<T>) -> bool { self.repr != other.repr }
}

pub fn mconcat<T: Copy Monoid>(v: &[T]) -> T {
    vec::foldl(mempty(), v, |accum, elt| { elt.mappend(&accum) })
}

pub fn merge<T: Copy Ord, M: Copy Monoid>(vec1: &[(T, M)], vec2: &[(T, M)]) -> ~[(T, M)] {
    let mut result = ~[];
    let mut (itr1, itr2) = (vec1, vec2);
    while (itr1.is_not_empty() && itr2.is_not_empty()) {
        let ((v1, m1), (v2, m2)) = (itr1.head(), itr2.head());
        if v1 < v2 {
            vec::push(result, (v1, m1));
            itr1 = vec::view(itr1, 1u, itr1.len());
            loop;
        }
        if v2 < v1 {
            vec::push(result, (v2, m2));
            itr2 = vec::view(itr2, 1u, itr2.len());
            loop;
        }
        vec::push(result, (v1, m1.mappend(&m2)));
        itr1 = vec::view(itr1, 1u, itr1.len());
        itr2 = vec::view(itr2, 1u, itr2.len());
    }

    if itr1.is_not_empty() { result += itr1; }
    if itr2.is_not_empty() { result += itr2; }
    return result;
}

pub fn mergei<T: Copy Ord, M: Copy Monoid>(vecs: &[~[(T, M)]]) -> ~[(T, M)] {
    return match vecs.len() {
      0u => ~[],
      1u => ~[] + vecs[0],
      len  => {
        let pre  = mergei(vec::view(vecs, 0u, len / 2u));
        let post = mergei(vec::view(vecs, len / 2u, len));
        merge(pre, post)
      }
    }
}

#[cfg(test)]
mod tests {
    fn to_sum<T: Copy, U: Copy Num>(tp: &(T, U)) -> (T, Sum<U>) {
        let (t, u) = *tp;
        return (t, Sum(u));
    }

    fn to_max<T: Copy, U: Copy Ord>(tp: &(T, U)) -> (T, Max<U>) {
        let (t, u) = *tp;
        return (t, Max(u));
    }

    #[test]
    fn test_merge() {
        let arg1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let arg2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        {
            let result = [(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)].map(to_sum);
            assert merge(arg1.map(to_sum), arg2.map(to_sum)) == result;
        }

        {
            let result = [(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)].map(to_max);
            assert merge(arg1.map(to_max), arg2.map(to_max)) == result;
        }

        {
            let result = arg1.map(to_sum);
            assert merge(result, []) == result;
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert merge([], []) == result;
        }
    }

    #[test]
    fn test_mergei() {
        {
            let arg = [~[to_sum(&(1, 1)), to_sum(&(2, 1))], ~[to_sum(&(1, 2)), to_sum(&(3, 1))], ~[to_sum(&(-1, 3))]];
            let result = [(-1, 3), (1, 3), (2, 1), (3, 1)].map(to_sum);
            assert mergei(arg) == result;
        }

        {
            let arg = [~[to_sum(&(1, 1))], ~[to_sum(&(1, 2))], ~[to_sum(&(1, 3))]];
            let result: ~[(int, Sum<int>)] = ~[to_sum(&(1, 6))];
            assert mergei(arg) == result;
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert mergei([~[], ~[], ~[]]) == result;
        }
    }
}

<commit_msg>Add euler::monoid::{Unwrap, merge_as, mergei_as}<commit_after>use cmp::{ Ord, Eq };
use bounded::{ Bounded, max_value, min_value };

pub trait Monoid {
    static pure fn mempty() -> self;
    pure fn mappend(&self, other: &self) -> self;
}

pub trait Unwrap<T> {
    pure fn unwrap(&self) -> T;
}

pub struct Sum<T> { repr: T }
pub pure fn Sum<T>(val: T) -> Sum<T> { Sum { repr: val } }

impl<T: Num> Sum<T> : Monoid {
    static pure fn mempty() -> Sum<T> { Sum(num::from_int(0)) }
    pure fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum(self.repr.add(other.repr)) }
}

impl<T: Copy> Sum<T> : Unwrap<T> {
    pure fn unwrap(&self) -> T { self.repr }
}

impl<T: cmp::Eq> Sum<T> : cmp::Eq {
    pure fn eq(other: &Sum<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Sum<T>) -> bool { self.repr != other.repr }
}

pub struct Prod<T> { repr: T }
pub pure fn Prod<T>(val: T) -> Prod<T> { Prod { repr: val }}

impl<T: Num> Prod<T> : Monoid {
    static pure fn mempty() -> Prod<T> { Prod(num::from_int(1)) }
    pure fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod(self.repr.mul(other.repr)) }
}

impl<T: Copy> Prod<T> : Unwrap<T> {
    pure fn unwrap(&self) -> T { self.repr }
}

impl<T: cmp::Eq> Prod<T> : cmp::Eq {
    pure fn eq(other: &Prod<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Prod<T>) -> bool { self.repr != other.repr }
}

pub struct Max<T> { repr: T }
pub pure fn Max<T>(val: T) -> Max<T> { Max{ repr: val } }

impl<T: Copy Bounded Ord> Max<T> : Monoid {
    static pure fn mempty() -> Max<T> { Max(min_value()) }
    pure fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr < other.repr { *other } else { *self }
    }
}

impl<T: Copy> Max<T> : Unwrap<T> {
    pure fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Max<T> : Eq {
    pure fn eq(other: &Max<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Max<T>) -> bool { self.repr != other.repr }
}

pub struct Min<T> { repr: T }
pub pure fn Min<T>(val: T) -> Min<T> { Min { repr: val } }

impl<T: Copy Bounded Ord> Min<T> : Monoid {
    static pure fn mempty() -> Min<T> { Min(max_value()) }
    pure fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr > other.repr { *other } else { *self }
    }
}

impl<T: Copy> Min<T> : Unwrap<T> {
    pure fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Min<T> : Eq {
    pure fn eq(other: &Min<T>) -> bool { self.repr == other.repr }
    pure fn ne(other: &Min<T>) -> bool { self.repr != other.repr }
}

pub fn mconcat<T: Copy Monoid>(v: &[T]) -> T {
    vec::foldl(mempty(), v, |accum, elt| { elt.mappend(&accum) })
}

pub fn merge<T: Copy Ord, M: Copy Monoid>(vec1: &[(T, M)], vec2: &[(T, M)]) -> ~[(T, M)] {
    let mut result = ~[];
    let mut (itr1, itr2) = (vec1, vec2);
    while (itr1.is_not_empty() && itr2.is_not_empty()) {
        let ((v1, m1), (v2, m2)) = (itr1.head(), itr2.head());
        if v1 < v2 {
            vec::push(result, (v1, m1));
            itr1 = vec::view(itr1, 1u, itr1.len());
            loop;
        }
        if v2 < v1 {
            vec::push(result, (v2, m2));
            itr2 = vec::view(itr2, 1u, itr2.len());
            loop;
        }
        vec::push(result, (v1, m1.mappend(&m2)));
        itr1 = vec::view(itr1, 1u, itr1.len());
        itr2 = vec::view(itr2, 1u, itr2.len());
    }

    if itr1.is_not_empty() { result += itr1; }
    if itr2.is_not_empty() { result += itr2; }
    return result;
}

pub fn mergei<T: Copy Ord, M: Copy Monoid>(vecs: &[~[(T, M)]]) -> ~[(T, M)] {
    return match vecs.len() {
      0u => ~[],
      1u => ~[] + vecs[0],
      len  => {
        let pre  = mergei(vec::view(vecs, 0u, len / 2u));
        let post = mergei(vec::view(vecs, len / 2u, len));
        merge(pre, post)
      }
    }
}

pub fn merge_as<T: Copy Ord, U: Copy, MT, M: Copy Monoid Unwrap<MT>>
    (vec1: &[(T, U)], vec2: &[(T, U)], f: fn(U) -> M) -> ~[(T, MT)] {
    fn convert<T: Copy, U: Copy, M: Copy>(v: &[(T, U)], f: fn(U) -> M) -> ~[(T, M)] {
        do v.map |tp| { (tp.first(), f(tp.second())) }
    }
    return merge(convert(vec1, f), convert(vec2, f)).map(|tp| (tp.first(), tp.second().unwrap()));
}

pub fn mergei_as<T: Copy Ord, U: Copy, MT, M: Copy Monoid Unwrap<MT>>(vecs: &[~[(T, U)]], f: fn(U) -> M) -> ~[(T, MT)] {
    return mergei(
        vecs.map(|v| v.map(|tp| (tp.first(), f(tp.second()))))
    ).map(|tp| (tp.first(), tp.second().unwrap()));
}

#[cfg(test)]
mod tests {
    fn to_sum<T: Copy, U: Copy Num>(tp: &(T, U)) -> (T, Sum<U>) {
        let (t, u) = *tp;
        return (t, Sum(u));
    }

    fn to_max<T: Copy, U: Copy Ord>(tp: &(T, U)) -> (T, Max<U>) {
        let (t, u) = *tp;
        return (t, Max(u));
    }

    #[test]
    fn test_merge() {
        let arg1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let arg2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        {
            let result = ~[(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)];
            assert merge(arg1.map(to_sum), arg2.map(to_sum)) == result.map(to_sum);
            assert merge_as(arg1, arg2, Sum) == result;
        }

        {
            let result = ~[(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)];
            assert merge(arg1.map(to_max), arg2.map(to_max)) == result.map(to_max);
            assert merge_as(arg1, arg2, Max) == result;
        }

        {
            let result = arg1.map(to_sum);
            assert merge(result, []) == result;
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert merge([], []) == result;
        }
    }

    #[test]
    fn test_mergei() {
        {
            let arg = [~[(1, 1), (2, 1)], ~[(1, 2), (3, 1)], ~[(-1, 3)]];
            let result = ~[(-1, 3), (1, 3), (2, 1), (3, 1)];
            assert mergei(arg.map(|v| v.map(to_sum))) == result.map(to_sum);
            assert mergei_as(arg, Sum) == result;
        }

        {
            let arg = [~[(1, 1)], ~[(1, 2)], ~[(1, 3)]];
            let result = ~[(1, 6)];
            assert mergei(arg.map(|v| v.map(to_sum))) == result.map(to_sum);
            assert mergei_as(arg, Sum) == result;
        }

        {
            let arg = [~[], ~[], ~[]];
            let result: ~[(int, int)] = ~[];
            assert mergei(arg.map(|v| v.map(to_sum))) == result.map(to_sum);
            assert mergei_as(arg, Sum) == result;
        }
    }
}

<|endoftext|>


<commit_before>#[doc = "Random number generation"];

export rng, weighted, extensions;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_new() -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_int_from(start: int, end: int) -> int {
        assert start <= end;
        start + int::abs(self.gen_int() % (end - start + 1))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as u64
    }

    #[doc = "Return a uint randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_uint_from(start: uint, end: uint) -> uint {
        assert start <= end;
        start + (self.gen_uint() % (end - start + 1u))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "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))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "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_from(1u, n) == 1u
        }
    }

    #[doc = "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;
        }
        s
    }

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

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: [T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "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_from(0u, values.len() - 1u)])
        }
    }

    #[doc = "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()
    }

    #[doc = "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 {
            ret none;
        }
        let chosen = self.gen_uint_from(0u, total - 1u);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "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|
            uint::range(0u, item.weight) {|_i|
                r += [item.item];
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: [T]) -> [T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "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_from(0u, i));
        }
    }

}

#[doc = "Create a random number generator"]
fn rng() -> rng {
    resource rand_res(c: *rctx) { rustrt::rand_free(c); }

    impl of rng for @rand_res {
        fn next() -> u32 { ret rustrt::rand_next(**self); }
    }

    @rand_res(rustrt::rand_new()) as rng
}

#[cfg(test)]
mod tests {

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

    #[test]
    #[should_fail]
    fn gen_int_from_fail() {
        rand::rng().gen_int_from(5, -2);
    }

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

    #[test]
    #[should_fail]
    fn gen_uint_from_fail() {
        rand::rng().gen_uint_from(5u, 2u);
    }

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

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

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

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

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

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option([]) == none::<int>;
        assert r.choose_option([1, 1, 1]) == some(1);
    }

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

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option([{weight: 1u, item: 42}]) == some(42);
        assert r.choose_weighted_option([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option([]) == none::<int>;
    }

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

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

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>add a seeded random number generator so that sequences of random numbers can be easily reproduced (for https://github.com/mozilla/rust/issues/2379)<commit_after>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;

enum rctx {}

#[abi = "cdecl"]
native 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);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_int_from(start: int, end: int) -> int {
        assert start <= end;
        start + int::abs(self.gen_int() % (end - start + 1))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as u64
    }

    #[doc = "Return a uint randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_uint_from(start: uint, end: uint) -> uint {
        assert start <= end;
        start + (self.gen_uint() % (end - start + 1u))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "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))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "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_from(1u, n) == 1u
        }
    }

    #[doc = "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;
        }
        s
    }

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

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: [T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "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_from(0u, values.len() - 1u)])
        }
    }

    #[doc = "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()
    }

    #[doc = "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 {
            ret none;
        }
        let chosen = self.gen_uint_from(0u, total - 1u);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "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|
            uint::range(0u, item.weight) {|_i|
                r += [item.item];
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: [T]) -> [T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "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_from(0u, i));
        }
    }

}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next(**self); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> [u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: [u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

#[cfg(test)]
mod tests {

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

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

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

    #[test]
    #[should_fail]
    fn gen_int_from_fail() {
        rand::rng().gen_int_from(5, -2);
    }

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

    #[test]
    #[should_fail]
    fn gen_uint_from_fail() {
        rand::rng().gen_uint_from(5u, 2u);
    }

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

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

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

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

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

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option([]) == none::<int>;
        assert r.choose_option([1, 1, 1]) == some(1);
    }

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

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option([{weight: 1u, item: 42}]) == some(42);
        assert r.choose_weighted_option([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option([]) == none::<int>;
    }

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

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

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


<commit_before>use byteorder::{ReadBytesExt, LittleEndian};
use encoding::all::UTF_16LE;
use encoding::{Encoding, DecoderTrap};
use lnkpkg::errors::{LnkError};
use std::io::Read;
use std::io::Error;
use std::slice;

pub fn read_string_u8_w_size<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string with the size preceeding the string
    let str_size = reader.read_u8()?;

    let mut utf8_buffer = vec![0;str_size as usize];
    reader.read_exact(utf8_buffer.as_mut_slice())?;

    Ok(
        String::from_utf8(utf8_buffer)?
    )
}

pub fn read_string_u16_w_size<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string with the size preceeding the string
    // multiply size by two (wchar = 2 bytes)
    let str_size = reader.read_u16::<LittleEndian>()? * 2;

    let mut utf16_buffer = vec![0;str_size as usize];
    reader.read_exact(utf16_buffer.as_mut_slice())?;

    let utf16_string = match UTF_16LE.decode(&utf16_buffer.as_slice(),DecoderTrap::Ignore) {
        Ok(utf16) => utf16,
        Err(error) => return Err(
            LnkError::utf16_decode_error(
                format!("Error decoding name in volume_label_unicode field. [{}]",error)
            )
        )
    };

    Ok(utf16_string)
}

pub fn read_string_u8_till_null<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string till a null char is reached
    let utf8_buffer = get_u8_vec(&mut reader)?;
    Ok(
        String::from_utf8(utf8_buffer)?
    )
}

pub fn read_string_u16_till_null<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string till a null char is reached
    let utf16_buffer = get_u8_vec_utf16(&mut reader)?;
    let utf16_string = match UTF_16LE.decode(&utf16_buffer.as_slice(),DecoderTrap::Ignore) {
        Ok(utf16) => utf16,
        Err(error) => return Err(
            LnkError::utf16_decode_error(
                format!("Error decoding name in volume_label_unicode field. [{}]",error)
            )
        )
    };
    Ok(utf16_string)
}

pub fn get_u8_vec<R: Read>(mut reader: R) -> Result<Vec<u8>,Error> {
    let mut string_vec: Vec<u8> = Vec::new();

    loop {
        let u8_char = reader.read_u8()?;
        if u8_char == 0x00 {
            break
        } else {
            string_vec.push(u8_char);
        }
    }

    Ok(string_vec)
}

pub fn get_u8_vec_utf16<R: Read>(mut reader: R) -> Result<Vec<u8>,Error>{
    let mut u16_vec: Vec<u16> = Vec::new();

    loop {
        let u16_char = reader.read_u16::<LittleEndian>()?;
        if u16_char == 0x0000 {
            break
        } else {
            u16_vec.push(u16_char);
        }
    }

    let u8_slice: &[u8] = unsafe {
        slice::from_raw_parts(u16_vec.as_ptr() as *const u8, u16_vec.len() * 2)
    };

    Ok(u8_slice.to_vec())
}

pub fn get_u16_vec<R: Read>(mut reader: R) -> Result<Vec<u16>,Error> {
    let mut string_vec: Vec<u16> = Vec::new();

    loop {
        let u16_char = reader.read_u16::<LittleEndian>()?;
        if u16_char == 0x0000 {
            break
        } else {
            string_vec.push(u16_char);
        }
    }

    Ok(string_vec)
}
<commit_msg>added custom ByteArray struct<commit_after>use byteorder::{ReadBytesExt, LittleEndian};
use encoding::all::UTF_16LE;
use encoding::{Encoding, DecoderTrap};
use lnkpkg::errors::{LnkError};
use std::io::Read;
use std::io::Error;
use std::slice;
use std::fmt;

pub struct ByteArray(pub Vec<u8>);
impl fmt::Debug for ByteArray {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{:?}",
            to_hex_string(&self.0),
        )
    }
}
// impl ser::Serialize for ByteArray {
//     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//         where S: ser::Serializer
//     {
//         serializer.serialize_str(&format!("{}", to_hex_string(&self.0)))
//     }
// }

pub fn to_hex_string(bytes: &Vec<u8>) -> String {
    let strs: Vec<String> = bytes.iter()
        .map(|b| format!("{:02X}", b))
        .collect();
    strs.join("")
}

pub fn read_string_u8_w_size<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string with the size preceeding the string
    let str_size = reader.read_u8()?;

    let mut utf8_buffer = vec![0;str_size as usize];
    reader.read_exact(utf8_buffer.as_mut_slice())?;

    Ok(
        String::from_utf8(utf8_buffer)?
    )
}

pub fn read_string_u16_w_size<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string with the size preceeding the string
    // multiply size by two (wchar = 2 bytes)
    let str_size = reader.read_u16::<LittleEndian>()? * 2;

    let mut utf16_buffer = vec![0;str_size as usize];
    reader.read_exact(utf16_buffer.as_mut_slice())?;

    let utf16_string = match UTF_16LE.decode(&utf16_buffer.as_slice(),DecoderTrap::Ignore) {
        Ok(utf16) => utf16,
        Err(error) => return Err(
            LnkError::utf16_decode_error(
                format!("Error decoding name in volume_label_unicode field. [{}]",error)
            )
        )
    };

    Ok(utf16_string)
}

pub fn read_string_u8_till_null<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string till a null char is reached
    let utf8_buffer = get_u8_vec(&mut reader)?;
    Ok(
        String::from_utf8(utf8_buffer)?
    )
}

pub fn read_string_u16_till_null<R: Read>(mut reader: R) -> Result<String,LnkError> {
    // Reads into a string till a null char is reached
    let utf16_buffer = get_u8_vec_utf16(&mut reader)?;
    let utf16_string = match UTF_16LE.decode(&utf16_buffer.as_slice(),DecoderTrap::Ignore) {
        Ok(utf16) => utf16,
        Err(error) => return Err(
            LnkError::utf16_decode_error(
                format!("Error decoding name in volume_label_unicode field. [{}]",error)
            )
        )
    };
    Ok(utf16_string)
}

pub fn get_u8_vec<R: Read>(mut reader: R) -> Result<Vec<u8>,Error> {
    let mut string_vec: Vec<u8> = Vec::new();

    loop {
        let u8_char = reader.read_u8()?;
        if u8_char == 0x00 {
            break
        } else {
            string_vec.push(u8_char);
        }
    }

    Ok(string_vec)
}

pub fn get_u8_vec_utf16<R: Read>(mut reader: R) -> Result<Vec<u8>,Error>{
    let mut u16_vec: Vec<u16> = Vec::new();

    loop {
        let u16_char = reader.read_u16::<LittleEndian>()?;
        if u16_char == 0x0000 {
            break
        } else {
            u16_vec.push(u16_char);
        }
    }

    let u8_slice: &[u8] = unsafe {
        slice::from_raw_parts(u16_vec.as_ptr() as *const u8, u16_vec.len() * 2)
    };

    Ok(u8_slice.to_vec())
}

pub fn get_u16_vec<R: Read>(mut reader: R) -> Result<Vec<u16>,Error> {
    let mut string_vec: Vec<u16> = Vec::new();

    loop {
        let u16_char = reader.read_u16::<LittleEndian>()?;
        if u16_char == 0x0000 {
            break
        } else {
            string_vec.push(u16_char);
        }
    }

    Ok(string_vec)
}
<|endoftext|>


<commit_before>// This is a part of Chrono.
// See README.md and LICENSE.txt for details.

//! The local (system) time zone.

use oldtime;
use oldtime::Duration as OldDuration;

use {Datelike, Timelike};
use naive::date::NaiveDate;
use naive::time::NaiveTime;
use naive::datetime::NaiveDateTime;
use date::Date;
use datetime::DateTime;
use super::{TimeZone, LocalResult};
use super::fixed::FixedOffset;

/// Converts a `time::Tm` struct into the timezone-aware `DateTime`.
/// This assumes that `time` is working correctly, i.e. any error is fatal.
fn tm_to_datetime(mut tm: oldtime::Tm) -> DateTime<Local> {
    if tm.tm_sec >= 60 {
        tm.tm_nsec += (tm.tm_sec - 59) * 1_000_000_000;
        tm.tm_sec = 59;
    }

    #[cfg(not(windows))]
    fn tm_to_naive_date(tm: &oldtime::Tm) -> NaiveDate {
        // from_yo is more efficient than from_ymd (since it's the internal representation).
        NaiveDate::from_yo(tm.tm_year + 1900, tm.tm_yday as u32 + 1)
    }

    #[cfg(windows)]
    fn tm_to_naive_date(tm: &oldtime::Tm) -> NaiveDate {
        // ...but tm_yday is broken in Windows (issue #85)
        NaiveDate::from_ymd(tm.tm_year + 1900, tm.tm_mon as u32 + 1, tm.tm_mday as u32)
    }

    let date = tm_to_naive_date(&tm);
    let time = NaiveTime::from_hms_nano(tm.tm_hour as u32, tm.tm_min as u32,
                                        tm.tm_sec as u32, tm.tm_nsec as u32);
    let offset = FixedOffset::east(tm.tm_utcoff);
    DateTime::from_utc(date.and_time(time) + OldDuration::seconds(-tm.tm_utcoff as i64), offset)
}

/// Converts a local `NaiveDateTime` to the `time::Timespec`.
fn datetime_to_timespec(d: &NaiveDateTime, local: bool) -> oldtime::Timespec {
    // well, this exploits an undocumented `Tm::to_timespec` behavior
    // to get the exact function we want (either `timegm` or `mktime`).
    // the number 1 is arbitrary but should be non-zero to trigger `mktime`.
    let tm_utcoff = if local {1} else {0};

    let mut tm = oldtime::Tm {
        tm_sec: d.second() as i32,
        tm_min: d.minute() as i32,
        tm_hour: d.hour() as i32,
        tm_mday: d.day() as i32,
        tm_mon: d.month0() as i32, // yes, C is that strange...
        tm_year: d.year() - 1900, // this doesn't underflow, we know that d is `NaiveDateTime`.
        tm_wday: 0, // to_local ignores this
        tm_yday: 0, // and this
        tm_isdst: -1,
        tm_utcoff: tm_utcoff,
        tm_nsec: d.nanosecond() as i32,
    };

    // adjustment for the leap second
    if tm.tm_nsec >= 1_000_000_000 {
        tm.tm_sec += 1;
        tm.tm_nsec -= 1_000_000_000;
    }

    tm.to_timespec()
}

/// The local timescale. This is implemented via the standard `time` crate.
///
/// Using the [`TimeZone`](../../../chrono/offset/trait.TimeZone.html) methods
/// on the Local struct is the preferred way to construct `DateTime<Local>`
/// instances.
///
/// # Example
///
/// ~~~~
/// use chrono::{Local, DateTime, TimeZone};
///
/// let dt: DateTime<Local> = Local::now();
/// let dt: DateTime<Local> = Local.timestamp(0, 0);
/// ~~~~
#[derive(Copy, Clone)]
pub struct Local;

impl Local {
    /// Returns a `Date` which corresponds to the current date.
    pub fn today() -> Date<Local> {
        Local::now().date()
    }

    /// Returns a `DateTime` which corresponds to the current date.
    pub fn now() -> DateTime<Local> {
        tm_to_datetime(oldtime::now())
    }
}

impl TimeZone for Local {
    type Offset = FixedOffset;

    fn from_offset(_offset: &FixedOffset) -> Local { Local }

    // they are easier to define in terms of the finished date and time unlike other offsets
    fn offset_from_local_date(&self, local: &NaiveDate) -> LocalResult<FixedOffset> {
        self.from_local_date(local).map(|date| *date.offset())
    }
    fn offset_from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<FixedOffset> {
        self.from_local_datetime(local).map(|datetime| *datetime.offset())
    }

    fn offset_from_utc_date(&self, utc: &NaiveDate) -> FixedOffset {
        *self.from_utc_date(utc).offset()
    }
    fn offset_from_utc_datetime(&self, utc: &NaiveDateTime) -> FixedOffset {
        *self.from_utc_datetime(utc).offset()
    }

    // override them for avoiding redundant works
    fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<Local>> {
        // this sounds very strange, but required for keeping `TimeZone::ymd` sane.
        // in the other words, we use the offset at the local midnight
        // but keep the actual date unaltered (much like `FixedOffset`).
        let midnight = self.from_local_datetime(&local.and_hms(0, 0, 0));
        midnight.map(|datetime| Date::from_utc(*local, *datetime.offset()))
    }
    fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<Local>> {
        let timespec = datetime_to_timespec(local, true);
        LocalResult::Single(tm_to_datetime(oldtime::at(timespec)))
    }

    fn from_utc_date(&self, utc: &NaiveDate) -> Date<Local> {
        let midnight = self.from_utc_datetime(&utc.and_hms(0, 0, 0));
        Date::from_utc(*utc, *midnight.offset())
    }
    fn from_utc_datetime(&self, utc: &NaiveDateTime) -> DateTime<Local> {
        let timespec = datetime_to_timespec(utc, false);
        tm_to_datetime(oldtime::at(timespec))
    }
}

#[cfg(test)]
mod tests {
    use Datelike;
    use offset::TimeZone;
    use super::Local;

    #[test]
    fn test_local_date_sanity_check() { // issue #27
        assert_eq!(Local.ymd(2999, 12, 28).day(), 28);
    }

    #[test]
    fn test_leap_second() { // issue #123
        let today = Local::today();
        let dt = today.and_hms_milli(1, 2, 59, 1000);
        let timestr = dt.time().to_string();
        // the OS API may or may not support the leap second,
        // but there are only two sensible options.
        assert!(timestr == "01:02:60" || timestr == "01:03:00",
                "unexpected timestr {:?}", timestr);

        // this case, while unsupported by most APIs, should *not* panic.
        let _ = today.and_hms_milli_opt(1, 2, 3, 1000);
    }
}

<commit_msg>Avoid passing nanoseconds to the OS APIs at all. (#123)<commit_after>// This is a part of Chrono.
// See README.md and LICENSE.txt for details.

//! The local (system) time zone.

use oldtime;
use oldtime::Duration as OldDuration;

use {Datelike, Timelike};
use naive::date::NaiveDate;
use naive::time::NaiveTime;
use naive::datetime::NaiveDateTime;
use date::Date;
use datetime::DateTime;
use super::{TimeZone, LocalResult};
use super::fixed::FixedOffset;

/// Converts a `time::Tm` struct into the timezone-aware `DateTime`.
/// This assumes that `time` is working correctly, i.e. any error is fatal.
fn tm_to_datetime(mut tm: oldtime::Tm) -> DateTime<Local> {
    if tm.tm_sec >= 60 {
        tm.tm_nsec += (tm.tm_sec - 59) * 1_000_000_000;
        tm.tm_sec = 59;
    }

    #[cfg(not(windows))]
    fn tm_to_naive_date(tm: &oldtime::Tm) -> NaiveDate {
        // from_yo is more efficient than from_ymd (since it's the internal representation).
        NaiveDate::from_yo(tm.tm_year + 1900, tm.tm_yday as u32 + 1)
    }

    #[cfg(windows)]
    fn tm_to_naive_date(tm: &oldtime::Tm) -> NaiveDate {
        // ...but tm_yday is broken in Windows (issue #85)
        NaiveDate::from_ymd(tm.tm_year + 1900, tm.tm_mon as u32 + 1, tm.tm_mday as u32)
    }

    let date = tm_to_naive_date(&tm);
    let time = NaiveTime::from_hms_nano(tm.tm_hour as u32, tm.tm_min as u32,
                                        tm.tm_sec as u32, tm.tm_nsec as u32);
    let offset = FixedOffset::east(tm.tm_utcoff);
    DateTime::from_utc(date.and_time(time) + OldDuration::seconds(-tm.tm_utcoff as i64), offset)
}

/// Converts a local `NaiveDateTime` to the `time::Timespec`.
fn datetime_to_timespec(d: &NaiveDateTime, local: bool) -> oldtime::Timespec {
    // well, this exploits an undocumented `Tm::to_timespec` behavior
    // to get the exact function we want (either `timegm` or `mktime`).
    // the number 1 is arbitrary but should be non-zero to trigger `mktime`.
    let tm_utcoff = if local {1} else {0};

    let tm = oldtime::Tm {
        tm_sec: d.second() as i32,
        tm_min: d.minute() as i32,
        tm_hour: d.hour() as i32,
        tm_mday: d.day() as i32,
        tm_mon: d.month0() as i32, // yes, C is that strange...
        tm_year: d.year() - 1900, // this doesn't underflow, we know that d is `NaiveDateTime`.
        tm_wday: 0, // to_local ignores this
        tm_yday: 0, // and this
        tm_isdst: -1,
        tm_utcoff: tm_utcoff,
        // do not set this, OS APIs are heavily inconsistent in terms of leap second handling
        tm_nsec: 0,
    };

    tm.to_timespec()
}

/// The local timescale. This is implemented via the standard `time` crate.
///
/// Using the [`TimeZone`](../../../chrono/offset/trait.TimeZone.html) methods
/// on the Local struct is the preferred way to construct `DateTime<Local>`
/// instances.
///
/// # Example
///
/// ~~~~
/// use chrono::{Local, DateTime, TimeZone};
///
/// let dt: DateTime<Local> = Local::now();
/// let dt: DateTime<Local> = Local.timestamp(0, 0);
/// ~~~~
#[derive(Copy, Clone)]
pub struct Local;

impl Local {
    /// Returns a `Date` which corresponds to the current date.
    pub fn today() -> Date<Local> {
        Local::now().date()
    }

    /// Returns a `DateTime` which corresponds to the current date.
    pub fn now() -> DateTime<Local> {
        tm_to_datetime(oldtime::now())
    }
}

impl TimeZone for Local {
    type Offset = FixedOffset;

    fn from_offset(_offset: &FixedOffset) -> Local { Local }

    // they are easier to define in terms of the finished date and time unlike other offsets
    fn offset_from_local_date(&self, local: &NaiveDate) -> LocalResult<FixedOffset> {
        self.from_local_date(local).map(|date| *date.offset())
    }

    fn offset_from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<FixedOffset> {
        self.from_local_datetime(local).map(|datetime| *datetime.offset())
    }

    fn offset_from_utc_date(&self, utc: &NaiveDate) -> FixedOffset {
        *self.from_utc_date(utc).offset()
    }

    fn offset_from_utc_datetime(&self, utc: &NaiveDateTime) -> FixedOffset {
        *self.from_utc_datetime(utc).offset()
    }

    // override them for avoiding redundant works
    fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<Local>> {
        // this sounds very strange, but required for keeping `TimeZone::ymd` sane.
        // in the other words, we use the offset at the local midnight
        // but keep the actual date unaltered (much like `FixedOffset`).
        let midnight = self.from_local_datetime(&local.and_hms(0, 0, 0));
        midnight.map(|datetime| Date::from_utc(*local, *datetime.offset()))
    }

    fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<Local>> {
        let timespec = datetime_to_timespec(local, true);

        // datetime_to_timespec completely ignores leap seconds, so we need to adjust for them
        let mut tm = oldtime::at(timespec);
        assert_eq!(tm.tm_nsec, 0);
        tm.tm_nsec = local.nanosecond() as i32;

        LocalResult::Single(tm_to_datetime(tm))
    }

    fn from_utc_date(&self, utc: &NaiveDate) -> Date<Local> {
        let midnight = self.from_utc_datetime(&utc.and_hms(0, 0, 0));
        Date::from_utc(*utc, *midnight.offset())
    }

    fn from_utc_datetime(&self, utc: &NaiveDateTime) -> DateTime<Local> {
        let timespec = datetime_to_timespec(utc, false);

        // datetime_to_timespec completely ignores leap seconds, so we need to adjust for them
        let mut tm = oldtime::at(timespec);
        assert_eq!(tm.tm_nsec, 0);
        tm.tm_nsec = utc.nanosecond() as i32;

        tm_to_datetime(tm)
    }
}

#[cfg(test)]
mod tests {
    use Datelike;
    use offset::TimeZone;
    use super::Local;

    #[test]
    fn test_local_date_sanity_check() { // issue #27
        assert_eq!(Local.ymd(2999, 12, 28).day(), 28);
    }

    #[test]
    fn test_leap_second() { // issue #123
        let today = Local::today();

        let dt = today.and_hms_milli(1, 2, 59, 1000);
        let timestr = dt.time().to_string();
        // the OS API may or may not support the leap second,
        // but there are only two sensible options.
        assert!(timestr == "01:02:60" || timestr == "01:03:00",
                "unexpected timestr {:?}", timestr);

        let dt = today.and_hms_milli(1, 2, 3, 1234);
        let timestr = dt.time().to_string();
        assert!(timestr == "01:02:03.234" || timestr == "01:02:04.234",
                "unexpected timestr {:?}", timestr);
    }
}

<|endoftext|>


<commit_before><commit_msg>Move alt method outside the benchmark function<commit_after><|endoftext|>


<commit_before><commit_msg>turn signal envelope into a ranged float [0.0, 1.0]<commit_after><|endoftext|>


<commit_before><commit_msg>clippy-clean<commit_after><|endoftext|>


<commit_before><commit_msg>removed unnecessary file<commit_after><|endoftext|>


<commit_before>use crate::{
    heartbeat::Heartbeat,
    socket_state::{SocketEvent, SocketStateHandle},
    tcp::TcpStream,
    thread::ThreadHandle,
    Result,
};
use log::trace;
use mio::{Events, Interest, Poll, Token};
use std::{
    collections::HashMap,
    fmt,
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread::Builder as ThreadBuilder,
};

pub trait ReactorBuilder: fmt::Debug + Send + Sync {
    fn build(&self, heartbeat: Heartbeat) -> Result<Box<dyn Reactor + Send>>;
}

pub trait Reactor: fmt::Debug + Send {
    fn register(&mut self, socket: &mut TcpStream, socket_state: SocketStateHandle) -> Result<()>;
    fn handle(&self) -> Box<dyn ReactorHandle + Send> {
        Box::new(DummyHandle)
    }
    fn start(self: Box<Self>) -> Result<ThreadHandle> {
        Ok(ThreadHandle::default())
    }
}

pub trait ReactorHandle {
    fn shutdown(&self) {}
    fn start_heartbeat(&self) {}
    fn poll_read(&self) {}
    fn poll_write(&self) {}
}

pub(crate) struct DefaultReactorBuilder;

impl ReactorBuilder for DefaultReactorBuilder {
    fn build(&self, heartbeat: Heartbeat) -> Result<Box<dyn Reactor + Send>> {
        Ok(Box::new(DefaultReactor::new(heartbeat)?))
    }
}

pub(crate) struct DefaultReactor {
    slot: AtomicUsize,
    poll: Poll,
    heartbeat: Heartbeat,
    slots: HashMap<Token, SocketStateHandle>,
    handle: DefaultReactorHandle,
}

#[derive(Clone)]
pub(crate) struct DefaultReactorHandle(Arc<AtomicBool>);

impl Reactor for DefaultReactor {
    fn handle(&self) -> Box<dyn ReactorHandle + Send> {
        Box::new(self.handle.clone())
    }

    fn register(&mut self, socket: &mut TcpStream, socket_state: SocketStateHandle) -> Result<()> {
        let token = Token(self.slot.fetch_add(1, Ordering::SeqCst));
        self.poll
            .registry()
            .register(socket, token, Interest::READABLE | Interest::WRITABLE)?;
        self.slots.insert(token, socket_state);
        Ok(())
    }

    fn start(mut self: Box<Self>) -> Result<ThreadHandle> {
        Ok(ThreadHandle::new(
            ThreadBuilder::new()
                .name("lapin-reactor".into())
                .spawn(move || {
                    let mut events = Events::with_capacity(16);
                    while self.should_run() {
                        self.run(&mut events)?;
                    }
                    Ok(())
                })?,
        ))
    }
}

impl DefaultReactor {
    fn new(heartbeat: Heartbeat) -> Result<Self> {
        Ok(Self {
            slot: AtomicUsize::new(1),
            poll: Poll::new()?,
            heartbeat,
            slots: HashMap::default(),
            handle: DefaultReactorHandle(Arc::new(AtomicBool::new(true))),
        })
    }

    fn should_run(&self) -> bool {
        self.handle.0.load(Ordering::SeqCst)
    }

    fn run(&mut self, events: &mut Events) -> Result<()> {
        trace!("reactor poll");
        self.poll.poll(events, self.heartbeat.poll_timeout()?)?;
        trace!("reactor poll done");
        for event in events.iter() {
            if let Some(socket) = self.slots.get(&event.token()) {
                if event.is_error() {
                    socket.send(SocketEvent::Error);
                }
                if event.is_read_closed() || event.is_write_closed() {
                    socket.send(SocketEvent::Closed);
                }
                if event.is_readable() {
                    socket.send(SocketEvent::Readable);
                }
                if event.is_writable() {
                    socket.send(SocketEvent::Writable);
                }
            }
        }
        Ok(())
    }
}

impl ReactorHandle for DefaultReactorHandle {
    fn shutdown(&self) {
        self.0.store(false, Ordering::SeqCst);
    }
}

impl fmt::Debug for DefaultReactorBuilder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DefaultReactorBuilder").finish()
    }
}

impl fmt::Debug for DefaultReactor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DefaultReactor").finish()
    }
}

#[derive(Clone)]
struct DummyHandle;

impl ReactorHandle for DummyHandle {}
<commit_msg>reactor: add Slot to some trait methods<commit_after>use crate::{
    heartbeat::Heartbeat,
    socket_state::{SocketEvent, SocketStateHandle},
    tcp::TcpStream,
    thread::ThreadHandle,
    Result,
};
use log::trace;
use mio::{Events, Interest, Poll, Token};
use std::{
    collections::HashMap,
    fmt,
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread::Builder as ThreadBuilder,
};

pub type Slot = usize;

pub trait ReactorBuilder: fmt::Debug + Send + Sync {
    fn build(&self, heartbeat: Heartbeat) -> Result<Box<dyn Reactor + Send>>;
}

pub trait Reactor: fmt::Debug + Send {
    fn register(&mut self, socket: &mut TcpStream, socket_state: SocketStateHandle) -> Result<Slot>;
    fn handle(&self) -> Box<dyn ReactorHandle + Send> {
        Box::new(DummyHandle)
    }
    fn start(self: Box<Self>) -> Result<ThreadHandle> {
        Ok(ThreadHandle::default())
    }
}

pub trait ReactorHandle {
    fn shutdown(&self) {}
    fn start_heartbeat(&self) {}
    fn poll_read(&self, _slot: Slot) {}
    fn poll_write(&self, _slot: Slot) {}
}

pub(crate) struct DefaultReactorBuilder;

impl ReactorBuilder for DefaultReactorBuilder {
    fn build(&self, heartbeat: Heartbeat) -> Result<Box<dyn Reactor + Send>> {
        Ok(Box::new(DefaultReactor::new(heartbeat)?))
    }
}

pub(crate) struct DefaultReactor {
    slot: AtomicUsize,
    poll: Poll,
    heartbeat: Heartbeat,
    slots: HashMap<Token, SocketStateHandle>,
    handle: DefaultReactorHandle,
}

#[derive(Clone)]
pub(crate) struct DefaultReactorHandle(Arc<AtomicBool>);

impl Reactor for DefaultReactor {
    fn handle(&self) -> Box<dyn ReactorHandle + Send> {
        Box::new(self.handle.clone())
    }

    fn register(&mut self, socket: &mut TcpStream, socket_state: SocketStateHandle) -> Result<usize> {
        let token = Token(self.slot.fetch_add(1, Ordering::SeqCst));
        self.poll
            .registry()
            .register(socket, token, Interest::READABLE | Interest::WRITABLE)?;
        self.slots.insert(token, socket_state);
        Ok(token.0)
    }

    fn start(mut self: Box<Self>) -> Result<ThreadHandle> {
        Ok(ThreadHandle::new(
            ThreadBuilder::new()
                .name("lapin-reactor".into())
                .spawn(move || {
                    let mut events = Events::with_capacity(16);
                    while self.should_run() {
                        self.run(&mut events)?;
                    }
                    Ok(())
                })?,
        ))
    }
}

impl DefaultReactor {
    fn new(heartbeat: Heartbeat) -> Result<Self> {
        Ok(Self {
            slot: AtomicUsize::new(1),
            poll: Poll::new()?,
            heartbeat,
            slots: HashMap::default(),
            handle: DefaultReactorHandle(Arc::new(AtomicBool::new(true))),
        })
    }

    fn should_run(&self) -> bool {
        self.handle.0.load(Ordering::SeqCst)
    }

    fn run(&mut self, events: &mut Events) -> Result<()> {
        trace!("reactor poll");
        self.poll.poll(events, self.heartbeat.poll_timeout()?)?;
        trace!("reactor poll done");
        for event in events.iter() {
            if let Some(socket) = self.slots.get(&event.token()) {
                if event.is_error() {
                    socket.send(SocketEvent::Error);
                }
                if event.is_read_closed() || event.is_write_closed() {
                    socket.send(SocketEvent::Closed);
                }
                if event.is_readable() {
                    socket.send(SocketEvent::Readable);
                }
                if event.is_writable() {
                    socket.send(SocketEvent::Writable);
                }
            }
        }
        Ok(())
    }
}

impl ReactorHandle for DefaultReactorHandle {
    fn shutdown(&self) {
        self.0.store(false, Ordering::SeqCst);
    }
}

impl fmt::Debug for DefaultReactorBuilder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DefaultReactorBuilder").finish()
    }
}

impl fmt::Debug for DefaultReactor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DefaultReactor").finish()
    }
}

#[derive(Clone)]
struct DummyHandle;

impl ReactorHandle for DummyHandle {}
<|endoftext|>


<commit_before><commit_msg>feat: Request::into_multicall_struct()<commit_after><|endoftext|>


<commit_before><commit_msg>Update to rust matser<commit_after><|endoftext|>


<commit_before>#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "linux")]
pub mod linux;
pub mod sockaddr;
pub mod configuration;

#[cfg(target_os = "macos")]
pub use self::macos as os;
#[cfg(target_os = "macos")]
pub use self::macos::create;

#[cfg(target_os = "linux")]
pub use self::linux as os;
#[cfg(target_os = "linux")]
pub use self::linux::create;

pub use self::configuration::Configuration;

use std::fmt::Debug;
use std::io::{Read, Write};
use std::net::Ipv4Addr;

use mio::event::Evented;

use common::error::*;

pub trait Tun: Read + Write + Debug + Evented {
    fn name(&self) -> &str;

    fn address(&self) -> Result<Ipv4Addr>;
    fn set_address(&mut self, value: Ipv4Addr) -> Result<()>;

    fn broadcast(&self) -> Result<Ipv4Addr>;
    fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()>;

    fn destination(&self) -> Result<Ipv4Addr>;
    fn set_destination(&mut self, value: Ipv4Addr) -> Result<()>;

    fn netmask(&self) -> Result<Ipv4Addr>;
    fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()>;

    fn mtu(&self) -> Result<i32>;
    fn set_mtu(&mut self, value: i32) -> Result<()>;

    fn flags(&self) -> Result<i16>;
    fn set_flags(&mut self, value: i16) -> Result<()>;

    fn set_enabled(&mut self, value: bool) -> Result<()>;
}
<commit_msg>Update src/tun/mod.rs<commit_after>pub mod sockaddr;
pub mod configuration;

#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "macos")]
pub use self::macos as os;

#[cfg(target_os = "linux")]
pub mod linux;
#[cfg(target_os = "linux")]
pub use self::linux as os;

#[cfg(not(any(target_os = "linux", target_os = "macos")))]
pub mod os {
    pub fn create() -> Result<Tun> {
        unimplemented!();
    }
}

pub use self::os::create;
pub use self::configuration::Configuration;

use std::fmt::Debug;
use std::io::{Read, Write};
use std::net::Ipv4Addr;

use mio::event::Evented;

use common::error::*;

pub trait Tun: Read + Write + Debug + Evented {
    fn name(&self) -> &str;

    fn address(&self) -> Result<Ipv4Addr>;
    fn set_address(&mut self, value: Ipv4Addr) -> Result<()>;

    fn broadcast(&self) -> Result<Ipv4Addr>;
    fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()>;

    fn destination(&self) -> Result<Ipv4Addr>;
    fn set_destination(&mut self, value: Ipv4Addr) -> Result<()>;

    fn netmask(&self) -> Result<Ipv4Addr>;
    fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()>;

    fn mtu(&self) -> Result<i32>;
    fn set_mtu(&mut self, value: i32) -> Result<()>;

    fn flags(&self) -> Result<i16>;
    fn set_flags(&mut self, value: i16) -> Result<()>;

    fn set_enabled(&mut self, value: bool) -> Result<()>;
}
<|endoftext|>


<commit_before><commit_msg>Do not use nonexistent subtraction intrinsics<commit_after><|endoftext|>


<commit_before>use cucumber::{async_trait, criteria::feature, futures::FutureExt, Context, Cucumber, World};
use elasticsearch::http::transport::SingleNodeConnectionPool;
use mimir2::adapters::primary::common::settings::QuerySettings;
use mimir2::adapters::secondary::elasticsearch::remote::connection_test_pool;
use mimir2::adapters::secondary::elasticsearch::{ES_DEFAULT_TIMEOUT, ES_DEFAULT_VERSION_REQ};
use mimir2::domain::ports::secondary::remote::Remote;
use std::convert::Infallible;

mod steps;

pub struct MyWorld {
    query_settings: QuerySettings,
    search_result: Vec<serde_json::Value>,
    processing_step: Option<steps::admin::ProcessingStep>,
    // client: Option<ElasticsearchStorage>,
}

#[async_trait(?Send)]
impl World for MyWorld {
    type Error = Infallible;

    async fn new() -> Result<Self, Infallible> {
        let query_settings = QuerySettings::default();
        Ok(Self {
            query_settings,
            search_result: Vec::new(),
            processing_step: None,
        })
    }
}

#[tokio::main]
async fn main() {
    let pool = connection_test_pool().await.unwrap();

    Cucumber::<MyWorld>::new()
        // Specifies where our feature files exist
        .features(&["./features/admin"])
        // Adds the implementation of our steps to the runner
        .steps(steps::admin::steps())
        // Add some global context for all the tests, like databases.
        .context(Context::new().add(pool))
        // Add some lifecycle functions to manage our database nightmare
        .before(feature("Example feature"), |ctx| {
            // FIXME What should be done with these before and after?
            // Should we create the client here?
            let pool = ctx.get::<SingleNodeConnectionPool>().unwrap().clone();
            async move {
                let _client = pool
                    .conn(ES_DEFAULT_TIMEOUT, ES_DEFAULT_VERSION_REQ)
                    .await
                    .unwrap();
            }
            .boxed()
        })
        // .after(feature("Example feature"), |ctx| {
        //     let pool = ctx.get::<SqlitePool>().unwrap().clone();
        //     async move { drop_tables(&pool).await }.boxed()
        // })
        // Parses the command line arguments if passed
        .cli()
        // Runs the Cucumber tests and then exists
        .run_and_exit()
        .await
}
<commit_msg>Make tests/admin independent from previous tests<commit_after>use cucumber::{async_trait, criteria::feature, futures::FutureExt, Context, Cucumber, World};
use elasticsearch::http::transport::SingleNodeConnectionPool;
use mimir2::adapters::primary::common::settings::QuerySettings;
use mimir2::adapters::secondary::elasticsearch::remote::connection_test_pool;
use mimir2::adapters::secondary::elasticsearch::{ES_DEFAULT_TIMEOUT, ES_DEFAULT_VERSION_REQ};
use mimir2::domain::ports::secondary::remote::Remote;
use mimir2::utils::docker;
use std::convert::Infallible;

mod steps;

pub struct MyWorld {
    query_settings: QuerySettings,
    search_result: Vec<serde_json::Value>,
    processing_step: Option<steps::admin::ProcessingStep>,
    // client: Option<ElasticsearchStorage>,
}

#[async_trait(?Send)]
impl World for MyWorld {
    type Error = Infallible;

    async fn new() -> Result<Self, Infallible> {
        let query_settings = QuerySettings::default();
        Ok(Self {
            query_settings,
            search_result: Vec::new(),
            processing_step: None,
        })
    }
}

#[tokio::main]
async fn main() {
    let _guard = docker::initialize()
        .await
        .expect("elasticsearch docker initialization");
    let pool = connection_test_pool().await.unwrap();

    Cucumber::<MyWorld>::new()
        // Specifies where our feature files exist
        .features(&["./features/admin"])
        // Adds the implementation of our steps to the runner
        .steps(steps::admin::steps())
        // Add some global context for all the tests, like databases.
        .context(Context::new().add(pool))
        // Add some lifecycle functions to manage our database nightmare
        .before(feature("Example feature"), |ctx| {
            // FIXME What should be done with these before and after?
            // Should we create the client here?
            let pool = ctx.get::<SingleNodeConnectionPool>().unwrap().clone();
            async move {
                let _client = pool
                    .conn(ES_DEFAULT_TIMEOUT, ES_DEFAULT_VERSION_REQ)
                    .await
                    .unwrap();
            }
            .boxed()
        })
        // .after(feature("Example feature"), |ctx| {
        //     let pool = ctx.get::<SqlitePool>().unwrap().clone();
        //     async move { drop_tables(&pool).await }.boxed()
        // })
        // Parses the command line arguments if passed
        .cli()
        // Runs the Cucumber tests and then exists
        .run_and_exit()
        .await
}
<|endoftext|>


<commit_before>extern crate hamcrest;
extern crate cargotest;

use std::env;

use cargotest::support::{git, project, execs, main_file, basic_bin_manifest};
use cargotest::support::registry::Package;
use hamcrest::{assert_that, existing_dir, existing_file, is_not};

#[test]
fn cargo_clean_simple() {
    let p = project("foo")
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .build();

    assert_that(p.cargo("build"), execs().with_status(0));
    assert_that(&p.build_dir(), existing_dir());

    assert_that(p.cargo("clean"),
                execs().with_status(0));
    assert_that(&p.build_dir(), is_not(existing_dir()));
}

#[test]
fn different_dir() {
    let p = project("foo")
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("src/bar/a.rs", "")
        .build();

    assert_that(p.cargo("build"), execs().with_status(0));
    assert_that(&p.build_dir(), existing_dir());

    assert_that(p.cargo("clean").cwd(&p.root().join("src")),
                execs().with_status(0).with_stdout(""));
    assert_that(&p.build_dir(), is_not(existing_dir()));
}

#[test]
fn clean_multiple_packages() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.d1]
                path = "d1"
            [dependencies.d2]
                path = "d2"

            [[bin]]
                name = "foo"
        "#)
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("d1/Cargo.toml", r#"
            [package]
            name = "d1"
            version = "0.0.1"
            authors = []

            [[bin]]
                name = "d1"
        "#)
        .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
        .file("d2/Cargo.toml", r#"
            [package]
            name = "d2"
            version = "0.0.1"
            authors = []

            [[bin]]
                name = "d2"
        "#)
        .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
        .build();

    assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("d2")
                                        .arg("-p").arg("foo"),
                execs().with_status(0));

    let d1_path = &p.build_dir().join("debug")
                                .join(format!("d1{}", env::consts::EXE_SUFFIX));
    let d2_path = &p.build_dir().join("debug")
                                .join(format!("d2{}", env::consts::EXE_SUFFIX));

    assert_that(&p.bin("foo"), existing_file());
    assert_that(d1_path, existing_file());
    assert_that(d2_path, existing_file());

    assert_that(p.cargo("clean").arg("-p").arg("d1").arg("-p").arg("d2")
                                .cwd(&p.root().join("src")),
                execs().with_status(0).with_stdout(""));
    assert_that(&p.bin("foo"), existing_file());
    assert_that(d1_path, is_not(existing_file()));
    assert_that(d2_path, is_not(existing_file()));
}

#[test]
fn clean_release() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "")
        .build();

    assert_that(p.cargo("build").arg("--release"),
                execs().with_status(0));

    assert_that(p.cargo("clean").arg("-p").arg("foo"),
                execs().with_status(0));
    assert_that(p.cargo("build").arg("--release"),
                execs().with_status(0).with_stdout(""));

    assert_that(p.cargo("clean").arg("-p").arg("foo").arg("--release"),
                execs().with_status(0));
    assert_that(p.cargo("build").arg("--release"),
                execs().with_status(0).with_stderr("\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
"));
}

#[test]
fn build_script() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
            build = "build.rs"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("build.rs", r#"
            use std::path::PathBuf;
            use std::env;

            fn main() {
                let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
                if env::var("FIRST").is_ok() {
                    std::fs::File::create(out.join("out")).unwrap();
                } else {
                    assert!(!std::fs::metadata(out.join("out")).is_ok());
                }
            }
        "#)
        .file("a/src/lib.rs", "")
        .build();

    assert_that(p.cargo("build").env("FIRST", "1"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("foo"),
                execs().with_status(0));
    assert_that(p.cargo("build").arg("-v"),
                execs().with_status(0).with_stderr("\
[COMPILING] foo v0.0.1 ([..])
[RUNNING] `rustc [..] build.rs [..]`
[RUNNING] `[..]build-script-build`
[RUNNING] `rustc [..] src[/]main.rs [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn clean_git() {
    let git = git::new("dep", |project| {
        project.file("Cargo.toml", r#"
            [project]
            name = "dep"
            version = "0.5.0"
            authors = []
        "#)
        .file("src/lib.rs", "")
    }).unwrap();

    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            dep = {{ git = '{}' }}
        "#, git.url()))
        .file("src/main.rs", "fn main() {}")
        .build();

    assert_that(p.cargo("build"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("dep"),
                execs().with_status(0).with_stdout(""));
    assert_that(p.cargo("build"),
                execs().with_status(0));
}

#[test]
fn registry() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            bar = "0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .build();

    Package::new("bar", "0.1.0").publish();

    assert_that(p.cargo("build"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("bar"),
                execs().with_status(0).with_stdout(""));
    assert_that(p.cargo("build"),
                execs().with_status(0));
}
<commit_msg>Added tests for clean with verbose output<commit_after>extern crate hamcrest;
extern crate cargotest;

use std::env;

use cargotest::support::{git, project, execs, main_file, basic_bin_manifest};
use cargotest::support::registry::Package;
use hamcrest::{assert_that, existing_dir, existing_file, is_not};

#[test]
fn cargo_clean_simple() {
    let p = project("foo")
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .build();

    assert_that(p.cargo("build"), execs().with_status(0));
    assert_that(&p.build_dir(), existing_dir());

    assert_that(p.cargo("clean"),
                execs().with_status(0));
    assert_that(&p.build_dir(), is_not(existing_dir()));
}

#[test]
fn different_dir() {
    let p = project("foo")
        .file("Cargo.toml", &basic_bin_manifest("foo"))
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("src/bar/a.rs", "")
        .build();

    assert_that(p.cargo("build"), execs().with_status(0));
    assert_that(&p.build_dir(), existing_dir());

    assert_that(p.cargo("clean").cwd(&p.root().join("src")),
                execs().with_status(0).with_stdout(""));
    assert_that(&p.build_dir(), is_not(existing_dir()));
}

#[test]
fn clean_multiple_packages() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.d1]
                path = "d1"
            [dependencies.d2]
                path = "d2"

            [[bin]]
                name = "foo"
        "#)
        .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
        .file("d1/Cargo.toml", r#"
            [package]
            name = "d1"
            version = "0.0.1"
            authors = []

            [[bin]]
                name = "d1"
        "#)
        .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
        .file("d2/Cargo.toml", r#"
            [package]
            name = "d2"
            version = "0.0.1"
            authors = []

            [[bin]]
                name = "d2"
        "#)
        .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
        .build();

    assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("d2")
                                        .arg("-p").arg("foo"),
                execs().with_status(0));

    let d1_path = &p.build_dir().join("debug")
                                .join(format!("d1{}", env::consts::EXE_SUFFIX));
    let d2_path = &p.build_dir().join("debug")
                                .join(format!("d2{}", env::consts::EXE_SUFFIX));

    assert_that(&p.bin("foo"), existing_file());
    assert_that(d1_path, existing_file());
    assert_that(d2_path, existing_file());

    assert_that(p.cargo("clean").arg("-p").arg("d1").arg("-p").arg("d2")
                                .cwd(&p.root().join("src")),
                execs().with_status(0).with_stdout(""));
    assert_that(&p.bin("foo"), existing_file());
    assert_that(d1_path, is_not(existing_file()));
    assert_that(d2_path, is_not(existing_file()));
}

#[test]
fn clean_release() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "")
        .build();

    assert_that(p.cargo("build").arg("--release"),
                execs().with_status(0));

    assert_that(p.cargo("clean").arg("-p").arg("foo"),
                execs().with_status(0));
    assert_that(p.cargo("build").arg("--release"),
                execs().with_status(0).with_stdout(""));

    assert_that(p.cargo("clean").arg("-p").arg("foo").arg("--release"),
                execs().with_status(0));
    assert_that(p.cargo("build").arg("--release"),
                execs().with_status(0).with_stderr("\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
"));
}

#[test]
fn build_script() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
            build = "build.rs"
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("build.rs", r#"
            use std::path::PathBuf;
            use std::env;

            fn main() {
                let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
                if env::var("FIRST").is_ok() {
                    std::fs::File::create(out.join("out")).unwrap();
                } else {
                    assert!(!std::fs::metadata(out.join("out")).is_ok());
                }
            }
        "#)
        .file("a/src/lib.rs", "")
        .build();

    assert_that(p.cargo("build").env("FIRST", "1"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("foo"),
                execs().with_status(0));
    assert_that(p.cargo("build").arg("-v"),
                execs().with_status(0).with_stderr("\
[COMPILING] foo v0.0.1 ([..])
[RUNNING] `rustc [..] build.rs [..]`
[RUNNING] `[..]build-script-build`
[RUNNING] `rustc [..] src[/]main.rs [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn clean_git() {
    let git = git::new("dep", |project| {
        project.file("Cargo.toml", r#"
            [project]
            name = "dep"
            version = "0.5.0"
            authors = []
        "#)
        .file("src/lib.rs", "")
    }).unwrap();

    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            dep = {{ git = '{}' }}
        "#, git.url()))
        .file("src/main.rs", "fn main() {}")
        .build();

    assert_that(p.cargo("build"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("dep"),
                execs().with_status(0).with_stdout(""));
    assert_that(p.cargo("build"),
                execs().with_status(0));
}

#[test]
fn registry() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            bar = "0.1"
        "#)
        .file("src/main.rs", "fn main() {}")
        .build();

    Package::new("bar", "0.1.0").publish();

    assert_that(p.cargo("build"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("bar"),
                execs().with_status(0).with_stdout(""));
    assert_that(p.cargo("build"),
                execs().with_status(0));
}

#[test]
fn clean_verbose(){
    let p = project("foo")
    .file("Cargo.toml", r#"
        [package]
        name = "foo"
        version = "0.0.1"

        [dependencies]
        bar = "0.1"
    "#)
    .file("src/main.rs", "fn main() {}")
    .build();

    Package::new("bar", "0.1.0").publish();

    assert_that(p.cargo("build"),
                execs().with_status(0));
    assert_that(p.cargo("clean").arg("-p").arg("bar").arg("--verbose"),
                execs().with_status(0).with_stderr("\
[REMOVING] [..]
[REMOVING] [..]
"));
    assert_that(p.cargo("build"),
            execs().with_status(0));
}
<|endoftext|>


<commit_before>mod helper;

#[cfg(target_os = "linux")]
mod unix;
<commit_msg>fix: Don't compile test helper on non-linux<commit_after>#[cfg(target_os = "linux")]
mod helper;

#[cfg(target_os = "linux")]
mod unix;
<|endoftext|>