<commit_before>use primal_bit::{BitVec};
use std::{cmp};

use wheel;
use primal_smallsieve::Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::WheelInfo>,
    presieve: BitVec,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = (32 << 10);
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

const PRESIEVE_PROD: usize = 2 * 3 * 5 * 7 * 11 * 13;
const PRESIEVE_PRIMES: &'static [usize] = &[2, 3, 5, 7, 11, 13];
const PRESIEVE_NEXT: usize = 17;
const PRESIEVE_ACTIVE: bool = true;

fn bits_for(x: usize) -> usize {
    (x * wheel::BYTE_SIZE + wheel::BYTE_MODULO - 1) / wheel::BYTE_MODULO
}

#[inline(never)]
fn compute_presieve(limit_bits: usize) -> BitVec {
    assert!(PRESIEVE_ACTIVE);
    let len = cmp::min(bits_for(PRESIEVE_PROD),
                       limit_bits);
    let mut bitv = BitVec::from_elem(len, false);

    // this is silly and should be done with a sieve that only uses
    // the primes in PRESIEVE_PRIMES.
    for i in 0..len {
        let true_ = wheel::from_bit_index(i);
        fn gcd(x: usize, y: usize) -> usize {
            if y == 0 { x }
            else { gcd(y, x % y) }
        }
        if gcd(true_, PRESIEVE_PROD) != 1 {
            bitv.set(i, true)
        }
    }
    bitv
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let mut current = match wheel::MODULO {
            6 => 5,
            30 => 7,
            210 => 11,
            _ => unimplemented!(),
        };
        let low = 0;

        let elems = cmp::min(bits_for(limit), SEG_ELEMS);
        let presieve = if PRESIEVE_ACTIVE {
            current = PRESIEVE_NEXT;
            compute_presieve(elems)
        } else {
            BitVec::new()
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }

    pub fn very_small_sieve(&mut self, low: usize) {
        let offset = (low % PRESIEVE_PROD) * wheel::BYTE_SIZE / wheel::BYTE_MODULO / 8;

        copy_all(self.sieve.as_bytes_mut(),
                 self.presieve.as_bytes(),
                 offset);
        fn copy_all(mut dst: &mut [u8], src: &[u8], init_offset: usize) {
            let mut pos = 0;
            // pre-fill data at the start, as a rotation of `src`.
            pos += memcpy(&mut dst[pos..], &src[init_offset..]);
            if pos >= dst.len() { return }

            pos += memcpy(&mut dst[pos..], &src[..init_offset]);
            if pos >= dst.len() { return }

            // progressively copy the prefix to the rest of the
            // vector, doubling each time.
            while pos < dst.len() {
                let (filled, unfilled) = dst.split_at_mut(pos);
                pos += memcpy(unfilled, filled);
            }
        }
        fn memcpy<'d>(dst: &'d mut [u8], src: &[u8]) -> usize {
            use std::ptr;
            let l = cmp::min(dst.len(), src.len());
            unsafe {
                ptr::copy(src.as_ptr(), dst.as_mut_ptr(), l);
            }
            l
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();
        let top = bytes.len();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    let mut si1 = wi1.sieve_index;
                    let mut wi_1 = wi1.wheel_index;
                    let p1 = wi1.prime;
                    let mut si2 = wi2.sieve_index;
                    let mut wi_2 = wi2.wheel_index;
                    let p2 = wi2.prime;

                    while si1 < top && si2 < top {
                        wheel::set_bit(bytes, &mut si1, &mut wi_1, p1);
                        wheel::set_bit(bytes, &mut si2, &mut wi_2, p2);
                    }
                    while si1 < top {
                        wheel::set_bit(bytes, &mut si1, &mut wi_1, p1);
                    }
                    while si2 < top {
                        wheel::set_bit(bytes, &mut si2, &mut wi_2, p2);
                    }

                    // if this wraps, we've hit the limit, and so won't be
                    // continuing, so whatever, it can be junk.
                    wi1.sieve_index = si1.wrapping_sub(top);
                    wi1.wheel_index = wi_1;
                    wi2.sieve_index = si2.wrapping_sub(top);
                    wi2.wheel_index = wi_2;
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            let mut si = wi.sieve_index;
            let mut wi_ = wi.wheel_index;
            let p = wi.prime;
            while si < top {
                wheel::set_bit(bytes, &mut si, &mut wi_, p);
            }
            // if this wraps, we've hit the limit, and so won't be
            // continuing, so whatever, it can be junk.
            wi.sieve_index = si.wrapping_sub(top);
            wi.wheel_index = wi_;
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                self.primes.push(wheel::compute_wheel_elem(s, low));
            }
            s += 1
        }

        self.current = s;
        if PRESIEVE_ACTIVE && self.presieve.len() > 0 {
            self.very_small_sieve(low);
        }
        self.direct_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            if PRESIEVE_ACTIVE {
                // but these are
                for &x in PRESIEVE_PRIMES {
                    let (use_, idx) = wheel::bit_index(x);
                    if use_ {
                        self.sieve.set(idx, false)
                    }
                }
            }
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<commit_msg>sieve: allow counting primes in a streaming manner.<commit_after>use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;
use primal_smallsieve::Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::WheelInfo>,
    presieve: BitVec,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = (32 << 10);
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

const PRESIEVE_PROD: usize = 2 * 3 * 5 * 7 * 11 * 13;
const PRESIEVE_PRIMES: &'static [usize] = &[2, 3, 5, 7, 11, 13];
const PRESIEVE_NEXT: usize = 17;
const PRESIEVE_ACTIVE: bool = true;

fn bits_for(x: usize) -> usize {
    (x * wheel::BYTE_SIZE + wheel::BYTE_MODULO - 1) / wheel::BYTE_MODULO
}

#[inline(never)]
fn compute_presieve(limit_bits: usize) -> BitVec {
    assert!(PRESIEVE_ACTIVE);
    let len = cmp::min(bits_for(PRESIEVE_PROD),
                       limit_bits);
    let mut bitv = BitVec::from_elem(len, false);

    // this is silly and should be done with a sieve that only uses
    // the primes in PRESIEVE_PRIMES.
    for i in 0..len {
        let true_ = wheel::from_bit_index(i);
        fn gcd(x: usize, y: usize) -> usize {
            if y == 0 { x }
            else { gcd(y, x % y) }
        }
        if gcd(true_, PRESIEVE_PROD) != 1 {
            bitv.set(i, true)
        }
    }
    bitv
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let mut current = match wheel::MODULO {
            6 => 5,
            30 => 7,
            210 => 11,
            _ => unimplemented!(),
        };
        let low = 0;

        let elems = cmp::min(bits_for(limit), SEG_ELEMS);
        let presieve = if PRESIEVE_ACTIVE {
            current = PRESIEVE_NEXT;
            compute_presieve(elems)
        } else {
            BitVec::new()
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    pub fn count_upto(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += 8 * bytes.len() - hamming::weight(bytes) as usize;
                }
                let (tweak_byte, tweak_bit) = (tweak / 8, tweak % 8);
                let (_, last) = sieve.next().unwrap();
                let bytes = last.as_bytes();
                count += 8 * tweak_byte - hamming::weight(&bytes[..tweak_byte]) as usize;
                let byte = bytes[tweak_byte];
                for i in 0..tweak_bit + includes as usize {
                    count += (byte & (1 << i) == 0) as usize
                }
                count
            }
        }
    }

    pub fn very_small_sieve(&mut self, low: usize) {
        let offset = (low % PRESIEVE_PROD) * wheel::BYTE_SIZE / wheel::BYTE_MODULO / 8;

        copy_all(self.sieve.as_bytes_mut(),
                 self.presieve.as_bytes(),
                 offset);
        fn copy_all(mut dst: &mut [u8], src: &[u8], init_offset: usize) {
            let mut pos = 0;
            // pre-fill data at the start, as a rotation of `src`.
            pos += memcpy(&mut dst[pos..], &src[init_offset..]);
            if pos >= dst.len() { return }

            pos += memcpy(&mut dst[pos..], &src[..init_offset]);
            if pos >= dst.len() { return }

            // progressively copy the prefix to the rest of the
            // vector, doubling each time.
            while pos < dst.len() {
                let (filled, unfilled) = dst.split_at_mut(pos);
                pos += memcpy(unfilled, filled);
            }
        }
        fn memcpy<'d>(dst: &'d mut [u8], src: &[u8]) -> usize {
            use std::ptr;
            let l = cmp::min(dst.len(), src.len());
            unsafe {
                ptr::copy(src.as_ptr(), dst.as_mut_ptr(), l);
            }
            l
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();
        let top = bytes.len();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    let mut si1 = wi1.sieve_index;
                    let mut wi_1 = wi1.wheel_index;
                    let p1 = wi1.prime;
                    let mut si2 = wi2.sieve_index;
                    let mut wi_2 = wi2.wheel_index;
                    let p2 = wi2.prime;

                    while si1 < top && si2 < top {
                        wheel::set_bit(bytes, &mut si1, &mut wi_1, p1);
                        wheel::set_bit(bytes, &mut si2, &mut wi_2, p2);
                    }
                    while si1 < top {
                        wheel::set_bit(bytes, &mut si1, &mut wi_1, p1);
                    }
                    while si2 < top {
                        wheel::set_bit(bytes, &mut si2, &mut wi_2, p2);
                    }

                    // if this wraps, we've hit the limit, and so won't be
                    // continuing, so whatever, it can be junk.
                    wi1.sieve_index = si1.wrapping_sub(top);
                    wi1.wheel_index = wi_1;
                    wi2.sieve_index = si2.wrapping_sub(top);
                    wi2.wheel_index = wi_2;
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            let mut si = wi.sieve_index;
            let mut wi_ = wi.wheel_index;
            let p = wi.prime;
            while si < top {
                wheel::set_bit(bytes, &mut si, &mut wi_, p);
            }
            // if this wraps, we've hit the limit, and so won't be
            // continuing, so whatever, it can be junk.
            wi.sieve_index = si.wrapping_sub(top);
            wi.wheel_index = wi_;
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                self.primes.push(wheel::compute_wheel_elem(s, low));
            }
            s += 1
        }

        self.current = s;
        if PRESIEVE_ACTIVE && self.presieve.len() > 0 {
            self.very_small_sieve(low);
        }
        self.direct_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            if PRESIEVE_ACTIVE {
                // but these are
                for &x in PRESIEVE_PRIMES {
                    let (use_, idx) = wheel::bit_index(x);
                    if use_ {
                        self.sieve.set(idx, false)
                    }
                }
            }
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<|endoftext|>


