<commit_before>#[doc = "A deque. Untested as of yet. Likely buggy"];

import option::{some, none};

iface t<T> {
    fn size() -> uint;
    fn add_front(T);
    fn add_back(T);
    fn pop_front() -> T;
    fn pop_back() -> T;
    fn peek_front() -> T;
    fn peek_back() -> T;
    fn get(int) -> T;
}

// FIXME eventually, a proper datatype plus an exported impl would be
// preferrable (#2343)
fn create<T: copy>() -> t<T> {
    type cell<T> = option<T>;

    let initial_capacity: uint = 32u; // 2^5
     /**
      * Grow is only called on full elts, so nelts is also len(elts), unlike
      * elsewhere.
      */
    fn grow<T: copy>(nelts: uint, lo: uint, elts: [mut cell<T>]) ->
       [mut cell<T>] {
        assert (nelts == vec::len(elts));
        let mut rv = [mut];

        let mut i = 0u;
        let nalloc = uint::next_power_of_two(nelts + 1u);
        while i < nalloc {
            if i < nelts {
                rv += [mut elts[(lo + i) % nelts]];
            } else { rv += [mut none]; }
            i += 1u;
        }

        ret rv;
    }
    fn get<T: copy>(elts: [mut cell<T>], i: uint) -> T {
        ret alt elts[i] { some(t) { t } _ { fail } };
    }

    type repr<T> = {mut nelts: uint,
                    mut lo: uint,
                    mut hi: uint,
                    mut elts: [mut cell<T>]};

    impl <T: copy> of t<T> for repr<T> {
        fn size() -> uint { ret self.nelts; }
        fn add_front(t: T) {
            let oldlo: uint = self.lo;
            if self.lo == 0u {
                self.lo = vec::len(self.elts) - 1u;
            } else { self.lo -= 1u; }
            if self.lo == self.hi {
                self.elts = grow(self.nelts, oldlo, self.elts);
                self.lo = vec::len(self.elts) - 1u;
                self.hi = self.nelts;
            }
            self.elts[self.lo] = some(t);
            self.nelts += 1u;
        }
        fn add_back(t: T) {
            if self.lo == self.hi && self.nelts != 0u {
                self.elts = grow(self.nelts, self.lo, self.elts);
                self.lo = 0u;
                self.hi = self.nelts;
            }
            self.elts[self.hi] = some(t);
            self.hi = (self.hi + 1u) % vec::len(self.elts);
            self.nelts += 1u;
        }
        /**
         * We actually release (turn to none()) the T we're popping so
         * that we don't keep anyone's refcount up unexpectedly.
         */
        fn pop_front() -> T {
            let t: T = get(self.elts, self.lo);
            self.elts[self.lo] = none;
            self.lo = (self.lo + 1u) % vec::len(self.elts);
            self.nelts -= 1u;
            ret t;
        }
        fn pop_back() -> T {
            if self.hi == 0u {
                self.hi = vec::len(self.elts) - 1u;
            } else { self.hi -= 1u; }
            let t: T = get(self.elts, self.hi);
            self.elts[self.hi] = none;
            self.nelts -= 1u;
            ret t;
        }
        fn peek_front() -> T { ret get(self.elts, self.lo); }
        fn peek_back() -> T { ret get(self.elts, self.hi - 1u); }
        fn get(i: int) -> T {
            let idx = (self.lo + (i as uint)) % vec::len(self.elts);
            ret get(self.elts, idx);
        }
    }

    let repr: repr<T> = {
        mut nelts: 0u,
        mut lo: 0u,
        mut hi: 0u,
        mut elts: vec::to_mut(vec::from_elem(initial_capacity, none))
    };
    repr as t::<T>
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_simple() {
        let d: deque::t<int> = deque::create::<int>();
        assert (d.size() == 0u);
        d.add_front(17);
        d.add_front(42);
        d.add_back(137);
        assert (d.size() == 3u);
        d.add_back(137);
        assert (d.size() == 4u);
        log(debug, d.peek_front());
        assert (d.peek_front() == 42);
        log(debug, d.peek_back());
        assert (d.peek_back() == 137);
        let mut i: int = d.pop_front();
        log(debug, i);
        assert (i == 42);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 17);
        assert (d.size() == 0u);
        d.add_back(3);
        assert (d.size() == 1u);
        d.add_front(2);
        assert (d.size() == 2u);
        d.add_back(4);
        assert (d.size() == 3u);
        d.add_front(1);
        assert (d.size() == 4u);
        log(debug, d.get(0));
        log(debug, d.get(1));
        log(debug, d.get(2));
        log(debug, d.get(3));
        assert (d.get(0) == 1);
        assert (d.get(1) == 2);
        assert (d.get(2) == 3);
        assert (d.get(3) == 4);
    }

    fn test_boxes(a: @int, b: @int, c: @int, d: @int) {
        let deq: deque::t<@int> = deque::create::<@int>();
        assert (deq.size() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.size() == 3u);
        deq.add_back(d);
        assert (deq.size() == 4u);
        assert (deq.peek_front() == b);
        assert (deq.peek_back() == d);
        assert (deq.pop_front() == b);
        assert (deq.pop_back() == d);
        assert (deq.pop_back() == c);
        assert (deq.pop_back() == a);
        assert (deq.size() == 0u);
        deq.add_back(c);
        assert (deq.size() == 1u);
        deq.add_front(b);
        assert (deq.size() == 2u);
        deq.add_back(d);
        assert (deq.size() == 3u);
        deq.add_front(a);
        assert (deq.size() == 4u);
        assert (deq.get(0) == a);
        assert (deq.get(1) == b);
        assert (deq.get(2) == c);
        assert (deq.get(3) == d);
    }

    type eqfn<T> = fn@(T, T) -> bool;

    fn test_parameterized<T: copy>(e: eqfn<T>, a: T, b: T, c: T, d: T) {
        let deq: deque::t<T> = deque::create::<T>();
        assert (deq.size() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.size() == 3u);
        deq.add_back(d);
        assert (deq.size() == 4u);
        assert (e(deq.peek_front(), b));
        assert (e(deq.peek_back(), d));
        assert (e(deq.pop_front(), b));
        assert (e(deq.pop_back(), d));
        assert (e(deq.pop_back(), c));
        assert (e(deq.pop_back(), a));
        assert (deq.size() == 0u);
        deq.add_back(c);
        assert (deq.size() == 1u);
        deq.add_front(b);
        assert (deq.size() == 2u);
        deq.add_back(d);
        assert (deq.size() == 3u);
        deq.add_front(a);
        assert (deq.size() == 4u);
        assert (e(deq.get(0), a));
        assert (e(deq.get(1), b));
        assert (e(deq.get(2), c));
        assert (e(deq.get(3), d));
    }

    enum taggy { one(int), two(int, int), three(int, int, int), }

    enum taggypar<T> {
        onepar(int), twopar(int, int), threepar(int, int, int),
    }

    type reccy = {x: int, y: int, t: taggy};

    #[test]
    fn test() {
        fn inteq(&&a: int, &&b: int) -> bool { ret a == b; }
        fn intboxeq(&&a: @int, &&b: @int) -> bool { ret a == b; }
        fn taggyeq(a: taggy, b: taggy) -> bool {
            alt a {
              one(a1) { alt b { one(b1) { ret a1 == b1; } _ { ret false; } } }
              two(a1, a2) {
                alt b {
                  two(b1, b2) { ret a1 == b1 && a2 == b2; }
                  _ { ret false; }
                }
              }
              three(a1, a2, a3) {
                alt b {
                  three(b1, b2, b3) { ret a1 == b1 && a2 == b2 && a3 == b3; }
                  _ { ret false; }
                }
              }
            }
        }
        fn taggypareq<T>(a: taggypar<T>, b: taggypar<T>) -> bool {
            alt a {
              onepar::<T>(a1) {
                alt b { onepar::<T>(b1) { ret a1 == b1; } _ { ret false; } }
              }
              twopar::<T>(a1, a2) {
                alt b {
                  twopar::<T>(b1, b2) { ret a1 == b1 && a2 == b2; }
                  _ { ret false; }
                }
              }
              threepar::<T>(a1, a2, a3) {
                alt b {
                  threepar::<T>(b1, b2, b3) {
                    ret a1 == b1 && a2 == b2 && a3 == b3;
                  }
                  _ { ret false; }
                }
              }
            }
        }
        fn reccyeq(a: reccy, b: reccy) -> bool {
            ret a.x == b.x && a.y == b.y && taggyeq(a.t, b.t);
        }
        #debug("*** test boxes");
        test_boxes(@5, @72, @64, @175);
        #debug("*** end test boxes");
        #debug("test parameterized: int");
        let eq1: eqfn<int> = inteq;
        test_parameterized::<int>(eq1, 5, 72, 64, 175);
        #debug("*** test parameterized: @int");
        let eq2: eqfn<@int> = intboxeq;
        test_parameterized::<@int>(eq2, @5, @72, @64, @175);
        #debug("*** end test parameterized @int");
        #debug("test parameterized: taggy");
        let eq3: eqfn<taggy> = taggyeq;
        test_parameterized::<taggy>(eq3, one(1), two(1, 2), three(1, 2, 3),
                                    two(17, 42));

        #debug("*** test parameterized: taggypar<int>");
        let eq4: eqfn<taggypar<int>> = bind taggypareq::<int>(_, _);
        test_parameterized::<taggypar<int>>(eq4, onepar::<int>(1),
                                            twopar::<int>(1, 2),
                                            threepar::<int>(1, 2, 3),
                                            twopar::<int>(17, 42));
        #debug("*** end test parameterized: taggypar::<int>");

        #debug("*** test parameterized: reccy");
        let reccy1: reccy = {x: 1, y: 2, t: one(1)};
        let reccy2: reccy = {x: 345, y: 2, t: two(1, 2)};
        let reccy3: reccy = {x: 1, y: 777, t: three(1, 2, 3)};
        let reccy4: reccy = {x: 19, y: 252, t: two(17, 42)};
        let eq5: eqfn<reccy> = reccyeq;
        test_parameterized::<reccy>(eq5, reccy1, reccy2, reccy3, reccy4);
        #debug("*** end test parameterized: reccy");
        #debug("*** done");
    }
}<commit_msg>Rewrite deque to use dvec<commit_after>#[doc = "A deque. Untested as of yet. Likely buggy"];