<commit_before>use diesel::*;

use helpers::connection;

table! {
    my_structs (foo) {
        foo -> Integer,
        bar -> Integer,
    }
}

#[test]
fn named_struct_definition() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct MyStruct {
        foo: i32,
        bar: i32,
    }

    let conn = &mut connection();
    let data = my_structs::table
        .select(MyStruct::as_select())
        .get_result(conn);
    assert!(data.is_err());
}

#[test]
fn tuple_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct MyStruct(
        #[diesel(column_name = foo)] i32,
        #[diesel(column_name = bar)] i32,
    );

    let conn = &mut connection();
    let data = my_structs::table
        .select(MyStruct::as_select())
        .get_result(conn);
    assert!(data.is_err());
}

// FIXME: Test usage with renamed columns

#[test]
fn embedded_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A<B> {
        foo: i32,
        #[diesel(embed)]
        b: B,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct C {
        bar: i32,
    }

    let conn = &mut connection();
    let data = my_structs::table
        .select(A::<C>::as_select())
        .get_result(conn);
    assert!(data.is_err());
}

#[test]
fn embedded_option() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: Option<B>,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct B {
        bar: i32,
    }

    let conn = &mut connection();
    let data = my_structs::table.select(A::as_select()).get_result(conn);
    assert!(data.is_err());
}

#[test]
fn embedded_option_with_nullable_field() {
    table! {
        my_structs (foo) {
            foo -> Integer,
            bar -> Nullable<Integer>,
        }
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: Option<B>,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct B {
        bar: Option<i32>,
    }

    let conn = &mut connection();
    let data = my_structs::table.select(A::as_select()).get_result(conn);
    assert!(data.is_err());
}

#[test]
fn manually_specified_expression() {
    table! {
        my_structs (foo) {
            foo -> Integer,
            bar -> Nullable<Text>,
        }
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A {
        foo: i32,
        #[diesel(
            select_expression = my_structs::bar.is_not_null(),
            select_expression_type = dsl::IsNotNull<my_structs::bar>
        )]
        bar_is_set: bool,
    }

    let conn = &mut connection();
    let data = my_structs::table.select(A::as_select()).get_result(conn);
    assert!(data.is_err());
}
<commit_msg>Improve manually_specified_expression test to test for tuples<commit_after>use diesel::*;

use helpers::connection;

table! {
    my_structs (foo) {
        foo -> Integer,
        bar -> Integer,
    }
}

#[test]
fn named_struct_definition() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct MyStruct {
        foo: i32,
        bar: i32,
    }

    let conn = &mut connection();
    let data = my_structs::table
        .select(MyStruct::as_select())
        .get_result(conn);
    assert!(data.is_err());
}

#[test]
fn tuple_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct MyStruct(
        #[diesel(column_name = foo)] i32,
        #[diesel(column_name = bar)] i32,
    );

    let conn = &mut connection();
    let data = my_structs::table
        .select(MyStruct::as_select())
        .get_result(conn);
    assert!(data.is_err());
}

// FIXME: Test usage with renamed columns

#[test]
fn embedded_struct() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A<B> {
        foo: i32,
        #[diesel(embed)]
        b: B,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct C {
        bar: i32,
    }

    let conn = &mut connection();
    let data = my_structs::table
        .select(A::<C>::as_select())
        .get_result(conn);
    assert!(data.is_err());
}

#[test]
fn embedded_option() {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: Option<B>,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct B {
        bar: i32,
    }

    let conn = &mut connection();
    let data = my_structs::table.select(A::as_select()).get_result(conn);
    assert!(data.is_err());
}

#[test]
fn embedded_option_with_nullable_field() {
    table! {
        my_structs (foo) {
            foo -> Integer,
            bar -> Nullable<Integer>,
        }
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A {
        foo: i32,
        #[diesel(embed)]
        b: Option<B>,
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct B {
        bar: Option<i32>,
    }

    let conn = &mut connection();
    let data = my_structs::table.select(A::as_select()).get_result(conn);
    assert!(data.is_err());
}

#[test]
fn manually_specified_expression() {
    table! {
        my_structs (foo) {
            foo -> Integer,
            bar -> Nullable<Text>,
            some_int -> Nullable<Integer>,
        }
    }

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable, Selectable)]
    #[diesel(table_name = my_structs)]
    struct A {
        foo: i32,
        #[diesel(
            select_expression = (my_structs::bar.is_not_null(), my_structs::some_int),
            select_expression_type = (dsl::IsNotNull<my_structs::bar>, my_structs::some_int),
        )]
        bar_is_set_and_some_int: (bool, Option<i32>),
    }

    let conn = &mut connection();
    let data = my_structs::table.select(A::as_select()).get_result(conn);
    assert!(data.is_err());
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

// Marauder is turn-based strategy game with hex grid.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use std::f32::consts::{
  PI,
  FRAC_PI_2
};
use std::num::{
  sqrt,
  pow,
  abs,
  sin,
  cos
};
use std::option;
use gltypes = gl::types;
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4
};
use cgmath::vector::{
  Vec3,
  Vec2,
  Vector
};
use cgmath::projection;
use cgmath::angle;

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<u32> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [gltypes::GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

pub struct Visualizer {
  hex_ex_radius: gltypes::GLfloat,
  hex_in_radius: gltypes::GLfloat
}

impl Visualizer {
  pub fn new() -> Visualizer {
    let hex_ex_radius: gltypes::GLfloat = 1.0 / 2.0;
    let hex_in_radius = sqrt(
        pow(hex_ex_radius, 2.0) - pow(hex_ex_radius / 2.0, 2.0));
    let visualizer = Visualizer {
      hex_ex_radius: hex_ex_radius,
      hex_in_radius: hex_in_radius
    };
    visualizer
  }

  pub fn dist(a: Vec2<f32>, b: Vec2<f32>) -> f32 {
    let dx = abs(b.x - a.x);
    let dy = abs(b.y - a.y);
    sqrt(pow(dx, 2.0) + pow(dy, 2.0))
  }

  pub fn v2i_to_v2f(&self, i: Vec2<i32>) -> Vec2<f32> {
    let v = Vec2 {
      x: (i.x as f32) * self.hex_in_radius * 2.0,
      y: (i.y as f32) * self.hex_ex_radius * 1.5
    };
    if i.y % 2 == 0 {
      Vec2{x: v.x + self.hex_in_radius, y: v.y}
    } else {
      v
    }
  }

  pub fn index_to_circle_vertex(&self, count: int, i: int) -> Vec2<f32> {
    let n = FRAC_PI_2 + 2.0 * PI * (i as f32) / (count as f32);
    Vec2{x: cos(n), y: sin(n)}.mul_s(self.hex_ex_radius)
  }

  pub fn index_to_hex_vertex(&self, i: int) -> Vec2<f32> {
    self.index_to_circle_vertex(6, i)
  }
}

fn compile_shader(src: &str, shader_type: gltypes::GLenum) -> gltypes::GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut gltypes::GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(
    vertex_shader: gltypes::GLuint,
    fragment_shader: gltypes::GLuint
) -> gltypes::GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len: gltypes::GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut gltypes::GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

pub struct Win {
  vertex_shader: gltypes::GLuint,
  fragment_shader: gltypes::GLuint,
  program: gltypes::GLuint,
  vertex_buffer_obj: gltypes::GLuint,
  matrix_id: gltypes::GLint,
  projection_matrix: Mat4<f32>,
  window: Option<glfw::Window>
}

fn get_projection_matrix() -> Mat4<f32> {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  projection::perspective(
    fov, ratio, display_range_min, display_range_max
  )
}

impl Win {
  pub fn new() -> Win {
    let mut win = Win {
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      projection_matrix: get_projection_matrix(),
      window: option::None
    };
    win.init_glfw();
    win.init_opengl();
    win.init_model();
    win
  }

  fn init_model(&mut self) {
    unsafe {
      // Create a Vertex Buffer Object
      gl::GenBuffers(1, &mut self.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);

      // Copy vertex data to VBO
      let float_size = std::mem::size_of::<gltypes::GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as gltypes::GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(self.program);
      gl::BindFragDataLocation(
        self.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        self.program, "position".to_c_str().unwrap()) as gltypes::GLuint;
      gl::EnableVertexAttribArray(pos_attr);

      let size = 3;
      let normalized = gl::FALSE;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      self.matrix_id = gl::GetUniformLocation(
        self.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }
  }

  fn init_glfw(&mut self) {
    glfw::set_error_callback(~glfw::LogErrorHandler);
    glfw::init();
    self.window = option::Some(
      glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    );
  }

  fn init_opengl(&mut self) {
    // glfw::window_hint::context_version(3, 2);
    let window = self.window.get_ref();
    window.make_context_current();
    window.set_cursor_pos_callback(~CursorPosContext);
    window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    self.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    self.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    self.program = link_program(self.vertex_shader, self.fragment_shader);
  }

  pub fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
    }
  }

  fn update_matrices(&self) {
    let mut mvp_matrix = self.projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);

      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform for each model
      // you render, since the model_view_proj_matrix will be
      // different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  pub fn draw(&self) {
    self.update_matrices();
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);
    self.window.get_ref().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.window.get_ref().should_close()
  }

  pub fn process_events(&self) {
    glfw::poll_events();
  }
}