import option::{some, none};
import dvec::{dvec, extensions};

iface t<T> {
    fn size() -> uint;
    fn add_front(T);
    fn add_back(T);
    fn pop_front() -> T;
    fn pop_back() -> T;
    fn peek_front() -> T;
    fn peek_back() -> T;
    fn get(int) -> T;
}

// FIXME eventually, a proper datatype plus an exported impl would be
// preferrable (#2343)
fn create<T: copy>() -> t<T> {
    type cell<T> = option<T>;

    let initial_capacity: uint = 32u; // 2^5
     /**
      * Grow is only called on full elts, so nelts is also len(elts), unlike
      * elsewhere.
      */
    fn grow<T: copy>(nelts: uint, lo: uint, -elts: [mut cell<T>]) ->
       [mut cell<T>] {
        assert (nelts == vec::len(elts));
        let mut rv = [mut];

        let mut i = 0u;
        let nalloc = uint::next_power_of_two(nelts + 1u);
        while i < nalloc {
            if i < nelts {
                rv += [mut elts[(lo + i) % nelts]];
            } else { rv += [mut none]; }
            i += 1u;
        }

        ret rv;
    }
    fn get<T: copy>(elts: dvec<cell<T>>, i: uint) -> T {
        alt elts.get_elt(i) { some(t) { t } _ { fail } }
    }

    type repr<T> = {mut nelts: uint,
                    mut lo: uint,
                    mut hi: uint,
                    elts: dvec<cell<T>>};

    impl <T: copy> of t<T> for repr<T> {
        fn size() -> uint { ret self.nelts; }
        fn add_front(t: T) {
            let oldlo: uint = self.lo;
            if self.lo == 0u {
                self.lo = self.elts.len() - 1u;
            } else { self.lo -= 1u; }
            if self.lo == self.hi {
                self.elts.swap({ |v| grow(self.nelts, oldlo, v) });
                self.lo = self.elts.len() - 1u;
                self.hi = self.nelts;
            }
            self.elts.set_elt(self.lo, some(t));
            self.nelts += 1u;
        }
        fn add_back(t: T) {
            if self.lo == self.hi && self.nelts != 0u {
                self.elts.swap({ |v| grow(self.nelts, self.lo, v) });
                self.lo = 0u;
                self.hi = self.nelts;
            }
            self.elts.set_elt(self.hi, some(t));
            self.hi = (self.hi + 1u) % self.elts.len();
            self.nelts += 1u;
        }
        /**
         * We actually release (turn to none()) the T we're popping so
         * that we don't keep anyone's refcount up unexpectedly.
         */
        fn pop_front() -> T {
            let t: T = get(self.elts, self.lo);
            self.elts.set_elt(self.lo, none);
            self.lo = (self.lo + 1u) % self.elts.len();
            self.nelts -= 1u;
            ret t;
        }
        fn pop_back() -> T {
            if self.hi == 0u {
                self.hi = self.elts.len() - 1u;
            } else { self.hi -= 1u; }
            let t: T = get(self.elts, self.hi);
            self.elts.set_elt(self.hi, none);
            self.nelts -= 1u;
            ret t;
        }
        fn peek_front() -> T { ret get(self.elts, self.lo); }
        fn peek_back() -> T { ret get(self.elts, self.hi - 1u); }
        fn get(i: int) -> T {
            let idx = (self.lo + (i as uint)) % self.elts.len();
            ret get(self.elts, idx);
        }
    }

    let repr: repr<T> = {
        mut nelts: 0u,
        mut lo: 0u,
        mut hi: 0u,
        elts:
            dvec::from_vec(
                vec::to_mut(
                    vec::from_elem(initial_capacity, none)))
    };
    repr as t::<T>
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_simple() {
        let d: deque::t<int> = deque::create::<int>();
        assert (d.size() == 0u);
        d.add_front(17);
        d.add_front(42);
        d.add_back(137);
        assert (d.size() == 3u);
        d.add_back(137);
        assert (d.size() == 4u);
        log(debug, d.peek_front());
        assert (d.peek_front() == 42);
        log(debug, d.peek_back());
        assert (d.peek_back() == 137);
        let mut i: int = d.pop_front();
        log(debug, i);
        assert (i == 42);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 17);
        assert (d.size() == 0u);
        d.add_back(3);
        assert (d.size() == 1u);
        d.add_front(2);
        assert (d.size() == 2u);
        d.add_back(4);
        assert (d.size() == 3u);
        d.add_front(1);
        assert (d.size() == 4u);
        log(debug, d.get(0));
        log(debug, d.get(1));
        log(debug, d.get(2));
        log(debug, d.get(3));
        assert (d.get(0) == 1);
        assert (d.get(1) == 2);
        assert (d.get(2) == 3);
        assert (d.get(3) == 4);
    }

    fn test_boxes(a: @int, b: @int, c: @int, d: @int) {
        let deq: deque::t<@int> = deque::create::<@int>();
        assert (deq.size() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.size() == 3u);
        deq.add_back(d);
        assert (deq.size() == 4u);
        assert (deq.peek_front() == b);
        assert (deq.peek_back() == d);
        assert (deq.pop_front() == b);
        assert (deq.pop_back() == d);
        assert (deq.pop_back() == c);
        assert (deq.pop_back() == a);
        assert (deq.size() == 0u);
        deq.add_back(c);
        assert (deq.size() == 1u);
        deq.add_front(b);
        assert (deq.size() == 2u);
        deq.add_back(d);
        assert (deq.size() == 3u);
        deq.add_front(a);
        assert (deq.size() == 4u);
        assert (deq.get(0) == a);
        assert (deq.get(1) == b);
        assert (deq.get(2) == c);
        assert (deq.get(3) == d);
    }

    type eqfn<T> = fn@(T, T) -> bool;

    fn test_parameterized<T: copy>(e: eqfn<T>, a: T, b: T, c: T, d: T) {
        let deq: deque::t<T> = deque::create::<T>();
        assert (deq.size() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.size() == 3u);
        deq.add_back(d);
        assert (deq.size() == 4u);
        assert (e(deq.peek_front(), b));
        assert (e(deq.peek_back(), d));
        assert (e(deq.pop_front(), b));
        assert (e(deq.pop_back(), d));
        assert (e(deq.pop_back(), c));
        assert (e(deq.pop_back(), a));
        assert (deq.size() == 0u);
        deq.add_back(c);
        assert (deq.size() == 1u);
        deq.add_front(b);
        assert (deq.size() == 2u);
        deq.add_back(d);
        assert (deq.size() == 3u);
        deq.add_front(a);
        assert (deq.size() == 4u);
        assert (e(deq.get(0), a));
        assert (e(deq.get(1), b));
        assert (e(deq.get(2), c));
        assert (e(deq.get(3), d));
    }

    enum taggy { one(int), two(int, int), three(int, int, int), }

    enum taggypar<T> {
        onepar(int), twopar(int, int), threepar(int, int, int),
    }

    type reccy = {x: int, y: int, t: taggy};

    #[test]
    fn test() {
        fn inteq(&&a: int, &&b: int) -> bool { ret a == b; }
        fn intboxeq(&&a: @int, &&b: @int) -> bool { ret a == b; }
        fn taggyeq(a: taggy, b: taggy) -> bool {
            alt a {
              one(a1) { alt b { one(b1) { ret a1 == b1; } _ { ret false; } } }
              two(a1, a2) {
                alt b {
                  two(b1, b2) { ret a1 == b1 && a2 == b2; }
                  _ { ret false; }
                }
              }
              three(a1, a2, a3) {
                alt b {
                  three(b1, b2, b3) { ret a1 == b1 && a2 == b2 && a3 == b3; }
                  _ { ret false; }
                }
              }
            }
        }
        fn taggypareq<T>(a: taggypar<T>, b: taggypar<T>) -> bool {
            alt a {
              onepar::<T>(a1) {
                alt b { onepar::<T>(b1) { ret a1 == b1; } _ { ret false; } }
              }
              twopar::<T>(a1, a2) {
                alt b {
                  twopar::<T>(b1, b2) { ret a1 == b1 && a2 == b2; }
                  _ { ret false; }
                }
              }
              threepar::<T>(a1, a2, a3) {
                alt b {
                  threepar::<T>(b1, b2, b3) {
                    ret a1 == b1 && a2 == b2 && a3 == b3;
                  }
                  _ { ret false; }
                }
              }
            }
        }
        fn reccyeq(a: reccy, b: reccy) -> bool {
            ret a.x == b.x && a.y == b.y && taggyeq(a.t, b.t);
        }
        #debug("*** test boxes");
        test_boxes(@5, @72, @64, @175);
        #debug("*** end test boxes");
        #debug("test parameterized: int");
        let eq1: eqfn<int> = inteq;
        test_parameterized::<int>(eq1, 5, 72, 64, 175);
        #debug("*** test parameterized: @int");
        let eq2: eqfn<@int> = intboxeq;
        test_parameterized::<@int>(eq2, @5, @72, @64, @175);
        #debug("*** end test parameterized @int");
        #debug("test parameterized: taggy");
        let eq3: eqfn<taggy> = taggyeq;
        test_parameterized::<taggy>(eq3, one(1), two(1, 2), three(1, 2, 3),
                                    two(17, 42));

        #debug("*** test parameterized: taggypar<int>");
        let eq4: eqfn<taggypar<int>> = bind taggypareq::<int>(_, _);
        test_parameterized::<taggypar<int>>(eq4, onepar::<int>(1),
                                            twopar::<int>(1, 2),
                                            threepar::<int>(1, 2, 3),
                                            twopar::<int>(17, 42));
        #debug("*** end test parameterized: taggypar::<int>");

        #debug("*** test parameterized: reccy");
        let reccy1: reccy = {x: 1, y: 2, t: one(1)};
        let reccy2: reccy = {x: 345, y: 2, t: two(1, 2)};
        let reccy3: reccy = {x: 1, y: 777, t: three(1, 2, 3)};
        let reccy4: reccy = {x: 19, y: 252, t: two(17, 42)};
        let eq5: eqfn<reccy> = reccyeq;
        test_parameterized::<reccy>(eq5, reccy1, reccy2, reccy3, reccy4);
        #debug("*** end test parameterized: reccy");
        #debug("*** done");
    }
}<|endoftext|>


<commit_before>//! **Plexus** is a library for polygonal mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable.