impl Drop for Win {
  fn drop(&mut self) {
    self.cleanup_opengl();

    // destroy glfw::Window before terminating glfw
    self.window = option::None;

    glfw::terminate();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    if action != glfw::Press {
      return;
    }
    match key {
      glfw::KeyEscape | glfw::KeyQ
                     => window.set_should_close(true),
      glfw::KeySpace => println!("space"),
      glfw::KeyUp    => unsafe { CAMERA_POS.y -= distance },
      glfw::KeyDown  => unsafe { CAMERA_POS.y += distance },
      glfw::KeyRight => unsafe { CAMERA_POS.x -= distance },
      glfw::KeyLeft  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>win.rs: Moved VERTEX_DATA to Win struct<commit_after>// See LICENSE file for copyright and license details.

// Marauder is turn-based strategy game with hex grid.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use std::f32::consts::{
  PI,
  FRAC_PI_2
};
use std::num::{
  sqrt,
  pow,
  abs,
  sin,
  cos
};
use std::option;
use gltypes = gl::types;
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4
};
use cgmath::vector::{
  Vec3,
  Vec2,
  Vector
};
use cgmath::projection;
use cgmath::angle;

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<u32> = Vec2{x: 640, y: 480};

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

pub struct Visualizer {
  hex_ex_radius: gltypes::GLfloat,
  hex_in_radius: gltypes::GLfloat
}

impl Visualizer {
  pub fn new() -> Visualizer {
    let hex_ex_radius: gltypes::GLfloat = 1.0 / 2.0;
    let hex_in_radius = sqrt(
        pow(hex_ex_radius, 2.0) - pow(hex_ex_radius / 2.0, 2.0));
    let visualizer = Visualizer {
      hex_ex_radius: hex_ex_radius,
      hex_in_radius: hex_in_radius
    };
    visualizer
  }

  pub fn dist(a: Vec2<f32>, b: Vec2<f32>) -> f32 {
    let dx = abs(b.x - a.x);
    let dy = abs(b.y - a.y);
    sqrt(pow(dx, 2.0) + pow(dy, 2.0))
  }

  pub fn v2i_to_v2f(&self, i: Vec2<i32>) -> Vec2<f32> {
    let v = Vec2 {
      x: (i.x as f32) * self.hex_in_radius * 2.0,
      y: (i.y as f32) * self.hex_ex_radius * 1.5
    };
    if i.y % 2 == 0 {
      Vec2{x: v.x + self.hex_in_radius, y: v.y}
    } else {
      v
    }
  }

  pub fn index_to_circle_vertex(&self, count: int, i: int) -> Vec2<f32> {
    let n = FRAC_PI_2 + 2.0 * PI * (i as f32) / (count as f32);
    Vec2{x: cos(n), y: sin(n)}.mul_s(self.hex_ex_radius)
  }

  pub fn index_to_hex_vertex(&self, i: int) -> Vec2<f32> {
    self.index_to_circle_vertex(6, i)
  }
}

fn compile_shader(src: &str, shader_type: gltypes::GLenum) -> gltypes::GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut gltypes::GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(
    vertex_shader: gltypes::GLuint,
    fragment_shader: gltypes::GLuint
) -> gltypes::GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len: gltypes::GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut gltypes::GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

pub struct Win {
  vertex_shader: gltypes::GLuint,
  fragment_shader: gltypes::GLuint,
  program: gltypes::GLuint,
  vertex_buffer_obj: gltypes::GLuint,
  matrix_id: gltypes::GLint,
  projection_matrix: Mat4<f32>,
  window: Option<glfw::Window>,
  vertex_data: ~[gltypes::GLfloat]
}

fn get_projection_matrix() -> Mat4<f32> {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  projection::perspective(
    fov, ratio, display_range_min, display_range_max
  )
}

impl Win {
  pub fn new() -> Win {
    let vertex_data = ~[
       0.0,  1.0, 0.0,
       2.0, -1.0, 0.0,
      -2.0, -1.0, 0.0,

      0.0,  1.0,  0.0,
      0.0, -1.0,  2.0,
      0.0, -1.0, -2.0
    ];
    let mut win = Win {
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      projection_matrix: get_projection_matrix(),
      window: option::None,
      vertex_data: vertex_data
    };
    win.init_glfw();
    win.init_opengl();
    win.init_model();
    win
  }

  fn init_model(&mut self) {
    unsafe {
      // Create a Vertex Buffer Object
      gl::GenBuffers(1, &mut self.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);

      // Copy vertex data to VBO
      let float_size = std::mem::size_of::<gltypes::GLfloat>();
      let vertices_ptr = (self.vertex_data.len() * float_size)
        as gltypes::GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&self.vertex_data[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(self.program);
      gl::BindFragDataLocation(
        self.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        self.program, "position".to_c_str().unwrap()) as gltypes::GLuint;
      gl::EnableVertexAttribArray(pos_attr);

      let size = 3;
      let normalized = gl::FALSE;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      self.matrix_id = gl::GetUniformLocation(
        self.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }
  }

  fn init_glfw(&mut self) {
    glfw::set_error_callback(~glfw::LogErrorHandler);
    glfw::init();
    self.window = option::Some(
      glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    );
  }

  fn init_opengl(&mut self) {
    // glfw::window_hint::context_version(3, 2);
    let window = self.window.get_ref();
    window.make_context_current();
    window.set_cursor_pos_callback(~CursorPosContext);
    window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    self.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    self.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    self.program = link_program(self.vertex_shader, self.fragment_shader);
  }

  pub fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
    }
  }

  fn update_matrices(&self) {
    let mut mvp_matrix = self.projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);

      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform for each model
      // you render, since the model_view_proj_matrix will be
      // different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  pub fn draw(&self) {
    self.update_matrices();
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::DrawArrays(gl::TRIANGLES, 0, self.vertex_data.len() as i32);
    self.window.get_ref().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.window.get_ref().should_close()
  }

  pub fn process_events(&self) {
    glfw::poll_events();
  }
}