pub mod buffer;
pub mod builder;
pub mod encoding;
pub mod graph;
pub mod index;
mod integration;
pub mod primitive;
mod transact;

use itertools::{Itertools, MinMaxResult};
use std::borrow::Borrow;
use std::fmt::Debug;

use crate::graph::Binding;

pub use theon::{AsPosition, Position};
pub use typenum::{U2, U3, U4};

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended, especially when
    //! working with generators and iterator expressions, as those operations
    //! are expressed mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the `primitive`
    //! module for generating and decomposing iterators over topological data
    //! (e.g., `Trigon`, `Tetragon`, etc.) are re-exported so that functions in
    //! iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing `MeshBuffer`s and `MeshGraph`s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The `Selector` enum and its variants are re-exported for convenience.
    //! `Selector` is often used when mutating `MeshGraph`s.

    pub use crate::buffer::{
        FromRawBuffers as _, FromRawBuffersWithArity as _, IntoFlatIndex as _,
        IntoStructuredIndex as _,
    };
    pub use crate::builder::{FacetBuilder as _, MeshBuilder as _, SurfaceBuilder as _};
    pub use crate::graph::{Binding as _, Selector};
    pub use crate::index::{CollectWithIndexer as _, IndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _, IntoTrigons as _,
        IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _, Vertices as _,
    };
    pub use crate::primitive::generate::Generator as _;
    pub use crate::primitive::{MapVertices as _, Polygonal as _, Topological as _};
    pub use crate::IteratorExt as _;
    pub use crate::{DynamicArity as _, FromGeometry as _, IntoGeometry as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait Arity: Copy {
    fn into_interval(self) -> (usize, Option<usize>);
}

/// Singular arity.
impl Arity for usize {
    fn into_interval(self) -> (usize, Option<usize>) {
        (self, Some(self))
    }
}

/// Closed interval arity.
///
/// This type represents a _closed interval_ arity with a minimum and maximum
/// inclusive range.
impl Arity for (usize, usize) {
    fn into_interval(self) -> (usize, Option<usize>) {
        let (min, max) = self;
        (min, Some(max))
    }
}

/// Open interval arity.
///
/// This type represents an _open interval_ arity with a minimum and optional
/// maximum inclusive range. When there is no maximum (`None`), the maximum
/// arity is unspecified. This typically means that there is no theoretical
/// maximum.
impl Arity for (usize, Option<usize>) {
    fn into_interval(self) -> (usize, Option<usize>) {
        self
    }
}

/// Type-level arity.
///
/// This trait specifies the arity that a type supports. Values of a
/// `StaticArity` type have an arity that reflects this constant, which may be
/// any type or form implementing the `Arity` trait.
pub trait StaticArity {
    type Static: Arity;

    const ARITY: Self::Static;
}

/// Value-level arity.
///
/// This trait specifies the arity of a value at runtime. This is often
/// distinct from the type-level arity of the `StaticArity` trait, which
/// expresses the capabilities of a type.
pub trait DynamicArity: StaticArity {
    type Dynamic: Arity;

    fn arity(&self) -> Self::Dynamic;
}

/// Topological types with fixed and singular arity.
///
/// Types are _monomorphic_ if they have a fixed and singular arity as types
/// and values. For example, `Trigon` always and only represents a trigon
/// (triangle) with an arity of three. `Trigon` values always have an arity of
/// three and types composed of only `Trigon`s have a compound arity of three.
///
/// This contrasts _polymorphic_ types like `Polygon`, which have an interval
/// arity at the type-level and a singular but varying arity for values
/// (because a `Polygon` value may be either a trigon or tertragon).
pub trait Monomorphic: StaticArity<Static = usize> {}

/// Arity of a compound structure.
///
/// `MeshArity` represents the arity of a compound structure, which may be
/// _uniform_ or _non-uniform_. This is typically the value-level arity for
/// mesh data structures like `MeshGraph` and `MeshBuffer`.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MeshArity {
    /// A compound structure has _uniform_ arity if all of its components have
    /// the same arity, such as a `MeshBuffer` composed entirely of trigons.
    Uniform(usize),
    /// A compound structure has _non-uniform_ arity if the arity of its
    /// components differ, such as a `MeshGraph` composed of trigons and
    /// tetragons.
    ///
    /// Non-uniform arity is represented as an inclusive range known as an
    /// _interval_. This is the minimum and maximum arity of the components, in
    /// that order.
    NonUniform(usize, usize),
}

impl MeshArity {
    pub fn from_components<T, I>(components: I) -> Self
    where
        T: DynamicArity<Dynamic = usize>,
        I: IntoIterator,
        I::Item: Borrow<T>,
    {
        match components
            .into_iter()
            .map(|component| component.borrow().arity())
            .minmax()
        {
            MinMaxResult::OneElement(exact) => MeshArity::Uniform(exact),
            MinMaxResult::MinMax(min, max) => MeshArity::NonUniform(min, max),
            _ => MeshArity::Uniform(0),
        }
    }
}

impl Arity for MeshArity {
    fn into_interval(self) -> (usize, Option<usize>) {
        match self {
            MeshArity::Uniform(exact) => (exact, Some(exact)),
            MeshArity::NonUniform(min, max) => (min, Some(max)),
        }
    }
}

pub trait FromGeometry<T> {
    fn from_geometry(other: T) -> Self;
}

impl<T> FromGeometry<T> for T {
    fn from_geometry(other: T) -> Self {
        other
    }
}

/// Geometry elision into `()`.
impl<T> FromGeometry<T> for ()
where
    T: UnitGeometry,
{
    fn from_geometry(_: T) -> Self {}
}

/// Geometry elision from `()`.
impl<T> FromGeometry<()> for T
where
    T: UnitGeometry + Default,
{
    fn from_geometry(_: ()) -> Self {
        T::default()
    }
}

/// Geometry elision.
///
/// Geometric types that implement this trait may be elided. In particular,
/// these types may be converted into and from `()` via the `FromGeometry` and
/// `IntoGeometry` traits.
///
/// For a geometric type `T`, the following table illustrates the elisions in
/// which `T` may participate:
///
/// | Bounds on `T`            | From | Into |
/// |--------------------------|------|------|
/// | `UnitGeometry`           | `T`  | `()` |
/// | `Default + UnitGeometry` | `()` | `T`  |
///
/// These conversions are useful when converting between mesh data structures
/// with incompatible geometry, such as from a `MeshGraph` with face geometry
/// to a `MeshBuffer` that cannot support such geometry.
///
/// When geometry features are enabled, `UnitGeometry` is implemented for
/// integrated foreign types.
pub trait UnitGeometry {}

pub trait IntoGeometry<T> {
    fn into_geometry(self) -> T;
}