impl Drop for Win {
  fn drop(&mut self) {
    self.cleanup_opengl();

    // destroy glfw::Window before terminating glfw
    self.window = option::None;

    glfw::terminate();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    if action != glfw::Press {
      return;
    }
    match key {
      glfw::KeyEscape | glfw::KeyQ
                     => window.set_should_close(true),
      glfw::KeySpace => println!("space"),
      glfw::KeyUp    => unsafe { CAMERA_POS.y -= distance },
      glfw::KeyDown  => unsafe { CAMERA_POS.y += distance },
      glfw::KeyRight => unsafe { CAMERA_POS.x -= distance },
      glfw::KeyLeft  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>#![crate_id = "twobit#0.2"]
#![crate_type = "dylib"]
#![feature(macro_rules)]

extern crate native;
extern crate rustrt;

use std::os::MemoryMap;
use std::collections::hashmap::HashMap;
use std::io::{ IoResult, IoError };

use rustrt::rtio::RtioFileStream;

#[deriving(Show)]
struct Block { start: u32, length: u32 }

struct Sequence {
	n_dna_bases: u32,
	unk_blocks: Vec<Block>,
	mask_blocks: Vec<Block>,
	dna_start: *mut u8
}

impl Sequence {
	fn range<'a>(&'a self, start: u32, end: u32) -> SeqRange<'a> {
		let mut rsize = (end - start + 1) as uint;
		let mut end = end;

		if end >= self.n_dna_bases {
			let rest = rsize - self.n_dna_bases as uint;
			end = self.n_dna_bases - 1;
			rsize = (end - start + 1) as uint;

			// seq range chained with an iterator that repeats the same value
			SeqRange {
				rsize: rsize,
				ptr: unsafe { self.dna_start.offset( (start / 4) as int) },
				idx: 0u,
				offset: (start % 4) as uint,
				unk_blocks: &self.unk_blocks,
				ub_exhausted: self.unk_blocks.len() == 0,
				ub_idx: 0,
				ub_start: if self.unk_blocks.len() > 0 { self.unk_blocks.get(0).start as uint } else { 0 },
				ub_end: if self.unk_blocks.len() > 0 { (self.unk_blocks.get(0).start + self.unk_blocks.get(0).length - 1) as uint } else { 0 },
				n_more: rest
			}
		} else {
			SeqRange {
				rsize: rsize,
				ptr: unsafe { self.dna_start.offset( (start / 4) as int) },
				idx: 0u,
				offset: (start % 4) as uint,
				unk_blocks: &self.unk_blocks,
				ub_exhausted: self.unk_blocks.len() == 0,
				ub_idx: 0,
				ub_start: if self.unk_blocks.len() > 0 { self.unk_blocks.get(0).start as uint } else { 0 },
				ub_end: if self.unk_blocks.len() > 0 { (self.unk_blocks.get(0).start + self.unk_blocks.get(0).length - 1) as uint } else { 0 },
				n_more: 0
			}
		}
	}

	fn string(&self, start: u32, end: u32) -> String {
		String::from_utf8(self.range(start, end).collect()).unwrap()
	}
}

struct SeqRange<'a> {
	rsize: uint,
	ptr: * mut u8,
	idx: uint,
	offset: uint,
	unk_blocks: &'a Vec<Block>,
	ub_exhausted: bool,
	ub_idx: uint,
	ub_start: uint,
	ub_end: uint,
	n_more: uint
}

impl<'a> SeqRange<'a> {
	#[inline]
	fn increment_idx(&mut self) {
		self.idx = self.idx + 1;
		self.offset = self.offset + 1;
		if self.offset == 4 {
			self.offset = 0;
			self.ptr = unsafe { self.ptr.offset(1) };
		}
	}
}

impl<'a> Iterator<u8> for SeqRange<'a> {
	fn next(&mut self) -> Option<u8> {
		if self.idx == self.rsize {
			if self.n_more > 0 {
				self.n_more = self.n_more - 1;
				return Some('N' as u8);
			}
			return None;
		} else {
			unsafe {
				// are we within a block?
				if !self.ub_exhausted {
					loop {
						if self.idx > self.ub_end {
							self.ub_idx = self.ub_idx + 1;
							if self.ub_idx == self.unk_blocks.len() {
								self.ub_exhausted = true;
								break;
							} else {
								self.ub_start = self.unk_blocks.get(self.ub_idx).start as uint;
								self.ub_end = self.ub_start + self.unk_blocks.get(self.ub_idx).length as uint - 1;
							}
						} else if self.idx >= self.ub_start {
							self.increment_idx();

							return Some('N' as u8);
						} else {
							// outside block, so continue to data collection
							break;
						}
					}
				}

				// no, so collect data
				let result = Some(byte_to_base(*self.ptr, self.offset) as u8);

				self.increment_idx();

				return result;
			}
		}
	}
}

pub struct TwoBit {
	seqs: HashMap<String, Sequence>,

	#[allow(dead_code)]
	data: MemoryMap // this is needed to keep the memory map alive
}

macro_rules! try_rt(
    ($e:expr) => (match $e { Ok(e) => e, Err(rustrt::rtio::IoError{code: code, extra: _, detail: _}) => return Err(IoError::from_errno(code, true)) })
)

fn mmap_read_u32(ptr: * mut u8, offset: uint) -> u32 {
	return unsafe {
		let tmp : *u32 = std::mem::transmute(ptr.offset(offset as int) as *[u8, ..4]);
		*tmp };
}

fn mmap_read_u8(ptr: * mut u8, offset: uint) -> u8 {
	return unsafe {
		*ptr.offset(offset as int)
	};
}

fn read_blocks(data: * mut u8, offset: u32) -> (Vec<Block>, u32) {
	let len = mmap_read_u32(data, offset as uint);
	let mut vec = Vec::<Block>::new();

	if len > 0 {
		let off1 = offset + 4;
		let off2 = offset + 4 + len*4;

		for i in range(0, len) {
			let start = mmap_read_u32(data, (off1 + i*4) as uint);
			let size = mmap_read_u32(data, (off2 + i*4) as uint);

			vec.push(Block{ start: start, length: size });
		}
	}

	return (vec, offset + 4 + 2*len*4);
}

fn mmap_read_index(data: *mut u8, count: u32) -> HashMap<String, Sequence> {
		let mut index = HashMap::with_capacity(count as uint);

		let mut header_start = 16u;

		for _ in range(0, count) {
			let name_size = mmap_read_u8(data, header_start);
			let name = unsafe { String::from_raw_parts(name_size as uint, name_size as uint, data.offset((header_start + 1) as int)) };
			let offset = mmap_read_u32(data, header_start + 1 + name_size as uint);

			// get actual info
			let dna_size = mmap_read_u32(data, offset as uint);

			// unknown blocks
			let (unk_blocks, offset) = read_blocks(data, offset + 4);

			// masked blocks
			let (mask_blocks, offset) = read_blocks(data, offset);

			// actual pointer to DNA data
			let dna_ptr = unsafe { data.offset((offset + 4) as int) }; // + reserved

			index.insert(name, Sequence { n_dna_bases: dna_size, unk_blocks: unk_blocks, mask_blocks: mask_blocks, dna_start: dna_ptr });

			header_start = header_start + 1 + name_size as uint + 4;
		}

		return index;
}

fn byte_to_base(value: u8, offset: uint) -> char {
	let bases = ['T', 'C', 'A', 'G'];
	let rev_offset = 3 - offset;
	let mask = 3 << (rev_offset * 2);
	let idx = (value & mask) >> (rev_offset * 2);

	return bases[idx as uint];
}

impl TwoBit {

	pub fn new(filename: &str) -> IoResult<TwoBit> {
		// open file
		let mut fh = try_rt!(native::io::file::open(&filename.to_c_str(), rustrt::rtio::Open, rustrt::rtio::Read));
		let fs = try_rt!(fh.fstat());

		// build memory map
		let mmap = match MemoryMap::new(fs.size as uint, [ std::os::MapReadable, std::os::MapFd(fh.fd())]) {
			Ok(val) => val,
			Err(_) => return Err(IoError{kind: std::io::OtherIoError, desc: "Memory map failed!", detail: None})
		};

		// TODO: add madvise call

		// validate header
		let val = mmap_read_u32(mmap.data, 0);

		if val != 0x1A412743 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Invalid signature or wrong architecture.", detail: None });
		}

		let val = mmap_read_u32(mmap.data, 4);
		if val != 0 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Unknown file version.", detail: None });
		} // TODO: actually report version found

		let n_sequences = mmap_read_u32(mmap.data, 8);
		if n_sequences == 0 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Zero sequence count.", detail: None });
		}

		let val = mmap_read_u32(mmap.data, 12);
		if val != 0 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Reserved bytes not zero.", detail: None });
		} // TODO: actually report value found

		// parse index
		let index = mmap_read_index(mmap.data, n_sequences);

		return Ok(TwoBit { seqs: index, data: mmap });
	}

	pub fn sequence(&self, chrom: &str, start: u32, end: u32) -> Option<String> {
		match self.seqs.find(&String::from_str(chrom)) {
			Some(ref seq) => Some(seq.string(start, end)),
			None => None
		}
	}

	pub fn sequence_len(&self, chrom: &str) -> Option<u32> {
		match self.seqs.find(&String::from_str(chrom)) {
			Some(&Sequence{ n_dna_bases: n, ..}) => Some(n),
			None => None
		}
	}

	pub fn sequence_names<'a>(&'a self) -> Vec<&'a String> {
		self.seqs.keys().collect()
	}

	pub fn base_frequencies(&self, chrom: &str) -> Option<[f64, ..4]> {
		match self.seqs.find(&String::from_str(chrom)) {
			Some(ref seq) => {
				let mut counts = [0f64, 0.0, 0.0, 0.0];

				for val in seq.range(0, seq.n_dna_bases - 1) {
					let c = val as char;

					match c {
						'A' => counts[0] = counts[0] + 1.0,
						'C' => counts[1] = counts[1] + 1.0,
						'G' => counts[2] = counts[2] + 1.0,
						'T' => counts[3] = counts[3] + 1.0,
						_ => {}
					}
				}

				let sum = counts[0] + counts[1] + counts[2] + counts[3];
				counts[0] = counts[0] / sum;
				counts[1] = counts[1] / sum;
				counts[2] = counts[2] / sum;
				counts[3] = counts[3] / sum;

				Some(counts)
			}
			None => None
		}
	}
}
<commit_msg>Make code cleaner, based on char<commit_after>#![crate_id = "twobit#0.2"]
#![crate_type = "dylib"]
#![feature(macro_rules)]

extern crate native;
extern crate rustrt;

use std::os::MemoryMap;
use std::collections::hashmap::HashMap;
use std::io::{ IoResult, IoError };
use std::iter::FromIterator;

use rustrt::rtio::RtioFileStream;

#[deriving(Show)]
struct Block { start: u32, length: u32 }

struct Sequence {
	n_dna_bases: u32,
	unk_blocks: Vec<Block>,
	mask_blocks: Vec<Block>,
	dna_start: *mut u8
}

impl Sequence {
	fn range<'a>(&'a self, start: u32, end: u32) -> SeqRange<'a> {
		let mut rsize = (end - start + 1) as uint;
		let mut end = end;

		if end >= self.n_dna_bases {
			let rest = rsize - self.n_dna_bases as uint;
			end = self.n_dna_bases - 1;
			rsize = (end - start + 1) as uint;

			// seq range chained with an iterator that repeats the same value
			SeqRange {
				rsize: rsize,
				ptr: unsafe { self.dna_start.offset( (start / 4) as int) },
				idx: 0u,
				offset: (start % 4) as uint,
				unk_blocks: &self.unk_blocks,
				ub_exhausted: self.unk_blocks.len() == 0,
				ub_idx: 0,
				ub_start: if self.unk_blocks.len() > 0 { self.unk_blocks.get(0).start as uint } else { 0 },
				ub_end: if self.unk_blocks.len() > 0 { (self.unk_blocks.get(0).start + self.unk_blocks.get(0).length - 1) as uint } else { 0 },
				n_more: rest
			}
		} else {
			SeqRange {
				rsize: rsize,
				ptr: unsafe { self.dna_start.offset( (start / 4) as int) },
				idx: 0u,
				offset: (start % 4) as uint,
				unk_blocks: &self.unk_blocks,
				ub_exhausted: self.unk_blocks.len() == 0,
				ub_idx: 0,
				ub_start: if self.unk_blocks.len() > 0 { self.unk_blocks.get(0).start as uint } else { 0 },
				ub_end: if self.unk_blocks.len() > 0 { (self.unk_blocks.get(0).start + self.unk_blocks.get(0).length - 1) as uint } else { 0 },
				n_more: 0
			}
		}
	}

	fn string(&self, start: u32, end: u32) -> String {
		FromIterator::from_iter(self.range(start, end))
	}
}

struct SeqRange<'a> {
	rsize: uint,
	ptr: * mut u8,
	idx: uint,
	offset: uint,
	unk_blocks: &'a Vec<Block>,
	ub_exhausted: bool,
	ub_idx: uint,
	ub_start: uint,
	ub_end: uint,
	n_more: uint
}

impl<'a> SeqRange<'a> {
	#[inline]
	fn increment_idx(&mut self) {
		self.idx = self.idx + 1;
		self.offset = self.offset + 1;
		if self.offset == 4 {
			self.offset = 0;
			self.ptr = unsafe { self.ptr.offset(1) };
		}
	}
}

impl<'a> Iterator<char> for SeqRange<'a> {
	fn next(&mut self) -> Option<char> {
		if self.idx == self.rsize {
			if self.n_more > 0 {
				self.n_more = self.n_more - 1;
				return Some('N');
			}
			return None;
		} else {
			unsafe {
				// are we within a block?
				if !self.ub_exhausted {
					loop {
						if self.idx > self.ub_end {
							self.ub_idx = self.ub_idx + 1;
							if self.ub_idx == self.unk_blocks.len() {
								self.ub_exhausted = true;
								break;
							} else {
								self.ub_start = self.unk_blocks.get(self.ub_idx).start as uint;
								self.ub_end = self.ub_start + self.unk_blocks.get(self.ub_idx).length as uint - 1;
							}
						} else if self.idx >= self.ub_start {
							self.increment_idx();

							return Some('N');
						} else {
							// outside block, so continue to data collection
							break;
						}
					}
				}

				// no, so collect data
				let result = Some(byte_to_base(*self.ptr, self.offset));

				self.increment_idx();

				return result;
			}
		}
	}

	fn size_hint(&self) -> (uint, Option<uint>) {
		// lower and upper bound (same)
		let bound = self.rsize - self.idx - self.n_more;
		(bound, Some(bound))
	}
}

pub struct TwoBit {
	seqs: HashMap<String, Sequence>,

	#[allow(dead_code)]
	data: MemoryMap // this is needed to keep the memory map alive
}

macro_rules! try_rt(
    ($e:expr) => (match $e { Ok(e) => e, Err(rustrt::rtio::IoError{code: code, extra: _, detail: _}) => return Err(IoError::from_errno(code, true)) })
)

fn mmap_read_u32(ptr: * mut u8, offset: uint) -> u32 {
	return unsafe {
		let tmp : *u32 = std::mem::transmute(ptr.offset(offset as int) as *[u8, ..4]);
		*tmp };
}

fn mmap_read_u8(ptr: * mut u8, offset: uint) -> u8 {
	return unsafe {
		*ptr.offset(offset as int)
	};
}

fn read_blocks(data: * mut u8, offset: u32) -> (Vec<Block>, u32) {
	let len = mmap_read_u32(data, offset as uint);
	let mut vec = Vec::<Block>::new();

	if len > 0 {
		let off1 = offset + 4;
		let off2 = offset + 4 + len*4;

		for i in range(0, len) {
			let start = mmap_read_u32(data, (off1 + i*4) as uint);
			let size = mmap_read_u32(data, (off2 + i*4) as uint);

			vec.push(Block{ start: start, length: size });
		}
	}

	return (vec, offset + 4 + 2*len*4);
}

fn mmap_read_index(data: *mut u8, count: u32) -> HashMap<String, Sequence> {
		let mut index = HashMap::with_capacity(count as uint);

		let mut header_start = 16u;

		for _ in range(0, count) {
			let name_size = mmap_read_u8(data, header_start);
			let name = unsafe { String::from_raw_parts(name_size as uint, name_size as uint, data.offset((header_start + 1) as int)) };
			let offset = mmap_read_u32(data, header_start + 1 + name_size as uint);

			// get actual info
			let dna_size = mmap_read_u32(data, offset as uint);

			// unknown blocks
			let (unk_blocks, offset) = read_blocks(data, offset + 4);

			// masked blocks
			let (mask_blocks, offset) = read_blocks(data, offset);

			// actual pointer to DNA data
			let dna_ptr = unsafe { data.offset((offset + 4) as int) }; // + reserved

			index.insert(name, Sequence { n_dna_bases: dna_size, unk_blocks: unk_blocks, mask_blocks: mask_blocks, dna_start: dna_ptr });

			header_start = header_start + 1 + name_size as uint + 4;
		}

		return index;
}

fn byte_to_base(value: u8, offset: uint) -> char {
	let bases = ['T', 'C', 'A', 'G'];
	let rev_offset = 3 - offset;
	let mask = 3 << (rev_offset * 2);
	let idx = (value & mask) >> (rev_offset * 2);

	return bases[idx as uint];
}

impl TwoBit {

	pub fn new(filename: &str) -> IoResult<TwoBit> {
		// open file
		let mut fh = try_rt!(native::io::file::open(&filename.to_c_str(), rustrt::rtio::Open, rustrt::rtio::Read));
		let fs = try_rt!(fh.fstat());

		// build memory map
		let mmap = match MemoryMap::new(fs.size as uint, [ std::os::MapReadable, std::os::MapFd(fh.fd())]) {
			Ok(val) => val,
			Err(_) => return Err(IoError{kind: std::io::OtherIoError, desc: "Memory map failed!", detail: None})
		};

		// TODO: add madvise call

		// validate header
		let val = mmap_read_u32(mmap.data, 0);

		if val != 0x1A412743 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Invalid signature or wrong architecture.", detail: None });
		}