impl<T, U> IntoGeometry<U> for T
where
    U: FromGeometry<T>,
{
    fn into_geometry(self) -> U {
        U::from_geometry(self)
    }
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection of ordered elements $\\{a, b, c\\}$, this iterator
    /// yeilds the ordered items $\\{(a, b), (b, c), (c, a)\\}$.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone,
    {
        Perimeter::new(self)
    }

    /// Maps an iterator over topological views to the keys of those views.
    ///
    /// It is often useful to examine or collect the keys of views over a
    /// `MeshGraph`. This iterator avoids redundant use of `map` to extract
    /// keys.
    ///
    /// # Examples
    ///
    /// Collecting keys of faces before a topological mutation:
    ///
    /// ```rust
    /// # extern crate decorum;
    /// # extern crate nalgebra;
    /// # extern crate plexus;
    /// #
    /// use decorum::R64;
    /// use nalgebra::Point3;
    /// use plexus::graph::MeshGraph;
    /// use plexus::prelude::*;
    /// use plexus::primitive::generate::Position;
    /// use plexus::primitive::sphere::UvSphere;
    ///
    /// type E3 = Point3<R64>;
    ///
    /// let mut graph = UvSphere::new(6, 6)
    ///     .polygons::<Position<E3>>()
    ///     .collect::<MeshGraph<E3>>();
    ///
    /// let keys = graph
    ///     .faces()
    ///     .filter(|face| face.arity() > 3)
    ///     .keys()
    ///     .collect::<Vec<_>>();
    /// for key in keys {
    ///     graph.face_mut(key).unwrap().poke_with_offset(0.5);
    /// }
    /// ```
    fn keys(self) -> Keys<Self>
    where
        Self::Item: Binding,
    {
        Keys::new(self)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

/// Iterator that produces a window of duplets over its input.
///
/// The duplets produced include the first value in the input sequence at both
/// the beginning and end of the iteration, forming a perimeter. Given a
/// collection of ordered elements $\\{a, b, c\\}$, this iterator yields the
/// ordered items $\\{(a, b), (b, c), (c, a)\\}$.
#[derive(Clone)]
pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

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

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

#[derive(Clone)]
pub struct Keys<I>
where
    I: Iterator,
    I::Item: Binding,
{
    input: I,
}

impl<I> Keys<I>
where
    I: Iterator,
    I::Item: Binding,
{
    fn new(input: I) -> Self {
        Keys { input }
    }
}

impl<I> Iterator for Keys<I>
where
    I: Iterator,
    I::Item: Binding,
{
    type Item = <I::Item as Binding>::Key;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.next().map(|view| view.key())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}
<commit_msg>Provide limited intra-documentation links in the root of the crate.<commit_after>//! **Plexus** is a library for polygonal mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable.

pub mod buffer;
pub mod builder;
pub mod encoding;
pub mod graph;
pub mod index;
mod integration;
pub mod primitive;
mod transact;

use itertools::{Itertools, MinMaxResult};
use std::borrow::Borrow;
use std::fmt::Debug;

use crate::graph::Binding;

pub use theon::{AsPosition, Position};
pub use typenum::{U2, U3, U4};

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended, especially when
    //! working with generators and iterator expressions, as those operations
    //! are expressed mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the [`primitive`]
    //! module for generating and decomposing iterators over topological data
    //! (e.g., [`Trigon`], [`Tetragon`], etc.) are re-exported so that functions
    //! in iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing [`MeshBuffer`]s and [`MeshGraph`]s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The [`Selector`] `enum` and its variants are re-exported for
    //! convenience. [`Selector`] is often used when mutating [`MeshGraph`]s.
    //!
    //! [`MeshBuffer`]: ../buffer/struct.MeshBuffer.html
    //! [`MeshGraph`]: ../graph/struct.MeshGraph.html
    //! [`primitive`]: ../primitive/index.html
    //! [`Selector`]: ../graph/enum.Selector.html
    //! [`Tetragon`]: ../primitive/type.Tetragon.html
    //! [`Trigon`]: ../primitive/type.Trigon.html

    pub use crate::buffer::{
        FromRawBuffers as _, FromRawBuffersWithArity as _, IntoFlatIndex as _,
        IntoStructuredIndex as _,
    };
    pub use crate::builder::{FacetBuilder as _, MeshBuilder as _, SurfaceBuilder as _};
    pub use crate::graph::{Binding as _, Selector};
    pub use crate::index::{CollectWithIndexer as _, IndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _, IntoTrigons as _,
        IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _, Vertices as _,
    };
    pub use crate::primitive::generate::Generator as _;
    pub use crate::primitive::{MapVertices as _, Polygonal as _, Topological as _};
    pub use crate::IteratorExt as _;
    pub use crate::{DynamicArity as _, FromGeometry as _, IntoGeometry as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait Arity: Copy {
    fn into_interval(self) -> (usize, Option<usize>);
}

/// Singular arity.
impl Arity for usize {
    fn into_interval(self) -> (usize, Option<usize>) {
        (self, Some(self))
    }
}

/// Closed interval arity.
///
/// This type represents a _closed interval_ arity with a minimum and maximum
/// inclusive range.
impl Arity for (usize, usize) {
    fn into_interval(self) -> (usize, Option<usize>) {
        let (min, max) = self;
        (min, Some(max))
    }
}

/// Open interval arity.
///
/// This type represents an _open interval_ arity with a minimum and optional
/// maximum inclusive range. When there is no maximum (`None`), the maximum
/// arity is unspecified. This typically means that there is no theoretical
/// maximum.
impl Arity for (usize, Option<usize>) {
    fn into_interval(self) -> (usize, Option<usize>) {
        self
    }
}

/// Type-level arity.
///
/// This trait specifies the arity that a type supports. Values of a
/// `StaticArity` type have an arity that reflects this constant, which may be
/// any type or form implementing the [`Arity`] trait.
///
/// [`Arity`]: trait.Arity.html
pub trait StaticArity {
    type Static: Arity;

    const ARITY: Self::Static;
}

/// Value-level arity.
///
/// This trait specifies the arity of a value at runtime. This is often
/// distinct from the type-level arity of the [`StaticArity`] trait, which
/// expresses the capabilities of a type.
///
/// [`StaticArity`]: trait.StaticArity.html
pub trait DynamicArity: StaticArity {
    type Dynamic: Arity;

    fn arity(&self) -> Self::Dynamic;
}

/// Topological types with fixed and singular arity.
///
/// Types are _monomorphic_ if they have a fixed and singular arity as types and
/// values. For example, [`Trigon`] always and only represents a trigon
/// (triangle) with an arity of three. [`Trigon`] values always have an arity of
/// three and types composed of only [`Trigon`]s have a compound arity of three.
///
/// This contrasts _polymorphic_ types like [`Polygon`], which have an interval
/// arity at the type-level and a singular but varying arity for values (because
/// a [`Polygon`] value may be either a trigon or tertragon).
///
/// [`Polygon`]: primitive/enum.Polygon.html
/// [`Trigon`]: primitive/type.Trigon.html
pub trait Monomorphic: StaticArity<Static = usize> {}

/// Arity of a compound structure.
///
/// `MeshArity` represents the arity of a compound structure, which may be
/// _uniform_ or _non-uniform_. This is typically the value-level arity for
/// mesh data structures like [`MeshGraph`] and [`MeshBuffer`].
///
/// [`MeshBuffer`]: buffer/struct.MeshBuffer.html
/// [`MeshGraph`]: graph/struct.MeshGraph.html
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MeshArity {
    /// A compound structure has _uniform_ arity if all of its components have
    /// the same arity, such as a `MeshBuffer` composed entirely of trigons.
    Uniform(usize),
    /// A compound structure has _non-uniform_ arity if the arity of its
    /// components differ, such as a `MeshGraph` composed of trigons and
    /// tetragons.
    ///
    /// Non-uniform arity is represented as an inclusive range known as an
    /// _interval_. This is the minimum and maximum arity of the components, in
    /// that order.
    NonUniform(usize, usize),
}

impl MeshArity {
    pub fn from_components<T, I>(components: I) -> Self
    where
        T: DynamicArity<Dynamic = usize>,
        I: IntoIterator,
        I::Item: Borrow<T>,
    {
        match components
            .into_iter()
            .map(|component| component.borrow().arity())
            .minmax()
        {
            MinMaxResult::OneElement(exact) => MeshArity::Uniform(exact),
            MinMaxResult::MinMax(min, max) => MeshArity::NonUniform(min, max),
            _ => MeshArity::Uniform(0),
        }
    }
}

impl Arity for MeshArity {
    fn into_interval(self) -> (usize, Option<usize>) {
        match self {
            MeshArity::Uniform(exact) => (exact, Some(exact)),
            MeshArity::NonUniform(min, max) => (min, Some(max)),
        }
    }
}

pub trait FromGeometry<T> {
    fn from_geometry(other: T) -> Self;
}

impl<T> FromGeometry<T> for T {
    fn from_geometry(other: T) -> Self {
        other
    }
}

/// Geometry elision into `()`.
impl<T> FromGeometry<T> for ()
where
    T: UnitGeometry,
{
    fn from_geometry(_: T) -> Self {}
}

/// Geometry elision from `()`.
impl<T> FromGeometry<()> for T
where
    T: UnitGeometry + Default,
{
    fn from_geometry(_: ()) -> Self {
        T::default()
    }
}

/// Geometry elision.
///
/// Geometric types that implement this trait may be elided. In particular,
/// these types may be converted into and from `()` via the [`FromGeometry`] and
/// [`IntoGeometry`] traits.
///
/// For a geometric type `T`, the following table illustrates the elisions in
/// which `T` may participate:
///
/// | Bounds on `T`            | From | Into |
/// |--------------------------|------|------|
/// | `UnitGeometry`           | `T`  | `()` |
/// | `Default + UnitGeometry` | `()` | `T`  |
///
/// These conversions are useful when converting between mesh data structures
/// with incompatible geometry, such as from a [`MeshGraph`] with face geometry
/// to a [`MeshBuffer`] that cannot support such geometry.
///
/// When geometry features are enabled, `UnitGeometry` is implemented for
/// integrated foreign types.
///
/// [`FromGeometry`]: trait.FromGeometry.html
/// [`IntoGeometry`]: trait.IntoGeometry.html
/// [`MeshBuffer`]: buffer/struct.MeshBuffer.html
/// [`MeshGraph`]: graph/struct.MeshGraph.html
pub trait UnitGeometry {}

pub trait IntoGeometry<T> {
    fn into_geometry(self) -> T;
}

impl<T, U> IntoGeometry<U> for T
where
    U: FromGeometry<T>,
{
    fn into_geometry(self) -> U {
        U::from_geometry(self)
    }
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection of ordered elements $\\{a, b, c\\}$, this iterator
    /// yeilds the ordered items $\\{(a, b), (b, c), (c, a)\\}$.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone,
    {
        Perimeter::new(self)
    }

    /// Maps an iterator over topological views to the keys of those views.
    ///
    /// It is often useful to examine or collect the keys of views over a
    /// [`MeshGraph`]. This iterator avoids redundant use of `map` to extract
    /// keys.
    ///
    /// # Examples
    ///
    /// Collecting keys of faces before a topological mutation:
    ///
    /// ```rust
    /// # extern crate decorum;
    /// # extern crate nalgebra;
    /// # extern crate plexus;
    /// #
    /// use decorum::R64;
    /// use nalgebra::Point3;
    /// use plexus::graph::MeshGraph;
    /// use plexus::prelude::*;
    /// use plexus::primitive::generate::Position;
    /// use plexus::primitive::sphere::UvSphere;
    ///
    /// type E3 = Point3<R64>;
    ///
    /// let mut graph = UvSphere::new(6, 6)
    ///     .polygons::<Position<E3>>()
    ///     .collect::<MeshGraph<E3>>();
    ///
    /// let keys = graph
    ///     .faces()
    ///     .filter(|face| face.arity() > 3)
    ///     .keys()
    ///     .collect::<Vec<_>>();
    /// for key in keys {
    ///     graph.face_mut(key).unwrap().poke_with_offset(0.5);
    /// }
    /// ```
    ///
    /// [`MeshGraph`]: graph/struct.MeshGraph.html
    fn keys(self) -> Keys<Self>
    where
        Self::Item: Binding,
    {
        Keys::new(self)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

/// Iterator that produces a window of duplets over its input.
///
/// The duplets produced include the first value in the input sequence at both
/// the beginning and end of the iteration, forming a perimeter. Given a
/// collection of ordered elements $\\{a, b, c\\}$, this iterator yields the
/// ordered items $\\{(a, b), (b, c), (c, a)\\}$.
#[derive(Clone)]
pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

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

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

#[derive(Clone)]
pub struct Keys<I>
where
    I: Iterator,
    I::Item: Binding,
{
    input: I,
}

impl<I> Keys<I>
where
    I: Iterator,
    I::Item: Binding,
{
    fn new(input: I) -> Self {
        Keys { input }
    }
}

impl<I> Iterator for Keys<I>
where
    I: Iterator,
    I::Item: Binding,
{
    type Item = <I::Item as Binding>::Key;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.next().map(|view| view.key())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use super::bls::{
    AggregateSignature,
    AggregatePublicKey,
};
use super::db::ClientDB;
use super::db::stores::{
    ValidatorStore,
    ValidatorStoreError,
};
use super::utils::types::Bitfield;

#[derive(Debug, PartialEq)]
pub enum SignatureVerificationError {
    BadValidatorIndex,
    PublicKeyCorrupt,
    NoPublicKeyForValidator,
    DBError(String),
}

/// Verify an aggregate signature across the supplied message.
///
/// The public keys used for verification are collected by mapping
/// each true bitfield bit to canonical ValidatorRecord index through
/// the attestation_indicies map.
///
/// Each public key is loaded from the store on-demand.
pub fn verify_aggregate_signature_for_indices<T>(
    message: &[u8],
    agg_sig: &AggregateSignature,
    attestation_indices: &[usize],
    bitfield: &Bitfield,
    validator_store: &ValidatorStore<T>)
    -> Result<Option<HashSet<usize>>, SignatureVerificationError>
    where T: ClientDB + Sized
{
    let mut voters = HashSet::new();
    let mut agg_pub_key = AggregatePublicKey::new();

    for i in 0..attestation_indices.len() {
        let voted = bitfield.get_bit(i);
        if voted {
            /*
             * De-reference the attestation index into a canonical ValidatorRecord index.
             */
            let validator = attestation_indices.get(i)
                .ok_or(SignatureVerificationError::BadValidatorIndex)?;
            /*
             * Load the validators public key from our store.
             */
            let pub_key = validator_store.get_public_key_by_index(i)?
                .ok_or(SignatureVerificationError::NoPublicKeyForValidator)?;
            /*
             * Add the validators public key to the aggregate public key.
             */
            agg_pub_key.add(&pub_key);
            /*
             * Add to the validator to the set of voters for this attestation record.
             */
            voters.insert(validator);
        }
    }
    /*
     * Verify the aggregate public key against the aggregate signature.
     *
     * This verification will only succeed if the exact set of public keys
     * were added to the aggregate public key as those that signed the aggregate signature.
     */
    if agg_sig.verify(&message, &agg_pub_key) {
        Ok(Some(voters))
    } else {
        Ok(None)
    }
}

impl From<ValidatorStoreError> for SignatureVerificationError {
    fn from(error: ValidatorStoreError) -> Self {
        match error {
            ValidatorStoreError::DBError(s) =>
                SignatureVerificationError::DBError(s),
            ValidatorStoreError::DecodeError =>
                SignatureVerificationError::PublicKeyCorrupt,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::bls::{
        Keypair,
        Signature,
    };
    use super::super::db::MemoryDB;
    use std::sync::Arc;

    /*
     * Cases that still need testing:
     *
     * - No signatures.
     * - Database failure.
     * - Unknown validator index.
     * - Extra validator on signature.
     */

    #[test]
    fn test_signature_verification() {
        let message = "cats".as_bytes();
        let signing_keypairs = vec![
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
        ];
        let non_signing_keypairs = vec![
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
        ];
        /*
         * Signing keypairs first, then non-signing
         */
        let mut all_keypairs = signing_keypairs.clone();
        all_keypairs.append(&mut non_signing_keypairs.clone());

        let attestation_indices: Vec<usize> = (0..all_keypairs.len())
            .collect();
        let mut bitfield = Bitfield::new();
        for i in 0..signing_keypairs.len() {
            bitfield.set_bit(i, true);
        }

        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db);

        for (i, keypair) in all_keypairs.iter().enumerate() {
            store.put_public_key_by_index(i, &keypair.pk).unwrap();
        }

        let mut agg_sig = AggregateSignature::new();
        for keypair in &signing_keypairs {
            let sig = Signature::new(&message, &keypair.sk);
            agg_sig.add(&sig);
        }

        /*
         * Test using all valid parameters.
         */
        let voters = verify_aggregate_signature_for_indices(
            &message,
            &agg_sig,
            &attestation_indices,
            &bitfield,
            &store).unwrap();

        let voters = voters.unwrap();
        (0..signing_keypairs.len())
            .for_each(|i| assert!(voters.contains(&i)));
        (signing_keypairs.len()..non_signing_keypairs.len())
            .for_each(|i| assert!(!voters.contains(&i)));

        /*
         * Add another validator to the bitfield, run validation will all other
         * parameters the same and assert that it fails.
         */
        bitfield.set_bit(signing_keypairs.len() + 1, true);
        let voters = verify_aggregate_signature_for_indices(
            &message,
            &agg_sig,
            &attestation_indices,
            &bitfield,
            &store).unwrap();

        assert_eq!(voters, None);
    }
}
<commit_msg>Fix bug introduced in previous commit<commit_after>use std::collections::HashSet;
use super::bls::{
    AggregateSignature,
    AggregatePublicKey,
};
use super::db::ClientDB;
use super::db::stores::{
    ValidatorStore,
    ValidatorStoreError,
};
use super::utils::types::Bitfield;

#[derive(Debug, PartialEq)]
pub enum SignatureVerificationError {
    BadValidatorIndex,
    PublicKeyCorrupt,
    NoPublicKeyForValidator,
    DBError(String),
}

/// Verify an aggregate signature across the supplied message.
///
/// The public keys used for verification are collected by mapping
/// each true bitfield bit to canonical ValidatorRecord index through
/// the attestation_indicies map.
///
/// Each public key is loaded from the store on-demand.
pub fn verify_aggregate_signature_for_indices<T>(
    message: &[u8],
    agg_sig: &AggregateSignature,
    attestation_indices: &[usize],
    bitfield: &Bitfield,
    validator_store: &ValidatorStore<T>)
    -> Result<Option<HashSet<usize>>, SignatureVerificationError>
    where T: ClientDB + Sized
{
    let mut voters = HashSet::new();
    let mut agg_pub_key = AggregatePublicKey::new();

    for i in 0..attestation_indices.len() {
        let voted = bitfield.get_bit(i);
        if voted {
            /*
             * De-reference the attestation index into a canonical ValidatorRecord index.
             */
            let validator = *attestation_indices.get(i)
                .ok_or(SignatureVerificationError::BadValidatorIndex)?;
            /*
             * Load the validators public key from our store.
             */
            let pub_key = validator_store.get_public_key_by_index(i)?
                .ok_or(SignatureVerificationError::NoPublicKeyForValidator)?;
            /*
             * Add the validators public key to the aggregate public key.
             */
            agg_pub_key.add(&pub_key);
            /*
             * Add to the validator to the set of voters for this attestation record.
             */
            voters.insert(validator);
        }
    }
    /*
     * Verify the aggregate public key against the aggregate signature.
     *
     * This verification will only succeed if the exact set of public keys
     * were added to the aggregate public key as those that signed the aggregate signature.
     */
    if agg_sig.verify(&message, &agg_pub_key) {
        Ok(Some(voters))
    } else {
        Ok(None)
    }
}

impl From<ValidatorStoreError> for SignatureVerificationError {
    fn from(error: ValidatorStoreError) -> Self {
        match error {
            ValidatorStoreError::DBError(s) =>
                SignatureVerificationError::DBError(s),
            ValidatorStoreError::DecodeError =>
                SignatureVerificationError::PublicKeyCorrupt,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::bls::{
        Keypair,
        Signature,
    };
    use super::super::db::MemoryDB;
    use std::sync::Arc;

    /*
     * Cases that still need testing:
     *
     * - No signatures.
     * - Database failure.
     * - Unknown validator index.
     * - Extra validator on signature.
     */

    #[test]
    fn test_signature_verification() {
        let message = "cats".as_bytes();
        let signing_keypairs = vec![
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
        ];
        let non_signing_keypairs = vec![
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
            Keypair::random(),
        ];
        /*
         * Signing keypairs first, then non-signing
         */
        let mut all_keypairs = signing_keypairs.clone();
        all_keypairs.append(&mut non_signing_keypairs.clone());

        let attestation_indices: Vec<usize> = (0..all_keypairs.len())
            .collect();
        let mut bitfield = Bitfield::new();
        for i in 0..signing_keypairs.len() {
            bitfield.set_bit(i, true);
        }

        let db = Arc::new(MemoryDB::open());
        let store = ValidatorStore::new(db);

        for (i, keypair) in all_keypairs.iter().enumerate() {
            store.put_public_key_by_index(i, &keypair.pk).unwrap();
        }

        let mut agg_sig = AggregateSignature::new();
        for keypair in &signing_keypairs {
            let sig = Signature::new(&message, &keypair.sk);
            agg_sig.add(&sig);
        }

        /*
         * Test using all valid parameters.
         */
        let voters = verify_aggregate_signature_for_indices(
            &message,
            &agg_sig,
            &attestation_indices,
            &bitfield,
            &store).unwrap();

        let voters = voters.unwrap();
        (0..signing_keypairs.len())
            .for_each(|i| assert!(voters.contains(&i)));
        (signing_keypairs.len()..non_signing_keypairs.len())
            .for_each(|i| assert!(!voters.contains(&i)));

        /*
         * Add another validator to the bitfield, run validation will all other
         * parameters the same and assert that it fails.
         */
        bitfield.set_bit(signing_keypairs.len() + 1, true);
        let voters = verify_aggregate_signature_for_indices(
            &message,
            &agg_sig,
            &attestation_indices,
            &bitfield,
            &store).unwrap();

        assert_eq!(voters, None);
    }
}
<|endoftext|>


<commit_before><commit_msg>Address comments<commit_after><|endoftext|>


<commit_before><commit_msg>MORE refraction bugs :D<commit_after><|endoftext|>


<commit_before><commit_msg>(feat) &Path -> AsRef<Path> [#87]<commit_after><|endoftext|>


<commit_before>#![feature(globs)]
#![crate_type = "bin"]

extern crate rgtk;
extern crate log;
extern crate debug;
extern crate collections;

use std::f64::consts::PI_2;

use rgtk::*;
use rgtk::gtk::signals;
use rgtk::gtk::DrawingArea;

use rgtk::cairo::enums::{
    FontSlantNormal,
    FontWeightNormal
};

fn main() {
    gtk::init();

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.set_source_rgb(250.0/255.0, 224.0/255.0, 55.0/255.0);
        cr.paint();

        cr.set_line_width(0.05);

        // border
        cr.set_source_rgb(0.3, 0.3, 0.3);
        cr.rectangle(0.0, 0.0, 1.0, 1.0);
        cr.stroke();

        cr.set_line_width(0.03);

        // draw circle
        cr.arc(0.5, 0.5, 0.4, 0.0, PI_2);
        cr.stroke();

        // mouth
        let mouth_top = 0.68;
        let mouth_width = 0.38;

        let mouth_dx = 0.10;
        let mouth_dy = 0.10;

        cr.move_to( 0.50 - mouth_width/2.0, mouth_top);
        cr.curve_to(0.50 - mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_width/2.0, mouth_top);

        println!("Extents: {}", cr.fill_extents());

        cr.stroke();

        let eye_y = 0.38;
        let eye_dx = 0.15;
        cr.arc(0.5 - eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();

        cr.arc(0.5 + eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();
    });

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.select_font_face("Sans",
                              cairo::enums::FontSlantNormal,
                              cairo::enums::FontWeightNormal);
        cr.set_font_size(0.35);

        cr.move_to(0.04, 0.53);
        cr.show_text("Hello");

        cr.move_to(0.27, 0.65);
        cr.text_path("void");
        cr.set_source_rgb(0.5, 0.5, 1.0);
        cr.fill_preserve();
        cr.set_source_rgb(0.0, 0.0, 0.0);
        cr.set_line_width(0.01);
        cr.stroke();

        cr.set_source_rgba(1.0, 0.2, 0.2, 0.6);
        cr.arc(0.04, 0.53, 0.02, 0.0, PI_2);
        cr.arc(0.27, 0.65, 0.02, 0.0, PI_2);
        cr.fill();
    });

    gtk::main();
}

pub fn drawable(width: i32, height: i32, draw_fn: |cairo::Context|){
    let mut window = gtk::Window::new(gtk::window_type::TopLevel).unwrap();
    let drawing_area = box DrawingArea::new().unwrap();

    drawing_area.connect(signals::Draw::new(draw_fn));

    window.set_default_size(width, height);

    window.connect(signals::DeleteEvent::new(|_|{
        gtk::main_quit();
        true
    }));
    window.add(&*drawing_area);
    window.show_all();
}<commit_msg>fix build<commit_after>#![feature(globs)]
#![crate_type = "bin"]

extern crate rgtk;
extern crate log;
extern crate collections;

use std::f64::consts::PI_2;

use rgtk::*;
use rgtk::gtk::signals;
use rgtk::gtk::DrawingArea;

use rgtk::cairo::enums::{
    FontSlantNormal,
    FontWeightNormal
};

fn main() {
    gtk::init();

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.set_source_rgb(250.0/255.0, 224.0/255.0, 55.0/255.0);
        cr.paint();

        cr.set_line_width(0.05);

        // border
        cr.set_source_rgb(0.3, 0.3, 0.3);
        cr.rectangle(0.0, 0.0, 1.0, 1.0);
        cr.stroke();

        cr.set_line_width(0.03);

        // draw circle
        cr.arc(0.5, 0.5, 0.4, 0.0, PI_2);
        cr.stroke();

        // mouth
        let mouth_top = 0.68;
        let mouth_width = 0.38;

        let mouth_dx = 0.10;
        let mouth_dy = 0.10;

        cr.move_to( 0.50 - mouth_width/2.0, mouth_top);
        cr.curve_to(0.50 - mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_width/2.0, mouth_top);

        println!("Extents: {}", cr.fill_extents());

        cr.stroke();

        let eye_y = 0.38;
        let eye_dx = 0.15;
        cr.arc(0.5 - eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();

        cr.arc(0.5 + eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();
    });

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.select_font_face("Sans",
                              cairo::enums::FontSlantNormal,
                              cairo::enums::FontWeightNormal);
        cr.set_font_size(0.35);

        cr.move_to(0.04, 0.53);
        cr.show_text("Hello");

        cr.move_to(0.27, 0.65);
        cr.text_path("void");
        cr.set_source_rgb(0.5, 0.5, 1.0);
        cr.fill_preserve();
        cr.set_source_rgb(0.0, 0.0, 0.0);
        cr.set_line_width(0.01);
        cr.stroke();

        cr.set_source_rgba(1.0, 0.2, 0.2, 0.6);
        cr.arc(0.04, 0.53, 0.02, 0.0, PI_2);
        cr.arc(0.27, 0.65, 0.02, 0.0, PI_2);
        cr.fill();
    });

    gtk::main();
}

pub fn drawable(width: i32, height: i32, draw_fn: |cairo::Context|){
    let mut window = gtk::Window::new(gtk::window_type::TopLevel).unwrap();
    let drawing_area = box DrawingArea::new().unwrap();

    drawing_area.connect(signals::Draw::new(draw_fn));

    window.set_default_size(width, height);

    window.connect(signals::DeleteEvent::new(|_|{
        gtk::main_quit();
        true
    }));
    window.add(&*drawing_area);
    window.show_all();
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::collections::hash_map::HashMap;
use std::fmt;
use std::io;
use std::mem;
use std::sync::mpsc::{channel, Receiver, Sender};

use crossbeam::{self, Scope};
use jobserver::{Acquired, HelperThread};

use core::{PackageId, Profile, Target};
use util::{Config, DependencyQueue, Dirty, Fresh, Freshness};
use util::{internal, profile, CargoResult, CargoResultExt, ProcessBuilder};
use handle_error;

use super::{Context, Kind, Unit};
use super::job::Job;

/// A management structure of the entire dependency graph to compile.
///
/// This structure is backed by the `DependencyQueue` type and manages the
/// actual compilation step of each package. Packages enqueue units of work and
/// then later on the entire graph is processed and compiled.
pub struct JobQueue<'a> {
    queue: DependencyQueue<Key<'a>, Vec<(Job, Freshness)>>,
    tx: Sender<Message<'a>>,
    rx: Receiver<Message<'a>>,
    active: usize,
    pending: HashMap<Key<'a>, PendingBuild>,
    compiled: HashSet<&'a PackageId>,
    documented: HashSet<&'a PackageId>,
    counts: HashMap<&'a PackageId, usize>,
    is_release: bool,
}

/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
    /// Number of jobs currently active
    amt: usize,
    /// Current freshness state of this package. Any dirty target within a
    /// package will cause the entire package to become dirty.
    fresh: Freshness,
}

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct Key<'a> {
    pkg: &'a PackageId,
    target: &'a Target,
    profile: &'a Profile,
    kind: Kind,
}

pub struct JobState<'a> {
    tx: Sender<Message<'a>>,
}

enum Message<'a> {
    Run(String),
    Stdout(String),
    Stderr(String),
    Token(io::Result<Acquired>),
    Finish(Key<'a>, CargoResult<()>),
}

impl<'a> JobState<'a> {
    pub fn running(&self, cmd: &ProcessBuilder) {
        let _ = self.tx.send(Message::Run(cmd.to_string()));
    }

    pub fn stdout(&self, out: &str) {
        let _ = self.tx.send(Message::Stdout(out.to_string()));
    }

    pub fn stderr(&self, err: &str) {
        let _ = self.tx.send(Message::Stderr(err.to_string()));
    }
}

impl<'a> JobQueue<'a> {
    pub fn new<'cfg>(cx: &Context<'a, 'cfg>) -> JobQueue<'a> {
        let (tx, rx) = channel();
        JobQueue {
            queue: DependencyQueue::new(),
            tx,
            rx,
            active: 0,
            pending: HashMap::new(),
            compiled: HashSet::new(),
            documented: HashSet::new(),
            counts: HashMap::new(),
            is_release: cx.build_config.release,
        }
    }

    pub fn enqueue<'cfg>(
        &mut self,
        cx: &Context<'a, 'cfg>,
        unit: &Unit<'a>,
        job: Job,
        fresh: Freshness,
    ) -> CargoResult<()> {
        let key = Key::new(unit);
        let deps = key.dependencies(cx)?;
        self.queue
            .queue(Fresh, key, Vec::new(), &deps)
            .push((job, fresh));
        *self.counts.entry(key.pkg).or_insert(0) += 1;
        Ok(())
    }

    /// Execute all jobs necessary to build the dependency graph.
    ///
    /// This function will spawn off `config.jobs()` workers to build all of the
    /// necessary dependencies, in order. Freshness is propagated as far as
    /// possible along each dependency chain.
    pub fn execute(&mut self, cx: &mut Context) -> CargoResult<()> {
        let _p = profile::start("executing the job graph");
        self.queue.queue_finished();

        // We need to give a handle to the send half of our message queue to the
        // jobserver helper thread. Unfortunately though we need the handle to be
        // `'static` as that's typically what's required when spawning a
        // thread!
        //
        // To work around this we transmute the `Sender` to a static lifetime.
        // we're only sending "longer living" messages and we should also
        // destroy all references to the channel before this function exits as
        // the destructor for the `helper` object will ensure the associated
        // thread is no longer running.
        //
        // As a result, this `transmute` to a longer lifetime should be safe in
        // practice.
        let tx = self.tx.clone();
        let tx = unsafe { mem::transmute::<Sender<Message<'a>>, Sender<Message<'static>>>(tx) };
        let helper = cx.jobserver
            .clone()
            .into_helper_thread(move |token| {
                drop(tx.send(Message::Token(token)));
            })
            .chain_err(|| "failed to create helper thread for jobserver management")?;

        crossbeam::scope(|scope| self.drain_the_queue(cx, scope, &helper))
    }

    fn drain_the_queue(
        &mut self,
        cx: &mut Context,
        scope: &Scope<'a>,
        jobserver_helper: &HelperThread,
    ) -> CargoResult<()> {
        let mut tokens = Vec::new();
        let mut queue = Vec::new();
        trace!("queue: {:#?}", self.queue);

        // Iteratively execute the entire dependency graph. Each turn of the
        // loop starts out by scheduling as much work as possible (up to the
        // maximum number of parallel jobs we have tokens for). A local queue
        // is maintained separately from the main dependency queue as one
        // dequeue may actually dequeue quite a bit of work (e.g. 10 binaries
        // in one project).
        //
        // After a job has finished we update our internal state if it was
        // successful and otherwise wait for pending work to finish if it failed
        // and then immediately return.
        let mut error = None;
        loop {
            // Dequeue as much work as we can, learning about everything
            // possible that can run. Note that this is also the point where we
            // start requesting job tokens. Each job after the first needs to
            // request a token.
            while let Some((fresh, key, jobs)) = self.queue.dequeue() {
                let total_fresh = jobs.iter().fold(fresh, |fresh, &(_, f)| f.combine(fresh));
                self.pending.insert(
                    key,
                    PendingBuild {
                        amt: jobs.len(),
                        fresh: total_fresh,
                    },
                );
                for (job, f) in jobs {
                    queue.push((key, job, f.combine(fresh)));
                    if self.active + queue.len() > 0 {
                        jobserver_helper.request_token();
                    }
                }
            }

            // Now that we've learned of all possible work that we can execute
            // try to spawn it so long as we've got a jobserver token which says
            // we're able to perform some parallel work.
            while error.is_none() && self.active < tokens.len() + 1 && !queue.is_empty() {
                let (key, job, fresh) = queue.remove(0);
                self.run(key, fresh, job, cx.config, scope)?;
            }

            // If after all that we're not actually running anything then we're
            // done!
            if self.active == 0 {
                break;
            }

            // And finally, before we block waiting for the next event, drop any
            // excess tokens we may have accidentally acquired. Due to how our
            // jobserver interface is architected we may acquire a token that we
            // don't actually use, and if this happens just relinquish it back
            // to the jobserver itself.
            tokens.truncate(self.active - 1);

            match self.rx.recv().unwrap() {
                Message::Run(cmd) => {
                    cx.config.shell().verbose(|c| c.status("Running", &cmd))?;
                }
                Message::Stdout(out) => {
                    if cx.config.extra_verbose() {
                        println!("{}", out);
                    }
                }
                Message::Stderr(err) => {
                    if cx.config.extra_verbose() {
                        writeln!(cx.config.shell().err(), "{}", err)?;
                    }
                }
                Message::Finish(key, result) => {
                    info!("end: {:?}", key);
                    self.active -= 1;
                    if self.active > 0 {
                        assert!(!tokens.is_empty());
                        drop(tokens.pop());
                    }
                    match result {
                        Ok(()) => self.finish(key, cx)?,
                        Err(e) => {
                            let msg = "The following warnings were emitted during compilation:";
                            self.emit_warnings(Some(msg), key, cx)?;

                            if self.active > 0 {
                                error = Some(format_err!("build failed"));
                                handle_error(e, &mut *cx.config.shell());
                                cx.config.shell().warn(
                                    "build failed, waiting for other \
                                     jobs to finish...",
                                )?;
                            } else {
                                error = Some(e);
                            }
                        }
                    }
                }
                Message::Token(acquired_token) => {
                    tokens.push(acquired_token.chain_err(|| "failed to acquire jobserver token")?);
                }
            }
        }

        let build_type = if self.is_release { "release" } else { "dev" };
        let profile = cx.lib_profile();
        let mut opt_type = String::from(if profile.opt_level == "0" {
            "unoptimized"
        } else {
            "optimized"
        });
        if profile.debuginfo.is_some() {
            opt_type += " + debuginfo";
        }
        let duration = cx.config.creation_time().elapsed();
        let time_elapsed = format!(
            "{}.{1:.2} secs",
            duration.as_secs(),
            duration.subsec_nanos() / 10_000_000
        );
        if self.queue.is_empty() {
            let message = format!(
                "{} [{}] target(s) in {}",
                build_type, opt_type, time_elapsed
            );
            cx.config.shell().status("Finished", message)?;
            Ok(())
        } else if let Some(e) = error {
            Err(e)
        } else {
            debug!("queue: {:#?}", self.queue);
            Err(internal("finished with jobs still left in the queue"))
        }
    }

    /// Executes a job in the `scope` given, pushing the spawned thread's
    /// handled onto `threads`.
    fn run(
        &mut self,
        key: Key<'a>,
        fresh: Freshness,
        job: Job,
        config: &Config,
        scope: &Scope<'a>,
    ) -> CargoResult<()> {
        info!("start: {:?}", key);

        self.active += 1;
        *self.counts.get_mut(key.pkg).unwrap() -= 1;

        let my_tx = self.tx.clone();
        let doit = move || {
            let res = job.run(fresh, &JobState { tx: my_tx.clone() });
            my_tx.send(Message::Finish(key, res)).unwrap();
        };
        match fresh {
            Freshness::Fresh => doit(),
            Freshness::Dirty => {
                scope.spawn(doit);
            }
        }

        // Print out some nice progress information
        self.note_working_on(config, &key, fresh)?;

        Ok(())
    }

    fn emit_warnings(&self, msg: Option<&str>, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
        let output = cx.build_state.outputs.lock().unwrap();
        if let Some(output) = output.get(&(key.pkg.clone(), key.kind)) {
            if let Some(msg) = msg {
                if !output.warnings.is_empty() {
                    writeln!(cx.config.shell().err(), "{}\n", msg)?;
                }
            }

            for warning in output.warnings.iter() {
                cx.config.shell().warn(warning)?;
            }

            if !output.warnings.is_empty() && msg.is_some() {
                // Output an empty line.
                writeln!(cx.config.shell().err(), "")?;
            }
        }

        Ok(())
    }

    fn finish(&mut self, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
        if key.profile.run_custom_build && cx.show_warnings(key.pkg) {
            self.emit_warnings(None, key, cx)?;
        }

        let state = self.pending.get_mut(&key).unwrap();
        state.amt -= 1;
        if state.amt == 0 {
            self.queue.finish(&key, state.fresh);
        }
        Ok(())
    }

    // This isn't super trivial because we don't want to print loads and
    // loads of information to the console, but we also want to produce a
    // faithful representation of what's happening. This is somewhat nuanced
    // as a package can start compiling *very* early on because of custom
    // build commands and such.
    //
    // In general, we try to print "Compiling" for the first nontrivial task
    // run for a package, regardless of when that is. We then don't print
    // out any more information for a package after we've printed it once.
    fn note_working_on(
        &mut self,
        config: &Config,
        key: &Key<'a>,
        fresh: Freshness,
    ) -> CargoResult<()> {
        if (self.compiled.contains(key.pkg) && !key.profile.doc)
            || (self.documented.contains(key.pkg) && key.profile.doc)
        {
            return Ok(());
        }

        match fresh {
            // Any dirty stage which runs at least one command gets printed as
            // being a compiled package
            Dirty => {
                if key.profile.doc {
                    if !key.profile.test {
                        self.documented.insert(key.pkg);
                        config.shell().status("Documenting", key.pkg)?;
                    }
                } else {
                    self.compiled.insert(key.pkg);
                    config.shell().status("Compiling", key.pkg)?;
                }
            }
            Fresh if self.counts[key.pkg] == 0 => {
                self.compiled.insert(key.pkg);
                config.shell().verbose(|c| c.status("Fresh", key.pkg))?;
            }
            Fresh => {}
        }
        Ok(())
    }
}

impl<'a> Key<'a> {
    fn new(unit: &Unit<'a>) -> Key<'a> {
        Key {
            pkg: unit.pkg.package_id(),
            target: unit.target,
            profile: unit.profile,
            kind: unit.kind,
        }
    }

    fn dependencies<'cfg>(&self, cx: &Context<'a, 'cfg>) -> CargoResult<Vec<Key<'a>>> {
        let unit = Unit {
            pkg: cx.get_package(self.pkg)?,
            target: self.target,
            profile: self.profile,
            kind: self.kind,
        };
        let targets = cx.dep_targets(&unit);
        Ok(targets
            .iter()
            .filter_map(|unit| {
                // Binaries aren't actually needed to *compile* tests, just to run
                // them, so we don't include this dependency edge in the job graph.
                if self.target.is_test() && unit.target.is_bin() {
                    None
                } else {
                    Some(Key::new(unit))
                }
            })
            .collect())
    }
}

impl<'a> fmt::Debug for Key<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} => {}/{} => {:?}",
            self.pkg, self.target, self.profile, self.kind
        )
    }
}
<commit_msg>Auto merge of #5357 - matklad:even-rust-has-format-string-bugs, r=alexcrichton<commit_after>use std::collections::HashSet;
use std::collections::hash_map::HashMap;
use std::fmt;
use std::io;
use std::mem;
use std::sync::mpsc::{channel, Receiver, Sender};