		let val = mmap_read_u32(mmap.data, 4);
		if val != 0 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Unknown file version.", detail: None });
		} // TODO: actually report version found

		let n_sequences = mmap_read_u32(mmap.data, 8);
		if n_sequences == 0 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Zero sequence count.", detail: None });
		}

		let val = mmap_read_u32(mmap.data, 12);
		if val != 0 {
			return Err(IoError { kind: std::io::OtherIoError, desc: "Reserved bytes not zero.", detail: None });
		} // TODO: actually report value found

		// parse index
		let index = mmap_read_index(mmap.data, n_sequences);

		return Ok(TwoBit { seqs: index, data: mmap });
	}

	pub fn sequence(&self, chrom: &str, start: u32, end: u32) -> Option<String> {
		match self.seqs.find(&String::from_str(chrom)) {
			Some(ref seq) => Some(seq.string(start, end)),
			None => None
		}
	}

	pub fn sequence_len(&self, chrom: &str) -> Option<u32> {
		match self.seqs.find(&String::from_str(chrom)) {
			Some(&Sequence{ n_dna_bases: n, ..}) => Some(n),
			None => None
		}
	}

	pub fn sequence_names<'a>(&'a self) -> Vec<&'a String> {
		self.seqs.keys().collect()
	}

	pub fn base_frequencies(&self, chrom: &str) -> Option<[f64, ..4]> {
		match self.seqs.find(&String::from_str(chrom)) {
			Some(ref seq) => {
				let mut counts = [0f64, 0.0, 0.0, 0.0];

				for c in seq.range(0, seq.n_dna_bases - 1) {
					match c {
						'A' => counts[0] = counts[0] + 1.0,
						'C' => counts[1] = counts[1] + 1.0,
						'G' => counts[2] = counts[2] + 1.0,
						'T' => counts[3] = counts[3] + 1.0,
						_ => {}
					}
				}

				let sum = counts[0] + counts[1] + counts[2] + counts[3];
				counts[0] = counts[0] / sum;
				counts[1] = counts[1] / sum;
				counts[2] = counts[2] / sum;
				counts[3] = counts[3] / sum;

				Some(counts)
			}
			None => None
		}
	}
}
<|endoftext|>


<commit_before>// Implementation in Rust of a simple Reversi game
// v 0.2.0
// by Enrico Ghiorzi

// Import modules
mod interface;
mod opponents;

extern crate rusthello_lib;
use rusthello_lib::game;

extern crate time;

fn main() {

    // Create a new game and two opponents

    let (light, dark) = interface::start_game();

    let mut game = game::Game::new();

    let start_time = time::precise_time_s();

    // Proceed with turn after turn till the endgame
    loop {
        // Draw the current board and game info
        interface::draw_board(&game);

        // Depending on the status of the game, proceed with the next turn or declare the winner
        match game.get_status() {

            // If the game is running, get the coordinates of the new move from the next player
            game::Status::Running { next_player } => {

                let coord: (usize, usize);
                match next_player {
                    game::Player::Light => coord = light.make_move(&game),
                    game::Player::Dark  => coord = dark.make_move(&game),
                }

                // If the new move is valid, perform it; otherwise panic
                // NB: opponents's make_move method is responsible for returning a legal move
                //     so the program should never print this message unless something goes horribly wrong
                if game.check_move(coord) {
                    game.make_move(coord);
                } else {
                    panic!("Invalid move sent to main!");
                }
            }

            // If the game is ended, exit the loop
            game::Status::Ended => {
                break;
            }
        }
    }

    println!("Time: {}", time::precise_time_s() - start_time);
}
<commit_msg>Removed execution time<commit_after>// Implementation in Rust of a simple Reversi game
// v 0.2.0
// by Enrico Ghiorzi

// Import modules
mod interface;
mod opponents;

extern crate rusthello_lib;
use rusthello_lib::game;