use crossbeam::{self, Scope};
use jobserver::{Acquired, HelperThread};

use core::{PackageId, Profile, Target};
use util::{Config, DependencyQueue, Dirty, Fresh, Freshness};
use util::{internal, profile, CargoResult, CargoResultExt, ProcessBuilder};
use handle_error;

use super::{Context, Kind, Unit};
use super::job::Job;

/// A management structure of the entire dependency graph to compile.
///
/// This structure is backed by the `DependencyQueue` type and manages the
/// actual compilation step of each package. Packages enqueue units of work and
/// then later on the entire graph is processed and compiled.
pub struct JobQueue<'a> {
    queue: DependencyQueue<Key<'a>, Vec<(Job, Freshness)>>,
    tx: Sender<Message<'a>>,
    rx: Receiver<Message<'a>>,
    active: usize,
    pending: HashMap<Key<'a>, PendingBuild>,
    compiled: HashSet<&'a PackageId>,
    documented: HashSet<&'a PackageId>,
    counts: HashMap<&'a PackageId, usize>,
    is_release: bool,
}

/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
    /// Number of jobs currently active
    amt: usize,
    /// Current freshness state of this package. Any dirty target within a
    /// package will cause the entire package to become dirty.
    fresh: Freshness,
}

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct Key<'a> {
    pkg: &'a PackageId,
    target: &'a Target,
    profile: &'a Profile,
    kind: Kind,
}

pub struct JobState<'a> {
    tx: Sender<Message<'a>>,
}

enum Message<'a> {
    Run(String),
    Stdout(String),
    Stderr(String),
    Token(io::Result<Acquired>),
    Finish(Key<'a>, CargoResult<()>),
}

impl<'a> JobState<'a> {
    pub fn running(&self, cmd: &ProcessBuilder) {
        let _ = self.tx.send(Message::Run(cmd.to_string()));
    }

    pub fn stdout(&self, out: &str) {
        let _ = self.tx.send(Message::Stdout(out.to_string()));
    }

    pub fn stderr(&self, err: &str) {
        let _ = self.tx.send(Message::Stderr(err.to_string()));
    }
}

impl<'a> JobQueue<'a> {
    pub fn new<'cfg>(cx: &Context<'a, 'cfg>) -> JobQueue<'a> {
        let (tx, rx) = channel();
        JobQueue {
            queue: DependencyQueue::new(),
            tx,
            rx,
            active: 0,
            pending: HashMap::new(),
            compiled: HashSet::new(),
            documented: HashSet::new(),
            counts: HashMap::new(),
            is_release: cx.build_config.release,
        }
    }

    pub fn enqueue<'cfg>(
        &mut self,
        cx: &Context<'a, 'cfg>,
        unit: &Unit<'a>,
        job: Job,
        fresh: Freshness,
    ) -> CargoResult<()> {
        let key = Key::new(unit);
        let deps = key.dependencies(cx)?;
        self.queue
            .queue(Fresh, key, Vec::new(), &deps)
            .push((job, fresh));
        *self.counts.entry(key.pkg).or_insert(0) += 1;
        Ok(())
    }

    /// Execute all jobs necessary to build the dependency graph.
    ///
    /// This function will spawn off `config.jobs()` workers to build all of the
    /// necessary dependencies, in order. Freshness is propagated as far as
    /// possible along each dependency chain.
    pub fn execute(&mut self, cx: &mut Context) -> CargoResult<()> {
        let _p = profile::start("executing the job graph");
        self.queue.queue_finished();

        // We need to give a handle to the send half of our message queue to the
        // jobserver helper thread. Unfortunately though we need the handle to be
        // `'static` as that's typically what's required when spawning a
        // thread!
        //
        // To work around this we transmute the `Sender` to a static lifetime.
        // we're only sending "longer living" messages and we should also
        // destroy all references to the channel before this function exits as
        // the destructor for the `helper` object will ensure the associated
        // thread is no longer running.
        //
        // As a result, this `transmute` to a longer lifetime should be safe in
        // practice.
        let tx = self.tx.clone();
        let tx = unsafe { mem::transmute::<Sender<Message<'a>>, Sender<Message<'static>>>(tx) };
        let helper = cx.jobserver
            .clone()
            .into_helper_thread(move |token| {
                drop(tx.send(Message::Token(token)));
            })
            .chain_err(|| "failed to create helper thread for jobserver management")?;

        crossbeam::scope(|scope| self.drain_the_queue(cx, scope, &helper))
    }

    fn drain_the_queue(
        &mut self,
        cx: &mut Context,
        scope: &Scope<'a>,
        jobserver_helper: &HelperThread,
    ) -> CargoResult<()> {
        let mut tokens = Vec::new();
        let mut queue = Vec::new();
        trace!("queue: {:#?}", self.queue);

        // Iteratively execute the entire dependency graph. Each turn of the
        // loop starts out by scheduling as much work as possible (up to the
        // maximum number of parallel jobs we have tokens for). A local queue
        // is maintained separately from the main dependency queue as one
        // dequeue may actually dequeue quite a bit of work (e.g. 10 binaries
        // in one project).
        //
        // After a job has finished we update our internal state if it was
        // successful and otherwise wait for pending work to finish if it failed
        // and then immediately return.
        let mut error = None;
        loop {
            // Dequeue as much work as we can, learning about everything
            // possible that can run. Note that this is also the point where we
            // start requesting job tokens. Each job after the first needs to
            // request a token.
            while let Some((fresh, key, jobs)) = self.queue.dequeue() {
                let total_fresh = jobs.iter().fold(fresh, |fresh, &(_, f)| f.combine(fresh));
                self.pending.insert(
                    key,
                    PendingBuild {
                        amt: jobs.len(),
                        fresh: total_fresh,
                    },
                );
                for (job, f) in jobs {
                    queue.push((key, job, f.combine(fresh)));
                    if self.active + queue.len() > 0 {
                        jobserver_helper.request_token();
                    }
                }
            }

            // Now that we've learned of all possible work that we can execute
            // try to spawn it so long as we've got a jobserver token which says
            // we're able to perform some parallel work.
            while error.is_none() && self.active < tokens.len() + 1 && !queue.is_empty() {
                let (key, job, fresh) = queue.remove(0);
                self.run(key, fresh, job, cx.config, scope)?;
            }

            // If after all that we're not actually running anything then we're
            // done!
            if self.active == 0 {
                break;
            }

            // And finally, before we block waiting for the next event, drop any
            // excess tokens we may have accidentally acquired. Due to how our
            // jobserver interface is architected we may acquire a token that we
            // don't actually use, and if this happens just relinquish it back
            // to the jobserver itself.
            tokens.truncate(self.active - 1);

            match self.rx.recv().unwrap() {
                Message::Run(cmd) => {
                    cx.config.shell().verbose(|c| c.status("Running", &cmd))?;
                }
                Message::Stdout(out) => {
                    if cx.config.extra_verbose() {
                        println!("{}", out);
                    }
                }
                Message::Stderr(err) => {
                    if cx.config.extra_verbose() {
                        writeln!(cx.config.shell().err(), "{}", err)?;
                    }
                }
                Message::Finish(key, result) => {
                    info!("end: {:?}", key);
                    self.active -= 1;
                    if self.active > 0 {
                        assert!(!tokens.is_empty());
                        drop(tokens.pop());
                    }
                    match result {
                        Ok(()) => self.finish(key, cx)?,
                        Err(e) => {
                            let msg = "The following warnings were emitted during compilation:";
                            self.emit_warnings(Some(msg), key, cx)?;

                            if self.active > 0 {
                                error = Some(format_err!("build failed"));
                                handle_error(e, &mut *cx.config.shell());
                                cx.config.shell().warn(
                                    "build failed, waiting for other \
                                     jobs to finish...",
                                )?;
                            } else {
                                error = Some(e);
                            }
                        }
                    }
                }
                Message::Token(acquired_token) => {
                    tokens.push(acquired_token.chain_err(|| "failed to acquire jobserver token")?);
                }
            }
        }

        let build_type = if self.is_release { "release" } else { "dev" };
        let profile = cx.lib_profile();
        let mut opt_type = String::from(if profile.opt_level == "0" {
            "unoptimized"
        } else {
            "optimized"
        });
        if profile.debuginfo.is_some() {
            opt_type += " + debuginfo";
        }
        let duration = cx.config.creation_time().elapsed();
        let time_elapsed = format!(
            "{}.{:02} secs",
            duration.as_secs(),
            duration.subsec_nanos() / 10_000_000
        );
        if self.queue.is_empty() {
            let message = format!(
                "{} [{}] target(s) in {}",
                build_type, opt_type, time_elapsed
            );
            cx.config.shell().status("Finished", message)?;
            Ok(())
        } else if let Some(e) = error {
            Err(e)
        } else {
            debug!("queue: {:#?}", self.queue);
            Err(internal("finished with jobs still left in the queue"))
        }
    }

    /// Executes a job in the `scope` given, pushing the spawned thread's
    /// handled onto `threads`.
    fn run(
        &mut self,
        key: Key<'a>,
        fresh: Freshness,
        job: Job,
        config: &Config,
        scope: &Scope<'a>,
    ) -> CargoResult<()> {
        info!("start: {:?}", key);

        self.active += 1;
        *self.counts.get_mut(key.pkg).unwrap() -= 1;

        let my_tx = self.tx.clone();
        let doit = move || {
            let res = job.run(fresh, &JobState { tx: my_tx.clone() });
            my_tx.send(Message::Finish(key, res)).unwrap();
        };
        match fresh {
            Freshness::Fresh => doit(),
            Freshness::Dirty => {
                scope.spawn(doit);
            }
        }

        // Print out some nice progress information
        self.note_working_on(config, &key, fresh)?;

        Ok(())
    }

    fn emit_warnings(&self, msg: Option<&str>, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
        let output = cx.build_state.outputs.lock().unwrap();
        if let Some(output) = output.get(&(key.pkg.clone(), key.kind)) {
            if let Some(msg) = msg {
                if !output.warnings.is_empty() {
                    writeln!(cx.config.shell().err(), "{}\n", msg)?;
                }
            }

            for warning in output.warnings.iter() {
                cx.config.shell().warn(warning)?;
            }

            if !output.warnings.is_empty() && msg.is_some() {
                // Output an empty line.
                writeln!(cx.config.shell().err(), "")?;
            }
        }

        Ok(())
    }

    fn finish(&mut self, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
        if key.profile.run_custom_build && cx.show_warnings(key.pkg) {
            self.emit_warnings(None, key, cx)?;
        }

        let state = self.pending.get_mut(&key).unwrap();
        state.amt -= 1;
        if state.amt == 0 {
            self.queue.finish(&key, state.fresh);
        }
        Ok(())
    }

    // This isn't super trivial because we don't want to print loads and
    // loads of information to the console, but we also want to produce a
    // faithful representation of what's happening. This is somewhat nuanced
    // as a package can start compiling *very* early on because of custom
    // build commands and such.
    //
    // In general, we try to print "Compiling" for the first nontrivial task
    // run for a package, regardless of when that is. We then don't print
    // out any more information for a package after we've printed it once.
    fn note_working_on(
        &mut self,
        config: &Config,
        key: &Key<'a>,
        fresh: Freshness,
    ) -> CargoResult<()> {
        if (self.compiled.contains(key.pkg) && !key.profile.doc)
            || (self.documented.contains(key.pkg) && key.profile.doc)
        {
            return Ok(());
        }

        match fresh {
            // Any dirty stage which runs at least one command gets printed as
            // being a compiled package
            Dirty => {
                if key.profile.doc {
                    if !key.profile.test {
                        self.documented.insert(key.pkg);
                        config.shell().status("Documenting", key.pkg)?;
                    }
                } else {
                    self.compiled.insert(key.pkg);
                    config.shell().status("Compiling", key.pkg)?;
                }
            }
            Fresh if self.counts[key.pkg] == 0 => {
                self.compiled.insert(key.pkg);
                config.shell().verbose(|c| c.status("Fresh", key.pkg))?;
            }
            Fresh => {}
        }
        Ok(())
    }
}

impl<'a> Key<'a> {
    fn new(unit: &Unit<'a>) -> Key<'a> {
        Key {
            pkg: unit.pkg.package_id(),
            target: unit.target,
            profile: unit.profile,
            kind: unit.kind,
        }
    }

    fn dependencies<'cfg>(&self, cx: &Context<'a, 'cfg>) -> CargoResult<Vec<Key<'a>>> {
        let unit = Unit {
            pkg: cx.get_package(self.pkg)?,
            target: self.target,
            profile: self.profile,
            kind: self.kind,
        };
        let targets = cx.dep_targets(&unit);
        Ok(targets
            .iter()
            .filter_map(|unit| {
                // Binaries aren't actually needed to *compile* tests, just to run
                // them, so we don't include this dependency edge in the job graph.
                if self.target.is_test() && unit.target.is_bin() {
                    None
                } else {
                    Some(Key::new(unit))
                }
            })
            .collect())
    }
}

impl<'a> fmt::Debug for Key<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} => {}/{} => {:?}",
            self.pkg, self.target, self.profile, self.kind
        )
    }
}
<|endoftext|>