fn main() {

    // Create a new game and two opponents

    let (light, dark) = interface::start_game();

    let mut game = game::Game::new();

    // Proceed with turn after turn till the endgame
    loop {
        // Draw the current board and game info
        interface::draw_board(&game);

        // Depending on the status of the game, proceed with the next turn or declare the winner
        match game.get_status() {

            // If the game is running, get the coordinates of the new move from the next player
            game::Status::Running { next_player } => {

                let coord: (usize, usize);
                match next_player {
                    game::Player::Light => coord = light.make_move(&game),
                    game::Player::Dark  => coord = dark.make_move(&game),
                }

                // If the new move is valid, perform it; otherwise panic
                // NB: opponents's make_move method is responsible for returning a legal move
                //     so the program should never print this message unless something goes horribly wrong
                if game.check_move(coord) {
                    game.make_move(coord);
                } else {
                    panic!("Invalid move sent to main!");
                }
            }

            // If the game is ended, exit the loop
            game::Status::Ended => {
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;
extern crate gcc;
extern crate gl_generator;
#[cfg(feature = "static")]
extern crate meson;
extern crate pkg_config;
extern crate wayland_scanner;

use gl_generator::{Api, Fallbacks, Profile, Registry, StaticGenerator};
use std::{env, io};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::process::Command;

fn main() {
    meson();
    let protocol_header_path =
        generate_protocol_headers().expect("Could not generate header files for wayland protocols");
    let target_dir = env::var("OUT_DIR").expect("$OUT_DIR not set!");
    let generated = bindgen::builder()
        .derive_debug(true)
        .derive_default(true)
        .generate_comments(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_type(r"^xkb_.*$")
        .whitelisted_type(r"^XKB_.*$")
        .whitelisted_function(r"^_?pixman_.*$")
        .whitelisted_function(r"^_?wlr_.*$")
        .whitelisted_function(r"^xkb_.*$")
        .ctypes_prefix("libc")
        .clang_arg("-Iwlroots/include")
        .clang_arg("-Iwlroots/include/wlr")
        // NOTE Necessary because they use the out directory to put
        // pragma information on what features are available in a header file
        // titled "config.h"
        .clang_arg(format!("-I{}{}", target_dir, "/include/"))
        .clang_arg(format!("-I{}", protocol_header_path.to_str().unwrap()))
        .clang_arg("-Iwlroots/include/xcursor")
        .clang_arg("-I/usr/include/pixman-1")
        // Work around bug https://github.com/rust-lang-nursery/rust-bindgen/issues/687
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL")
        .generate().unwrap();

    println!("cargo:rustc-link-lib=dylib=X11");
    println!("cargo:rustc-link-lib=dylib=X11-xcb");
    println!("cargo:rustc-link-lib=dylib=xkbcommon");
    println!("cargo:rustc-link-lib=dylib=xcb");
    println!("cargo:rustc-link-lib=dylib=xcb-composite");
    println!("cargo:rustc-link-lib=dylib=xcb-xfixes");
    println!("cargo:rustc-link-lib=dylib=xcb-image");
    println!("cargo:rustc-link-lib=dylib=xcb-render");
    println!("cargo:rustc-link-lib=dylib=xcb-shm");
    println!("cargo:rustc-link-lib=dylib=xcb-icccm");
    println!("cargo:rustc-link-lib=dylib=xcb-xkb");
    println!("cargo:rustc-link-lib=dylib=wayland-egl");
    println!("cargo:rustc-link-lib=dylib=wayland-client");
    println!("cargo:rustc-link-lib=dylib=wayland-server");
    println!("cargo:rustc-link-lib=dylib=EGL");
    println!("cargo:rustc-link-lib=dylib=GL");
    println!("cargo:rustc-link-lib=dylib=gbm");
    println!("cargo:rustc-link-lib=dylib=drm");
    println!("cargo:rustc-link-lib=dylib=input");
    println!("cargo:rustc-link-lib=dylib=udev");
    println!("cargo:rustc-link-lib=dylib=dbus-1");
    println!("cargo:rustc-link-lib=dylib=pixman-1");

    link_optional_libs();

    if !cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wlroots");
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    // generate the bindings
    generated.write_to_file("src/gen.rs").unwrap();

    generate_protocols();

    // Example Khronos building stuff
    let mut file = File::create(&Path::new(&target_dir).join("bindings.rs")).unwrap();
    Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, [])
        .write_bindings(StaticGenerator, &mut file)
        .unwrap();
}

#[cfg(not(feature = "static"))]
fn meson() {}

#[cfg(feature = "static")]
fn meson() {
    let build_path =
        PathBuf::from(env::var("OUT_DIR").expect("Could not get OUT_DIR env variable"));
    build_path.join("build");
    let build_path_str = build_path.to_str()
                                   .expect("Could not turn build path into a string");
    println!("cargo:rustc-link-search=native=wlroots");
    println!("cargo:rustc-link-search=native={}/lib", build_path_str);
    println!("cargo:rustc-link-search=native={}/lib64", build_path_str);
    println!("cargo:rustc-link-search=native={}/build/", build_path_str);
    if cfg!(feature = "static") {
        println!("cargo:rustc-link-search=native={}/util/", build_path_str);
        println!("cargo:rustc-link-search=native={}/types/", build_path_str);
        println!("cargo:rustc-link-search=native={}/protocol/",
                 build_path_str);
        println!("cargo:rustc-link-search=native={}/xcursor/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xwayland/",
                 build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/", build_path_str);
        println!("cargo:rustc-link-search=native={}/render/", build_path_str);

        println!("cargo:rustc-link-lib=static=wlr_util");
        println!("cargo:rustc-link-lib=static=wlr_types");
        println!("cargo:rustc-link-lib=static=wlr_xcursor");
        println!("cargo:rustc-link-lib=static=wlr_xwayland");
        println!("cargo:rustc-link-lib=static=wlr_backend");
        println!("cargo:rustc-link-lib=static=wlr_render");
        // wayland protocols
        println!("cargo:rustc-link-lib=static=wl_protos");
    }

    meson::build("wlroots", build_path_str);
}

/// Gets the unstable and stable protocols in /usr/share-wayland-protocols and
/// generates server headers for them.
///
/// The path to the folder with the generated headers is returned. It will
/// have two directories, `stable`, and `unstable`.
fn generate_protocol_headers() -> io::Result<PathBuf> {
    let output_dir_str = env::var("OUT_DIR").unwrap();
    let out_path: PathBuf = format!("{}/wayland-protocols", output_dir_str).into();
    fs::create_dir(&out_path).ok();
    let protocols = fs::read_dir("/usr/share/wayland-protocols/stable")?
        .chain(fs::read_dir("/usr/share/wayland-protocols/unstable")?);
    for entry in protocols {
        let entry = entry?;
        for entry in fs::read_dir(entry.path())? {
            let entry = entry?;
            let path = entry.path();
            let mut filename = entry.file_name().into_string().unwrap();
            if filename.ends_with(".xml") {
                let new_length = filename.len() - 4;
                filename.truncate(new_length);
            }
            filename.push_str("-protocol");
            Command::new("wayland-scanner").arg("server-header")
                                           .arg(path.clone())
                                           .arg(format!("{}/{}.h",
                                                        out_path.to_str().unwrap(),
                                                        filename))
                                           .status()
                                           .unwrap();
        }
    }
    Ok(out_path)
}

fn generate_protocols() {
    let output_dir_str = env::var("OUT_DIR").unwrap();

    let output_dir = Path::new(&output_dir_str);

    let protocols = &[("./wlroots/protocol/server-decoration.xml", "server_decoration")];

    for protocol in protocols {
        wayland_scanner::generate_code(protocol.0,
                                       output_dir.join(format!("{}_server_api.rs", protocol.1)),
                                       wayland_scanner::Side::Server);
        wayland_scanner::generate_code(protocol.0,
                                       output_dir.join(format!("{}_client_api.rs", protocol.1)),
                                       wayland_scanner::Side::Client);
        wayland_scanner::generate_interfaces(protocol.0,
                                             output_dir.join(format!("{}_interfaces.rs",
                                                                     protocol.1)));
    }
}
fn link_optional_libs() {
    if cfg!(feature = "libcap") && pkg_config::probe_library("libcap").is_ok() {
        println!("cargo:rustc-link-lib=dylib=cap");
    }
    if cfg!(feature = "systemd") && pkg_config::probe_library("libsystemd").is_ok() {
        println!("cargo:rustc-link-lib=dylib=systemd");
    }
    if cfg!(feature = "elogind") && pkg_config::probe_library("elogind").is_ok() {
        println!("cargo:rustc-link-lib=dylib=elogind");
    }
}
<commit_msg>Improve error if wlroots dir does not exist<commit_after>extern crate bindgen;
extern crate gcc;
extern crate gl_generator;
#[cfg(feature = "static")]
extern crate meson;
extern crate pkg_config;
extern crate wayland_scanner;

use gl_generator::{Api, Fallbacks, Profile, Registry, StaticGenerator};
use std::{env, io};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::process::Command;

fn main() {
    meson();
    let protocol_header_path =
        generate_protocol_headers().expect("Could not generate header files for wayland protocols");
    let target_dir = env::var("OUT_DIR").expect("$OUT_DIR not set!");
    let generated = bindgen::builder()
        .derive_debug(true)
        .derive_default(true)
        .generate_comments(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_type(r"^xkb_.*$")
        .whitelisted_type(r"^XKB_.*$")
        .whitelisted_function(r"^_?pixman_.*$")
        .whitelisted_function(r"^_?wlr_.*$")
        .whitelisted_function(r"^xkb_.*$")
        .ctypes_prefix("libc")
        .clang_arg("-Iwlroots/include")
        .clang_arg("-Iwlroots/include/wlr")
        // NOTE Necessary because they use the out directory to put
        // pragma information on what features are available in a header file
        // titled "config.h"
        .clang_arg(format!("-I{}{}", target_dir, "/include/"))
        .clang_arg(format!("-I{}", protocol_header_path.to_str().unwrap()))
        .clang_arg("-Iwlroots/include/xcursor")
        .clang_arg("-I/usr/include/pixman-1")
        // Work around bug https://github.com/rust-lang-nursery/rust-bindgen/issues/687
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL")
        .generate().unwrap();

    println!("cargo:rustc-link-lib=dylib=X11");
    println!("cargo:rustc-link-lib=dylib=X11-xcb");
    println!("cargo:rustc-link-lib=dylib=xkbcommon");
    println!("cargo:rustc-link-lib=dylib=xcb");
    println!("cargo:rustc-link-lib=dylib=xcb-composite");
    println!("cargo:rustc-link-lib=dylib=xcb-xfixes");
    println!("cargo:rustc-link-lib=dylib=xcb-image");
    println!("cargo:rustc-link-lib=dylib=xcb-render");
    println!("cargo:rustc-link-lib=dylib=xcb-shm");
    println!("cargo:rustc-link-lib=dylib=xcb-icccm");
    println!("cargo:rustc-link-lib=dylib=xcb-xkb");
    println!("cargo:rustc-link-lib=dylib=wayland-egl");
    println!("cargo:rustc-link-lib=dylib=wayland-client");
    println!("cargo:rustc-link-lib=dylib=wayland-server");
    println!("cargo:rustc-link-lib=dylib=EGL");
    println!("cargo:rustc-link-lib=dylib=GL");
    println!("cargo:rustc-link-lib=dylib=gbm");
    println!("cargo:rustc-link-lib=dylib=drm");
    println!("cargo:rustc-link-lib=dylib=input");
    println!("cargo:rustc-link-lib=dylib=udev");
    println!("cargo:rustc-link-lib=dylib=dbus-1");
    println!("cargo:rustc-link-lib=dylib=pixman-1");

    link_optional_libs();

    if !cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wlroots");
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    // generate the bindings
    generated.write_to_file("src/gen.rs").unwrap();

    generate_protocols();

    // Example Khronos building stuff
    let mut file = File::create(&Path::new(&target_dir).join("bindings.rs")).unwrap();
    Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, [])
        .write_bindings(StaticGenerator, &mut file)
        .unwrap();
}

#[cfg(not(feature = "static"))]
fn meson() {}

#[cfg(feature = "static")]
fn meson() {
    let build_path =
        PathBuf::from(env::var("OUT_DIR").expect("Could not get OUT_DIR env variable"));
    build_path.join("build");
    let build_path_str = build_path.to_str()
                                   .expect("Could not turn build path into a string");
    println!("cargo:rustc-link-search=native=wlroots");
    println!("cargo:rustc-link-search=native={}/lib", build_path_str);
    println!("cargo:rustc-link-search=native={}/lib64", build_path_str);
    println!("cargo:rustc-link-search=native={}/build/", build_path_str);
    if cfg!(feature = "static") {
        println!("cargo:rustc-link-search=native={}/util/", build_path_str);
        println!("cargo:rustc-link-search=native={}/types/", build_path_str);
        println!("cargo:rustc-link-search=native={}/protocol/",
                 build_path_str);
        println!("cargo:rustc-link-search=native={}/xcursor/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xwayland/",
                 build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/", build_path_str);
        println!("cargo:rustc-link-search=native={}/render/", build_path_str);

        println!("cargo:rustc-link-lib=static=wlr_util");
        println!("cargo:rustc-link-lib=static=wlr_types");
        println!("cargo:rustc-link-lib=static=wlr_xcursor");
        println!("cargo:rustc-link-lib=static=wlr_xwayland");
        println!("cargo:rustc-link-lib=static=wlr_backend");
        println!("cargo:rustc-link-lib=static=wlr_render");
        // wayland protocols
        println!("cargo:rustc-link-lib=static=wl_protos");
    }

    if Path::new("wlroots").exists() {
        meson::build("wlroots", build_path_str);
    } else {
        panic!("The `wlroots` submodule does not exist");
    }
}

/// Gets the unstable and stable protocols in /usr/share-wayland-protocols and
/// generates server headers for them.
///
/// The path to the folder with the generated headers is returned. It will
/// have two directories, `stable`, and `unstable`.
fn generate_protocol_headers() -> io::Result<PathBuf> {
    let output_dir_str = env::var("OUT_DIR").unwrap();
    let out_path: PathBuf = format!("{}/wayland-protocols", output_dir_str).into();
    fs::create_dir(&out_path).ok();
    let protocols = fs::read_dir("/usr/share/wayland-protocols/stable")?
        .chain(fs::read_dir("/usr/share/wayland-protocols/unstable")?);
    for entry in protocols {
        let entry = entry?;
        for entry in fs::read_dir(entry.path())? {
            let entry = entry?;
            let path = entry.path();
            let mut filename = entry.file_name().into_string().unwrap();
            if filename.ends_with(".xml") {
                let new_length = filename.len() - 4;
                filename.truncate(new_length);
            }
            filename.push_str("-protocol");
            Command::new("wayland-scanner").arg("server-header")
                                           .arg(path.clone())
                                           .arg(format!("{}/{}.h",
                                                        out_path.to_str().unwrap(),
                                                        filename))
                                           .status()
                                           .unwrap();
        }
    }
    Ok(out_path)
}

fn generate_protocols() {
    let output_dir_str = env::var("OUT_DIR").unwrap();

    let output_dir = Path::new(&output_dir_str);

    let protocols = &[("./wlroots/protocol/server-decoration.xml", "server_decoration")];

    for protocol in protocols {
        wayland_scanner::generate_code(protocol.0,
                                       output_dir.join(format!("{}_server_api.rs", protocol.1)),
                                       wayland_scanner::Side::Server);
        wayland_scanner::generate_code(protocol.0,
                                       output_dir.join(format!("{}_client_api.rs", protocol.1)),
                                       wayland_scanner::Side::Client);
        wayland_scanner::generate_interfaces(protocol.0,
                                             output_dir.join(format!("{}_interfaces.rs",
                                                                     protocol.1)));
    }
}
fn link_optional_libs() {
    if cfg!(feature = "libcap") && pkg_config::probe_library("libcap").is_ok() {
        println!("cargo:rustc-link-lib=dylib=cap");
    }
    if cfg!(feature = "systemd") && pkg_config::probe_library("libsystemd").is_ok() {
        println!("cargo:rustc-link-lib=dylib=systemd");
    }
    if cfg!(feature = "elogind") && pkg_config::probe_library("elogind").is_ok() {
        println!("cargo:rustc-link-lib=dylib=elogind");
    }
}
<|endoftext|>


<commit_before><commit_msg>Grab local lock earlier and don't send missing local files<commit_after><|endoftext|>


<commit_before>pub trait AdjacentBound: Ord {
    fn is_adjacent(&self, other: &Self) -> bool {
        self.comes_before(other) || self.comes_after(other)
    }

    fn comes_before(&self, other: &Self) -> bool;

    fn comes_after(&self, other: &Self) -> bool;

    fn increment(&self) -> Self;

    fn decrement(&self) -> Self;

    fn increment_ref(&mut self);

    fn decrement_ref(&mut self);
}

macro_rules! adjacent_bound_impl {
    ($type:ty, $one:expr) => {
        impl AdjacentBound for $type {
            fn comes_before(&self, other: &Self) -> bool {
                *self == (*other - $one)
            }

            fn comes_after(&self, other: &Self) -> bool {
                *self == (*other + $one)
            }

            fn increment(&self) -> Self {
                *self + $one
            }

            fn decrement(&self) -> Self {
                *self - $one
            }

            fn increment_ref(&mut self) {
                *self = *self + $one;
            }

            fn decrement_ref(&mut self) {
                *self = *self - $one;
            }
        }
    }
}

adjacent_bound_impl!(u8, 1u8);
adjacent_bound_impl!(i8, 1i8);

adjacent_bound_impl!(u16, 1u16);
adjacent_bound_impl!(i16, 1i16);

adjacent_bound_impl!(u32, 1u32);
adjacent_bound_impl!(i32, 1i32);

adjacent_bound_impl!(u64, 1u64);
adjacent_bound_impl!(i64, 1i64);

#[cfg(feature = "chrono")]
mod chrono_impl {
    use chrono::{Date, DateTime, Duration, FixedOffset, Local, NaiveDate, NaiveDateTime,
                 NaiveTime, Utc};
    use AdjacentBound;

    adjacent_bound_impl!(NaiveDate, Duration::days(1));
    adjacent_bound_impl!(NaiveDateTime, Duration::min_value());
    adjacent_bound_impl!(NaiveTime, Duration::min_value());

    adjacent_bound_impl!(Date<Utc>, Duration::days(1));
    adjacent_bound_impl!(Date<FixedOffset>, Duration::days(1));
    adjacent_bound_impl!(Date<Local>, Duration::days(1));

    adjacent_bound_impl!(DateTime<Utc>, Duration::min_value());
    adjacent_bound_impl!(DateTime<FixedOffset>, Duration::min_value());
    adjacent_bound_impl!(DateTime<Local>, Duration::min_value());

}

adjacent_bound_impl!(usize, 1usize);
adjacent_bound_impl!(isize, 1isize);#[cfg(feature = "chrono")]
#[cfg(feature = "chrono")]
pub use self::chrono_impl::*;
<commit_msg>Implemented AdjacentBound for Wrapping<T> implementations<commit_after>pub trait AdjacentBound: Ord {
    fn is_adjacent(&self, other: &Self) -> bool {
        self.comes_before(other) || self.comes_after(other)
    }

    fn comes_before(&self, other: &Self) -> bool;

    fn comes_after(&self, other: &Self) -> bool;

    fn increment(&self) -> Self;

    fn decrement(&self) -> Self;

    fn increment_ref(&mut self);

    fn decrement_ref(&mut self);
}

macro_rules! adjacent_bound_impl {
    ($type:ty, $one:expr) => {
        impl AdjacentBound for $type {
            fn comes_before(&self, other: &Self) -> bool {
                *self == (*other - $one)
            }

            fn comes_after(&self, other: &Self) -> bool {
                *self == (*other + $one)
            }

            fn increment(&self) -> Self {
                *self + $one
            }

            fn decrement(&self) -> Self {
                *self - $one
            }

            fn increment_ref(&mut self) {
                *self = *self + $one;
            }

            fn decrement_ref(&mut self) {
                *self = *self - $one;
            }
        }
    }
}

macro_rules! adjacent_bound_impl_and_wrapping {
    ($type:ty, $one:expr) => {
        adjacent_bound_impl!($type, $one);
        adjacent_bound_impl!(::std::num::Wrapping<$type>, ::std::num::Wrapping($one));
    }
}

adjacent_bound_impl_and_wrapping!(u8, 1u8);
adjacent_bound_impl_and_wrapping!(i8, 1i8);

adjacent_bound_impl_and_wrapping!(u16, 1u16);
adjacent_bound_impl_and_wrapping!(i16, 1i16);

adjacent_bound_impl_and_wrapping!(u32, 1u32);
adjacent_bound_impl_and_wrapping!(i32, 1i32);

adjacent_bound_impl_and_wrapping!(u64, 1u64);
adjacent_bound_impl_and_wrapping!(i64, 1i64);

adjacent_bound_impl_and_wrapping!(usize, 1usize);
adjacent_bound_impl_and_wrapping!(isize, 1isize);

#[cfg(test)]
mod tests {
    use std::num::Wrapping;
    use AdjacentBound;

    #[test]
    fn overflow_wrapping_tests() {
        assert!(Wrapping(u32::max_value()).is_immediately_before(&Wrapping(0)));
        assert!(Wrapping(0).is_immediately_after(&Wrapping(u32::max_value())));
    }
}

#[cfg(feature = "chrono")]
mod chrono_impl {
    use chrono::{Date, DateTime, Duration, FixedOffset, Local, NaiveDate, NaiveDateTime,
                 NaiveTime, Utc};
    use AdjacentBound;

    adjacent_bound_impl!(NaiveDate, Duration::days(1));
    adjacent_bound_impl!(NaiveDateTime, Duration::min_value());
    adjacent_bound_impl!(NaiveTime, Duration::min_value());

    adjacent_bound_impl!(Date<Utc>, Duration::days(1));
    adjacent_bound_impl!(Date<FixedOffset>, Duration::days(1));
    adjacent_bound_impl!(Date<Local>, Duration::days(1));

    adjacent_bound_impl!(DateTime<Utc>, Duration::min_value());
    adjacent_bound_impl!(DateTime<FixedOffset>, Duration::min_value());
    adjacent_bound_impl!(DateTime<Local>, Duration::min_value());

}

#[cfg(feature = "chrono")]
pub use self::chrono_impl::*;
<|endoftext|>