<commit_before>//! A general purpose `Batcher` implementation based on radix sort.

use timely::progress::frontier::Antichain;

use ::Diff;

use lattice::Lattice;
use trace::{Batch, Batcher, Builder};

/// Creates batches from unordered tuples.
pub struct MergeBatcher<K: Ord, V: Ord, T: Ord, R: Diff, B: Batch<K, V, T, R>> {
    sorter: MergeSorter<(K, V), T, R>,
    lower: Vec<T>,
    frontier: Antichain<T>,
    phantom: ::std::marker::PhantomData<B>,
}

impl<K, V, T, R, B> Batcher<K, V, T, R, B> for MergeBatcher<K, V, T, R, B>
where
    K: Ord+Clone,
    V: Ord+Clone,
    T: Lattice+Ord+Clone,
    R: Diff,
    B: Batch<K, V, T, R>,
{
    fn new() -> Self {
        MergeBatcher {
            sorter: MergeSorter::new(),
            frontier: Antichain::new(),
            lower: vec![T::minimum()],
            phantom: ::std::marker::PhantomData,
        }
    }

    #[inline(never)]
    fn push_batch(&mut self, batch: &mut Vec<((K,V),T,R)>) {
        self.sorter.push(batch);
    }

    // Sealing a batch means finding those updates with times not greater or equal to any time
    // in `upper`. All updates must have time greater or equal to the previously used `upper`,
    // which we call `lower`, by assumption that after sealing a batcher we receive no more
    // updates with times not greater or equal to `upper`.
    #[inline(never)]
    fn seal(&mut self, upper: &[T]) -> B {

        let mut builder = B::Builder::new();

        let mut merged = Vec::new();
        self.sorter.finish_into(&mut merged);

        let mut kept = Vec::new();
        let mut keep = Vec::with_capacity(1024);

        self.frontier.clear();

        // TODO: Re-use buffer, rather than dropping.
        for mut buffer in merged.drain(..) {
            for ((key, val), time, diff) in buffer.drain(..) {
                if upper.iter().any(|t| t.less_equal(&time)) {
                    // keep_count += 1;
                    self.frontier.insert(time.clone());
                    keep.push(((key, val), time, diff));
                    if keep.len() == keep.capacity() {
                        kept.push(keep);
                        keep = self.sorter.empty();
                    }
                }
                else {
                    // seal_count += 1;
                    builder.push((key, val, time, diff));
                }
            }
        }
        if keep.len() > 0 {
            kept.push(keep);
        }
        if kept.len() > 0 {
            self.sorter.push_list(kept);
        }

        let seal = builder.done(&self.lower[..], &upper[..], &self.lower[..]);
        self.lower = upper.to_vec();
        seal
    }

    // the frontier of elements remaining after the most recent call to `self.seal`.
    fn frontier(&mut self) -> &[T] {
        self.frontier.elements()
    }
}

use std::slice::{from_raw_parts};

pub struct VecQueue<T> {
    list: Vec<T>,
    head: usize,
    tail: usize,
}

impl<T> VecQueue<T> {
    #[inline(always)]
    pub fn new() -> Self { VecQueue::from(Vec::new()) }
    #[inline(always)]
    pub fn pop(&mut self) -> T {
        debug_assert!(self.head < self.tail);
        self.head += 1;
        unsafe { ::std::ptr::read(self.list.as_mut_ptr().offset((self.head as isize) - 1)) }
    }
    #[inline(always)]
    pub fn peek(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.head) }
    }
    #[inline(always)]
    pub fn _peek_tail(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.tail-1) }
    }
    #[inline(always)]
    pub fn _slice(&self) -> &[T] {
        debug_assert!(self.head < self.tail);
        unsafe { from_raw_parts(self.list.get_unchecked(self.head), self.tail - self.head) }
    }
    #[inline(always)]
    pub fn from(mut list: Vec<T>) -> Self {
        let tail = list.len();
        unsafe { list.set_len(0); }
        VecQueue {
            list: list,
            head: 0,
            tail: tail,
        }
    }
    // could leak, if self.head != self.tail.
    #[inline(always)]
    pub fn done(self) -> Vec<T> {
        debug_assert!(self.head == self.tail);
        self.list
    }
    #[inline(always)]
    pub fn len(&self) -> usize { self.tail - self.head }
    #[inline(always)]
    pub fn is_empty(&self) -> bool { self.head == self.tail }
}

#[inline(always)]
unsafe fn push_unchecked<T>(vec: &mut Vec<T>, element: T) {
    debug_assert!(vec.len() < vec.capacity());
    let len = vec.len();
    ::std::ptr::write(vec.get_unchecked_mut(len), element);
    vec.set_len(len + 1);
}

pub struct MergeSorter<D: Ord, T: Ord, R: Diff> {
    queue: Vec<Vec<Vec<(D, T, R)>>>,    // each power-of-two length list of allocations.
    stash: Vec<Vec<(D, T, R)>>,
}

impl<D: Ord, T: Ord, R: Diff> MergeSorter<D, T, R> {

    #[inline]
    pub fn new() -> Self { MergeSorter { queue: Vec::new(), stash: Vec::new() } }

    #[inline]
    pub fn empty(&mut self) -> Vec<(D, T, R)> {
        self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024))
    }

    #[inline(never)]
    pub fn _sort(&mut self, list: &mut Vec<Vec<(D, T, R)>>) {
        for mut batch in list.drain(..) {
            self.push(&mut batch);
        }
        self.finish_into(list);
    }

    #[inline]
    pub fn push(&mut self, batch: &mut Vec<(D, T, R)>) {
        // TODO: Reason about possible unbounded stash growth. How to / should we return them?
        // TODO: Reason about mis-sized vectors, from deserialized data; should probably drop.
        let mut batch = if self.stash.len() > 2 {
            ::std::mem::replace(batch, self.stash.pop().unwrap())
        }
        else {
            ::std::mem::replace(batch, Vec::new())
        };

        if batch.len() > 0 {
            batch.sort_unstable_by(|x,y| (&x.0, &x.1).cmp(&(&y.0, &y.1)));
            for index in 1 .. batch.len() {
                if batch[index].0 == batch[index - 1].0 && batch[index].1 == batch[index - 1].1 {
                    batch[index].2 = batch[index].2 + batch[index - 1].2;
                    batch[index - 1].2 = R::zero();
                }
            }
            batch.retain(|x| !x.2.is_zero());

            self.queue.push(vec![batch]);
            while self.queue.len() > 1 && (self.queue[self.queue.len()-1].len() >= self.queue[self.queue.len()-2].len() / 2) {
                let list1 = self.queue.pop().unwrap();
                let list2 = self.queue.pop().unwrap();
                let merged = self.merge_by(list1, list2);
                self.queue.push(merged);
            }
        }
    }

    // This is awkward, because it isn't a power-of-two length any more, and we don't want
    // to break it down to be so.
    pub fn push_list(&mut self, list: Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 && self.queue[self.queue.len()-1].len() < list.len() {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }
        self.queue.push(list);
    }

    #[inline(never)]
    pub fn finish_into(&mut self, target: &mut Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }

        if let Some(mut last) = self.queue.pop() {
            ::std::mem::swap(&mut last, target);
        }
    }

    // merges two sorted input lists into one sorted output list.
    #[inline(never)]
    fn merge_by(&mut self, list1: Vec<Vec<(D, T, R)>>, list2: Vec<Vec<(D, T, R)>>) -> Vec<Vec<(D, T, R)>> {

        use std::cmp::Ordering;

        // TODO: `list1` and `list2` get dropped; would be better to reuse?
        let mut output = Vec::with_capacity(list1.len() + list2.len());
        let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));

        let mut list1 = VecQueue::from(list1);
        let mut list2 = VecQueue::from(list2);

        let mut head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
        let mut head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };

        // while we have valid data in each input, merge.
        while !head1.is_empty() && !head2.is_empty() {

            while (result.capacity() - result.len()) > 0 && head1.len() > 0 && head2.len() > 0 {

                let cmp = {
                    let x = head1.peek();
                    let y = head2.peek();
                    (&x.0, &x.1).cmp(&(&y.0, &y.1))
                };
                match cmp {
                    Ordering::Less    => { unsafe { push_unchecked(&mut result, head1.pop()); } }
                    Ordering::Greater => { unsafe { push_unchecked(&mut result, head2.pop()); } }
                    Ordering::Equal   => {
                        let (data1, time1, diff1) = head1.pop();
                        let (_data2, _time2, diff2) = head2.pop();
                        let diff = diff1 + diff2;
                        if !diff.is_zero() {
                            unsafe { push_unchecked(&mut result, (data1, time1, diff)); }
                        }
                    }
                }
            }

            if result.capacity() == result.len() {
                output.push(result);
                result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            }

            if head1.is_empty() {
                let done1 = head1.done();
                if done1.capacity() == 1024 { self.stash.push(done1); }
                head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
            }
            if head2.is_empty() {
                let done2 = head2.done();
                if done2.capacity() == 1024 { self.stash.push(done2); }
                head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };
            }
        }

        if result.len() > 0 { output.push(result); }
        else if result.capacity() > 0 { self.stash.push(result); }

        if !head1.is_empty() {
            let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            for _ in 0 .. head1.len() { result.push(head1.pop()); }
            output.push(result);
        }
        while !list1.is_empty() {
            output.push(list1.pop());
        }

        if !head2.is_empty() {
            let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            for _ in 0 .. head2.len() { result.push(head2.pop()); }
            output.push(result);
        }
        while !list2.is_empty() {
            output.push(list2.pop());
        }

        output
    }
}

/// Reports the number of elements satisfing the predicate.
///
/// This methods *relies strongly* on the assumption that the predicate
/// stays false once it becomes false, a joint property of the predicate
/// and the slice. This allows `advance` to use exponential search to
/// count the number of elements in time logarithmic in the result.
#[inline(always)]
pub fn _advance<T, F: Fn(&T)->bool>(slice: &[T], function: F) -> usize {

	// start with no advance
	let mut index = 0;
	if index < slice.len() && function(&slice[index]) {

		// advance in exponentially growing steps.
		let mut step = 1;
		while index + step < slice.len() && function(&slice[index + step]) {
			index += step;
			step = step << 1;
		}

		// advance in exponentially shrinking steps.
		step = step >> 1;
		while step > 0 {
			if index + step < slice.len() && function(&slice[index + step]) {
				index += step;
			}
			step = step >> 1;
		}

		index += 1;
	}

	index
}
<commit_msg>reduce allocations<commit_after>//! A general purpose `Batcher` implementation based on radix sort.

use timely::progress::frontier::Antichain;

use ::Diff;

use lattice::Lattice;
use trace::{Batch, Batcher, Builder};

/// Creates batches from unordered tuples.
pub struct MergeBatcher<K: Ord, V: Ord, T: Ord, R: Diff, B: Batch<K, V, T, R>> {
    sorter: MergeSorter<(K, V), T, R>,
    lower: Vec<T>,
    frontier: Antichain<T>,
    phantom: ::std::marker::PhantomData<B>,
}

impl<K, V, T, R, B> Batcher<K, V, T, R, B> for MergeBatcher<K, V, T, R, B>
where
    K: Ord+Clone,
    V: Ord+Clone,
    T: Lattice+Ord+Clone,
    R: Diff,
    B: Batch<K, V, T, R>,
{
    fn new() -> Self {
        MergeBatcher {
            sorter: MergeSorter::new(),
            frontier: Antichain::new(),
            lower: vec![T::minimum()],
            phantom: ::std::marker::PhantomData,
        }
    }

    #[inline(never)]
    fn push_batch(&mut self, batch: &mut Vec<((K,V),T,R)>) {
        self.sorter.push(batch);
    }

    // Sealing a batch means finding those updates with times not greater or equal to any time
    // in `upper`. All updates must have time greater or equal to the previously used `upper`,
    // which we call `lower`, by assumption that after sealing a batcher we receive no more
    // updates with times not greater or equal to `upper`.
    #[inline(never)]
    fn seal(&mut self, upper: &[T]) -> B {

        let mut builder = B::Builder::new();

        let mut merged = Vec::new();
        self.sorter.finish_into(&mut merged);

        let mut kept = Vec::new();
        let mut keep = Vec::new();

        self.frontier.clear();

        // TODO: Re-use buffer, rather than dropping.
        for mut buffer in merged.drain(..) {
            for ((key, val), time, diff) in buffer.drain(..) {
                if upper.iter().any(|t| t.less_equal(&time)) {
                    // keep_count += 1;
                    self.frontier.insert(time.clone());
                    if keep.len() == keep.capacity() {
                        if keep.len() > 0 {
                            kept.push(keep);
                            keep = self.sorter.empty();
                        }
                    }
                    keep.push(((key, val), time, diff));
                }
                else {
                    // seal_count += 1;
                    builder.push((key, val, time, diff));
                }
            }
            // Recycling buffer.
            self.sorter.push(&mut buffer);
        }

        // Finish the kept data.
        if keep.len() > 0 {
            kept.push(keep);
        }
        if kept.len() > 0 {
            self.sorter.push_list(kept);
        }

        // Drain buffers (fast reclaimation).
        // TODO : This isn't obviously the best policy, but "safe" wrt footprint.
        //        In particular, if we are reading serialized input data, we may
        //        prefer to keep these buffers around to re-fill, if possible.
        let mut buffer = Vec::new();
        self.sorter.push(&mut buffer);
        while buffer.capacity() > 0 {
            buffer = Vec::new();
            self.sorter.push(&mut buffer);
        }

        let seal = builder.done(&self.lower[..], &upper[..], &self.lower[..]);
        self.lower = upper.to_vec();
        seal
    }

    // the frontier of elements remaining after the most recent call to `self.seal`.
    fn frontier(&mut self) -> &[T] {
        self.frontier.elements()
    }
}

use std::slice::{from_raw_parts};

pub struct VecQueue<T> {
    list: Vec<T>,
    head: usize,
    tail: usize,
}

impl<T> VecQueue<T> {
    #[inline(always)]
    pub fn new() -> Self { VecQueue::from(Vec::new()) }
    #[inline(always)]
    pub fn pop(&mut self) -> T {
        debug_assert!(self.head < self.tail);
        self.head += 1;
        unsafe { ::std::ptr::read(self.list.as_mut_ptr().offset((self.head as isize) - 1)) }
    }
    #[inline(always)]
    pub fn peek(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.head) }
    }
    #[inline(always)]
    pub fn _peek_tail(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.tail-1) }
    }
    #[inline(always)]
    pub fn _slice(&self) -> &[T] {
        debug_assert!(self.head < self.tail);
        unsafe { from_raw_parts(self.list.get_unchecked(self.head), self.tail - self.head) }
    }
    #[inline(always)]
    pub fn from(mut list: Vec<T>) -> Self {
        let tail = list.len();
        unsafe { list.set_len(0); }
        VecQueue {
            list: list,
            head: 0,
            tail: tail,
        }
    }
    // could leak, if self.head != self.tail.
    #[inline(always)]
    pub fn done(self) -> Vec<T> {
        debug_assert!(self.head == self.tail);
        self.list
    }
    #[inline(always)]
    pub fn len(&self) -> usize { self.tail - self.head }
    #[inline(always)]
    pub fn is_empty(&self) -> bool { self.head == self.tail }
}

#[inline(always)]
unsafe fn push_unchecked<T>(vec: &mut Vec<T>, element: T) {
    debug_assert!(vec.len() < vec.capacity());
    let len = vec.len();
    ::std::ptr::write(vec.get_unchecked_mut(len), element);
    vec.set_len(len + 1);
}

pub struct MergeSorter<D: Ord, T: Ord, R: Diff> {
    queue: Vec<Vec<Vec<(D, T, R)>>>,    // each power-of-two length list of allocations.
    stash: Vec<Vec<(D, T, R)>>,
}

impl<D: Ord, T: Ord, R: Diff> MergeSorter<D, T, R> {

    #[inline]
    pub fn new() -> Self { MergeSorter { queue: Vec::new(), stash: Vec::new() } }

    #[inline]
    pub fn empty(&mut self) -> Vec<(D, T, R)> {
        self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024))
    }

    #[inline(never)]
    pub fn _sort(&mut self, list: &mut Vec<Vec<(D, T, R)>>) {
        for mut batch in list.drain(..) {
            self.push(&mut batch);
        }
        self.finish_into(list);
    }

    #[inline]
    pub fn push(&mut self, batch: &mut Vec<(D, T, R)>) {
        // TODO: Reason about possible unbounded stash growth. How to / should we return them?
        // TODO: Reason about mis-sized vectors, from deserialized data; should probably drop.
        let mut batch = if self.stash.len() > 2 {
            ::std::mem::replace(batch, self.stash.pop().unwrap())
        }
        else {
            ::std::mem::replace(batch, Vec::new())
        };

        if batch.len() > 0 {
            batch.sort_unstable_by(|x,y| (&x.0, &x.1).cmp(&(&y.0, &y.1)));
            for index in 1 .. batch.len() {
                if batch[index].0 == batch[index - 1].0 && batch[index].1 == batch[index - 1].1 {
                    batch[index].2 = batch[index].2 + batch[index - 1].2;
                    batch[index - 1].2 = R::zero();
                }
            }
            batch.retain(|x| !x.2.is_zero());

            self.queue.push(vec![batch]);
            while self.queue.len() > 1 && (self.queue[self.queue.len()-1].len() >= self.queue[self.queue.len()-2].len() / 2) {
                let list1 = self.queue.pop().unwrap();
                let list2 = self.queue.pop().unwrap();
                let merged = self.merge_by(list1, list2);
                self.queue.push(merged);
            }
        }
    }

    // This is awkward, because it isn't a power-of-two length any more, and we don't want
    // to break it down to be so.
    pub fn push_list(&mut self, list: Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 && self.queue[self.queue.len()-1].len() < list.len() {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }
        self.queue.push(list);
    }

    #[inline(never)]
    pub fn finish_into(&mut self, target: &mut Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }

        if let Some(mut last) = self.queue.pop() {
            ::std::mem::swap(&mut last, target);
        }
    }

    // merges two sorted input lists into one sorted output list.
    #[inline(never)]
    fn merge_by(&mut self, list1: Vec<Vec<(D, T, R)>>, list2: Vec<Vec<(D, T, R)>>) -> Vec<Vec<(D, T, R)>> {

        use std::cmp::Ordering;

        // TODO: `list1` and `list2` get dropped; would be better to reuse?
        let mut output = Vec::with_capacity(list1.len() + list2.len());
        let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));

        let mut list1 = VecQueue::from(list1);
        let mut list2 = VecQueue::from(list2);

        let mut head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
        let mut head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };

        // while we have valid data in each input, merge.
        while !head1.is_empty() && !head2.is_empty() {

            while (result.capacity() - result.len()) > 0 && head1.len() > 0 && head2.len() > 0 {

                let cmp = {
                    let x = head1.peek();
                    let y = head2.peek();
                    (&x.0, &x.1).cmp(&(&y.0, &y.1))
                };
                match cmp {
                    Ordering::Less    => { unsafe { push_unchecked(&mut result, head1.pop()); } }
                    Ordering::Greater => { unsafe { push_unchecked(&mut result, head2.pop()); } }
                    Ordering::Equal   => {
                        let (data1, time1, diff1) = head1.pop();
                        let (_data2, _time2, diff2) = head2.pop();
                        let diff = diff1 + diff2;
                        if !diff.is_zero() {
                            unsafe { push_unchecked(&mut result, (data1, time1, diff)); }
                        }
                    }
                }
            }

            if result.capacity() == result.len() {
                output.push(result);
                result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            }

            if head1.is_empty() {
                let done1 = head1.done();
                if done1.capacity() == 1024 { self.stash.push(done1); }
                head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
            }
            if head2.is_empty() {
                let done2 = head2.done();
                if done2.capacity() == 1024 { self.stash.push(done2); }
                head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };
            }
        }

        if result.len() > 0 { output.push(result); }
        else if result.capacity() > 0 { self.stash.push(result); }

        if !head1.is_empty() {
            let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            for _ in 0 .. head1.len() { result.push(head1.pop()); }
            output.push(result);
        }
        while !list1.is_empty() {
            output.push(list1.pop());
        }

        if !head2.is_empty() {
            let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            for _ in 0 .. head2.len() { result.push(head2.pop()); }
            output.push(result);
        }
        while !list2.is_empty() {
            output.push(list2.pop());
        }

        output
    }
}

/// Reports the number of elements satisfing the predicate.
///
/// This methods *relies strongly* on the assumption that the predicate
/// stays false once it becomes false, a joint property of the predicate
/// and the slice. This allows `advance` to use exponential search to
/// count the number of elements in time logarithmic in the result.
#[inline(always)]
pub fn _advance<T, F: Fn(&T)->bool>(slice: &[T], function: F) -> usize {

	// start with no advance
	let mut index = 0;
	if index < slice.len() && function(&slice[index]) {

		// advance in exponentially growing steps.
		let mut step = 1;
		while index + step < slice.len() && function(&slice[index + step]) {
			index += step;
			step = step << 1;
		}

		// advance in exponentially shrinking steps.
		step = step >> 1;
		while step > 0 {
			if index + step < slice.len() && function(&slice[index + step]) {
				index += step;
			}
			step = step >> 1;
		}

		index += 1;
	}

	index
}
<|endoftext|>


<commit_before>//! A runtime implementation that runs everything on the current thread.
//!
//! [`current_thread::Runtime`][rt] is similar to the primary
//! [`Runtime`][concurrent-rt] except that it runs all components on the current
//! thread instead of using a thread pool. This means that it is able to spawn
//! futures that do not implement `Send`.
//!
//! Same as the default [`Runtime`][concurrent-rt], the
//! [`current_thread::Runtime`][rt] includes:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//! * A [timer] for scheduling work to run after a set period of time.
//!
//! Note that [`current_thread::Runtime`][rt] does not implement `Send` itself
//! and cannot be safely moved to other threads.
//!
//! # Spawning from other threads
//!
//! While [`current_thread::Runtime`][rt] does not implement `Send` and cannot
//! safely be moved to other threads, it provides a `Handle` that can be sent
//! to other threads and allows to spawn new tasks from there.
//!
//! For example:
//!
//! ```
//! # extern crate tokio;
//! # extern crate futures;
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//! use std::thread;
//!
//! # fn main() {
//! let mut runtime = Runtime::new().unwrap();
//! let handle = runtime.handle();
//!
//! thread::spawn(move || {
//!     handle.spawn(future::ok(()));
//! }).join().unwrap();
//!
//! # /*
//! runtime.run().unwrap();
//! # */
//! # }
//! ```
//!
//! # Examples
//!
//! Creating a new `Runtime` and running a future `f` until its completion and
//! returning its result.
//!
//! ```
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//!
//! let mut runtime = Runtime::new().unwrap();
//!
//! // Use the runtime...
//! // runtime.block_on(f); // where f is a future
//! ```
//!
//! [rt]: struct.Runtime.html
//! [concurrent-rt]: ../struct.Runtime.html
//! [chan]: https://docs.rs/futures/0.1/futures/sync/mpsc/fn.channel.html
//! [reactor]: ../../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors
//! [timer]: ../../timer/index.html

mod builder;
mod runtime;

pub use self::builder::Builder;
pub use self::runtime::{Runtime, Handle};
pub use tokio_current_thread::spawn;

use futures::Future;

/// Run the provided future to completion using a runtime running on the current thread.
///
/// This first creates a new [`Runtime`], and calls [`Runtime::block_on`] with the provided future,
/// which blocks the current thread until the provided future completes. It then calls
/// [`Runtime::run`] to wait for any other spawned futures to resolve.
pub fn block_on_all<F>(future: F) -> Result<F::Item, F::Error>
where
    F: Future,
{
    let mut r = Runtime::new().expect("failed to start runtime on current thread");
    let v = r.block_on(future)?;
    r.run().expect("failed to resolve remaining futures");
    Ok(v)
}
<commit_msg>Reexport TaskExecutor from tokio_current_thread (#652)<commit_after>//! A runtime implementation that runs everything on the current thread.
//!
//! [`current_thread::Runtime`][rt] is similar to the primary
//! [`Runtime`][concurrent-rt] except that it runs all components on the current
//! thread instead of using a thread pool. This means that it is able to spawn
//! futures that do not implement `Send`.
//!
//! Same as the default [`Runtime`][concurrent-rt], the
//! [`current_thread::Runtime`][rt] includes:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//! * A [timer] for scheduling work to run after a set period of time.
//!
//! Note that [`current_thread::Runtime`][rt] does not implement `Send` itself
//! and cannot be safely moved to other threads.
//!
//! # Spawning from other threads
//!
//! While [`current_thread::Runtime`][rt] does not implement `Send` and cannot
//! safely be moved to other threads, it provides a `Handle` that can be sent
//! to other threads and allows to spawn new tasks from there.
//!
//! For example:
//!
//! ```
//! # extern crate tokio;
//! # extern crate futures;
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//! use std::thread;
//!
//! # fn main() {
//! let mut runtime = Runtime::new().unwrap();
//! let handle = runtime.handle();
//!
//! thread::spawn(move || {
//!     handle.spawn(future::ok(()));
//! }).join().unwrap();
//!
//! # /*
//! runtime.run().unwrap();
//! # */
//! # }
//! ```
//!
//! # Examples
//!
//! Creating a new `Runtime` and running a future `f` until its completion and
//! returning its result.
//!
//! ```
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//!
//! let mut runtime = Runtime::new().unwrap();
//!
//! // Use the runtime...
//! // runtime.block_on(f); // where f is a future
//! ```
//!
//! [rt]: struct.Runtime.html
//! [concurrent-rt]: ../struct.Runtime.html
//! [chan]: https://docs.rs/futures/0.1/futures/sync/mpsc/fn.channel.html
//! [reactor]: ../../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors
//! [timer]: ../../timer/index.html

mod builder;
mod runtime;

pub use self::builder::Builder;
pub use self::runtime::{Runtime, Handle};
pub use tokio_current_thread::spawn;
pub use tokio_current_thread::TaskExecutor;

use futures::Future;

/// Run the provided future to completion using a runtime running on the current thread.
///
/// This first creates a new [`Runtime`], and calls [`Runtime::block_on`] with the provided future,
/// which blocks the current thread until the provided future completes. It then calls
/// [`Runtime::run`] to wait for any other spawned futures to resolve.
pub fn block_on_all<F>(future: F) -> Result<F::Item, F::Error>
where
    F: Future,
{
    let mut r = Runtime::new().expect("failed to start runtime on current thread");
    let v = r.block_on(future)?;
    r.run().expect("failed to resolve remaining futures");
    Ok(v)
}
<|endoftext|>


<commit_before>// Microbenchmark for the smallintmap library

use std;
import std::smallintmap;
import std::smallintmap::{smallintmap, map};
import io::writer_util;

fn append_sequential(min: uint, max: uint, map: smallintmap<uint>) {
    uint::range(min, max) { |i|
        map.insert(i, i + 22u);
    }
}

fn check_sequential(min: uint, max: uint, map: smallintmap<uint>) {
    uint::range(min, max) { |i|
        assert map.get(i) == i + 22u;
    }
}

fn main(args: [str]) {
    let args = if vec::len(args) <= 1u {["", "1000000", "100"]} else {args};
    let max = uint::from_str(args[1]).get();
    let rep = uint::from_str(args[2]).get();

    let mut checkf = 0.0;
    let mut appendf = 0.0;

    uint::range(0u, rep) {|_r|
        let map = smallintmap::mk();
        let start = std::time::precise_time_s();
        append_sequential(0u, max, map);
        let mid = std::time::precise_time_s();
        check_sequential(0u, max, map);
        let end = std::time::precise_time_s();

        checkf += (end - mid) as float;
        appendf += (mid - start) as float;
    }

    let maxf = max as float;

    io::stdout().write_str(#fmt("insert(): %? seconds\n", checkf));
    io::stdout().write_str(#fmt("        : %f op/sec\n", maxf/checkf));
    io::stdout().write_str(#fmt("get()   : %? seconds\n", appendf));
    io::stdout().write_str(#fmt("        : %f op/sec\n", maxf/appendf));
}<commit_msg>bench: Reduce constants in std-smallintmap to make it valgrind fast<commit_after>// Microbenchmark for the smallintmap library

use std;
import std::smallintmap;
import std::smallintmap::{smallintmap, map};
import io::writer_util;

fn append_sequential(min: uint, max: uint, map: smallintmap<uint>) {
    uint::range(min, max) { |i|
        map.insert(i, i + 22u);
    }
}

fn check_sequential(min: uint, max: uint, map: smallintmap<uint>) {
    uint::range(min, max) { |i|
        assert map.get(i) == i + 22u;
    }
}

fn main(args: [str]) {
    let args = if vec::len(args) <= 1u {["", "10000", "50"]} else {args};
    let max = uint::from_str(args[1]).get();
    let rep = uint::from_str(args[2]).get();

    let mut checkf = 0.0;
    let mut appendf = 0.0;

    uint::range(0u, rep) {|_r|
        let map = smallintmap::mk();
        let start = std::time::precise_time_s();
        append_sequential(0u, max, map);
        let mid = std::time::precise_time_s();
        check_sequential(0u, max, map);
        let end = std::time::precise_time_s();

        checkf += (end - mid) as float;
        appendf += (mid - start) as float;
    }

    let maxf = max as float;

    io::stdout().write_str(#fmt("insert(): %? seconds\n", checkf));
    io::stdout().write_str(#fmt("        : %f op/sec\n", maxf/checkf));
    io::stdout().write_str(#fmt("get()   : %? seconds\n", appendf));
    io::stdout().write_str(#fmt("        : %f op/sec\n", maxf/appendf));
}<|endoftext|>


<commit_before>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt};
use iml_rabbit::{
    basic_consume, connect_to_queue, purge_queue, BasicConsumeOptions, Channel, ImlRabbitError,
};
use iml_wire_types::{Fqdn, PluginMessage};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum ImlServiceQueueError {
    #[error(transparent)]
    ImlRabbitError(#[from] ImlRabbitError),
    #[error(transparent)]
    SerdeJsonError(#[from] serde_json::error::Error),
}

/// Creates a consumer for an iml-service.
/// This fn will first purge the queue
/// and then consume from it.
///
/// This is expected to be called once during startup.
pub async fn consume_service_queue<'a>(
    ch: &Channel,
    name: &'a str,
) -> Result<
    impl Stream<Item = Result<PluginMessage, ImlServiceQueueError>> + 'a,
    ImlServiceQueueError,
> {
    let name2 = name.to_string();

    let q = connect_to_queue(name.to_string(), ch).await?;

    purge_queue(ch, name2).await?;

    let s = basic_consume(
        ch,
        q,
        name,
        Some(BasicConsumeOptions {
            no_ack: true,
            ..BasicConsumeOptions::default()
        }),
    )
    .await?
    .map_err(ImlServiceQueueError::from)
    .map_ok(|(_, x)| x)
    .and_then(|m| {
        tracing::debug!("Incoming message: {}", String::from_utf8_lossy(&m.data));

        future::ready(serde_json::from_slice(&m.data).map_err(ImlServiceQueueError::from))
    });

    Ok(s)
}

/// Given an incoming message Return an `Option` of fqdn and body
pub fn data_only(message: PluginMessage) -> Option<(Fqdn, serde_json::Value)> {
    match message {
        PluginMessage::Data { body, fqdn, .. } => Some((fqdn, body)),
        _ => None,
    }
}

pub fn into_deserialized<T: serde::de::DeserializeOwned>(
    (fqdn, body): (Fqdn, serde_json::Value),
) -> Result<(Fqdn, T), ImlServiceQueueError> {
    let v = serde_json::from_value(body)?;

    Ok((fqdn, v))
}

pub fn consume_data<'a, T: serde::de::DeserializeOwned + Send + 'a>(
    ch: &'a Channel,
    queue_name: &'a str,
) -> impl Stream<Item = Result<(Fqdn, T), ImlServiceQueueError>> + 'a {
    consume_service_queue(ch, queue_name)
        .try_flatten_stream()
        .try_filter_map(|x| future::ok(data_only(x)))
        .and_then(|x| future::ready(into_deserialized(x)))
        .boxed()
}
<commit_msg>Remove queue purge during startup (#2080)<commit_after>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt};
use iml_rabbit::{basic_consume, connect_to_queue, BasicConsumeOptions, Channel, ImlRabbitError};
use iml_wire_types::{Fqdn, PluginMessage};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum ImlServiceQueueError {
    #[error(transparent)]
    ImlRabbitError(#[from] ImlRabbitError),
    #[error(transparent)]
    SerdeJsonError(#[from] serde_json::error::Error),
}

/// Creates a consumer for an iml-service.
///
/// This is expected to be called once during startup.
pub async fn consume_service_queue<'a>(
    ch: &Channel,
    name: &'a str,
) -> Result<
    impl Stream<Item = Result<PluginMessage, ImlServiceQueueError>> + 'a,
    ImlServiceQueueError,
> {
    let q = connect_to_queue(name.to_string(), ch).await?;

    let s = basic_consume(
        ch,
        q,
        name,
        Some(BasicConsumeOptions {
            no_ack: true,
            ..BasicConsumeOptions::default()
        }),
    )
    .await?
    .map_err(ImlServiceQueueError::from)
    .map_ok(|(_, x)| x)
    .and_then(|m| {
        tracing::debug!("Incoming message: {}", String::from_utf8_lossy(&m.data));

        future::ready(serde_json::from_slice(&m.data).map_err(ImlServiceQueueError::from))
    });

    Ok(s)
}

/// Given an incoming message Return an `Option` of fqdn and body
pub fn data_only(message: PluginMessage) -> Option<(Fqdn, serde_json::Value)> {
    match message {
        PluginMessage::Data { body, fqdn, .. } => Some((fqdn, body)),
        _ => None,
    }
}

pub fn into_deserialized<T: serde::de::DeserializeOwned>(
    (fqdn, body): (Fqdn, serde_json::Value),
) -> Result<(Fqdn, T), ImlServiceQueueError> {
    let v = serde_json::from_value(body)?;

    Ok((fqdn, v))
}

pub fn consume_data<'a, T: serde::de::DeserializeOwned + Send + 'a>(
    ch: &'a Channel,
    queue_name: &'a str,
) -> impl Stream<Item = Result<(Fqdn, T), ImlServiceQueueError>> + 'a {
    consume_service_queue(ch, queue_name)
        .try_flatten_stream()
        .try_filter_map(|x| future::ok(data_only(x)))
        .and_then(|x| future::ready(into_deserialized(x)))
        .boxed()
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate input;
extern crate shader_version;

use shader_version::OpenGL;
use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const ();

/// Size in pixels.
#[derive(Debug, Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

impl From<[u32; 2]> for Size {
    #[inline(always)]
    fn from(value: [u32; 2]) -> Size {
        Size { width: value[0], height: value[1] }
    }
}

impl From<(u32, u32)> for Size {
    #[inline(always)]
    fn from(value: (u32, u32)) -> Size {
        Size { width: value.0, height: value.1 }
    }
}

/// Builds window from window settings.
pub trait BuildFromWindowSettings: Sized {
    /// Builds window from window settings.
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String>;
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Tells the window to close or stay open.
    fn set_should_close(&mut self, value: bool);

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
    /// If true, enable vsync.
    vsync: bool,
    /// An optional OpenGL version.
    opengl: Option<OpenGL>,
    /// Whether sRGB is enabled.
    srgb: bool,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    ///
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    /// - vsync: false
    /// - srgb: true
    pub fn new<T: Into<String>, S: Into<Size>>(
        title: T, size: S) -> WindowSettings
    {
        WindowSettings {
            title: title.into(),
            size: size.into(),
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
            vsync: false,
            opengl: None,
            srgb: true,
        }
    }

    /// Builds window.
    pub fn build<W: BuildFromWindowSettings>(self) -> Result<W, String> {
        BuildFromWindowSettings::build_from_window_settings(self)
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    ///
    /// See https://en.wikipedia.org/wiki/Multisample_anti-aliasing
    /// for more information.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }

    /// Gets vsync.
    ///
    /// See https://en.wikipedia.org/wiki/Screen_tearing for more information.
    pub fn get_vsync(&self) -> bool { self.vsync }

    /// Sets vsync.
    pub fn vsync(mut self, value: bool) -> Self {
        self.vsync = value;
        self
    }

    /// Gets opengl.
    pub fn get_maybe_opengl(&self) -> Option<OpenGL> { self.opengl }

    /// Sets opengl.
    pub fn maybe_opengl(mut self, value: Option<OpenGL>) -> Self {
        self.opengl = value;
        self
    }

    /// Sets opengl.
    pub fn opengl(mut self, value: OpenGL) -> Self {
        self.opengl = Some(value);
        self
    }

    /// Gets sRGB.
    pub fn get_srgb(&self) -> bool { self.srgb }

    /// Sets sRGB.
    ///
    /// See https://en.wikipedia.org/wiki/SRGB for more information.
    pub fn srgb(mut self, value: bool) -> Self {
        self.srgb = value;
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
    size: Size
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        NoWindow {
            should_close: false,
            title: settings.title,
            size: settings.size,
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn size(&self) -> Size { self.size }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl BuildFromWindowSettings for NoWindow {
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String> {
        Ok(NoWindow::new(settings))
    }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<commit_msg>Derive `Clone` on `BuildFromWindowSettings`<commit_after>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate input;
extern crate shader_version;

use shader_version::OpenGL;
use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const ();

/// Size in pixels.
#[derive(Debug, Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

impl From<[u32; 2]> for Size {
    #[inline(always)]
    fn from(value: [u32; 2]) -> Size {
        Size { width: value[0], height: value[1] }
    }
}

impl From<(u32, u32)> for Size {
    #[inline(always)]
    fn from(value: (u32, u32)) -> Size {
        Size { width: value.0, height: value.1 }
    }
}

/// Builds window from window settings.
pub trait BuildFromWindowSettings: Sized {
    /// Builds window from window settings.
    fn build_from_window_settings(settings: &WindowSettings)
    -> Result<Self, String>;
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Tells the window to close or stay open.
    fn set_should_close(&mut self, value: bool);

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
#[derive(Clone)]
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
    /// If true, enable vsync.
    vsync: bool,
    /// An optional OpenGL version.
    opengl: Option<OpenGL>,
    /// Whether sRGB is enabled.
    srgb: bool,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    ///
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    /// - vsync: false
    /// - srgb: true
    pub fn new<T: Into<String>, S: Into<Size>>(
        title: T, size: S) -> WindowSettings
    {
        WindowSettings {
            title: title.into(),
            size: size.into(),
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
            vsync: false,
            opengl: None,
            srgb: true,
        }
    }

    /// Builds window.
    pub fn build<W: BuildFromWindowSettings>(&self) -> Result<W, String> {
        BuildFromWindowSettings::build_from_window_settings(self)
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    ///
    /// See https://en.wikipedia.org/wiki/Multisample_anti-aliasing
    /// for more information.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }

    /// Gets vsync.
    ///
    /// See https://en.wikipedia.org/wiki/Screen_tearing for more information.
    pub fn get_vsync(&self) -> bool { self.vsync }

    /// Sets vsync.
    pub fn vsync(mut self, value: bool) -> Self {
        self.vsync = value;
        self
    }

    /// Gets opengl.
    pub fn get_maybe_opengl(&self) -> Option<OpenGL> { self.opengl }

    /// Sets opengl.
    pub fn maybe_opengl(mut self, value: Option<OpenGL>) -> Self {
        self.opengl = value;
        self
    }

    /// Sets opengl.
    pub fn opengl(mut self, value: OpenGL) -> Self {
        self.opengl = Some(value);
        self
    }

    /// Gets sRGB.
    pub fn get_srgb(&self) -> bool { self.srgb }

    /// Sets sRGB.
    ///
    /// See https://en.wikipedia.org/wiki/SRGB for more information.
    pub fn srgb(mut self, value: bool) -> Self {
        self.srgb = value;
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
    size: Size
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: &WindowSettings) -> NoWindow {
        NoWindow {
            should_close: false,
            title: settings.get_title(),
            size: settings.get_size(),
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn size(&self) -> Size { self.size }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl BuildFromWindowSettings for NoWindow {
    fn build_from_window_settings(settings: &WindowSettings)
    -> Result<Self, String> {
        Ok(NoWindow::new(settings))
    }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<|endoftext|>


<commit_before>//! `Source` data description.
use crate::data::RoomName;

with_base_fields_and_update_struct! {
    /// A source object, which creeps can gain energy by mining from.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct Source {
        /// The source's current energy - available to be mined be creeps.
        pub energy: u32,
        /// The source's maximum energy - what `energy` resets to on regeneration.
        pub energy_capacity: u32,
        /// The amount of energy either harvested on this source specifically or for the room since
        /// the last invasion (not sure which it is).
        pub invader_harvested: u32,
        /// The game time at which the source will next regenerate. `None` when waiting on a creep to
        /// first harvest it.
        pub next_regeneration_time: Option<u64>,
        /// The number of ticks between when a source is first harvested after regeneration and when it next
        /// regenerates.
        pub ticks_to_regeneration: u32,
    }

    /// The update structure for a source object.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct SourceUpdate { ... }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;
    use serde_json;

    use crate::data::RoomName;

    use super::Source;

    #[test]
    fn parse_source_and_update() {
        let json = json!({
            "_id": "57ef9dba86f108ae6e60e2fc",
            "energy": 260,
            "energyCapacity": 3000,
            "invaderHarvested": 29240,
            "nextRegenerationTime": 19894026,
            "room": "E4S61",
            "ticksToRegeneration": 300,
            "type": "source",
            "x": 26,
            "y": 9,
        });

        let mut obj = Source::deserialize(&json).unwrap();

        assert_eq!(
            obj,
            Source {
                id: "57ef9dba86f108ae6e60e2fc".to_owned(),
                room: RoomName::new("E4S61").unwrap(),
                x: 26,
                y: 9,
                energy: 260,
                energy_capacity: 3000,
                invader_harvested: 29240,
                next_regeneration_time: Some(19894026),
                ticks_to_regeneration: 300,
            }
        );

        obj.update(
            serde_json::from_value(json!({
                "x": 40,
                "y": 50,
                "energy": 0,
            }))
            .unwrap(),
        );

        assert_eq!(
            obj,
            Source {
                id: "57ef9dba86f108ae6e60e2fc".to_owned(),
                room: RoomName::new("E4S61").unwrap(),
                x: 40,
                y: 50,
                energy: 0,
                energy_capacity: 3000,
                invader_harvested: 29240,
                next_regeneration_time: Some(19894026),
                ticks_to_regeneration: 300,
            }
        );
    }
}
<commit_msg>Handle null invader_harvested in Source<commit_after>//! `Source` data description.
use crate::data::RoomName;

with_base_fields_and_update_struct! {
    /// A source object, which creeps can gain energy by mining from.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct Source {
        /// The source's current energy - available to be mined be creeps.
        pub energy: u32,
        /// The source's maximum energy - what `energy` resets to on regeneration.
        pub energy_capacity: u32,
        /// The amount of energy either harvested on this source specifically or for the room since
        /// the last invasion (not sure which it is).
        #[serde(default)]
        pub invader_harvested: u32,
        /// The game time at which the source will next regenerate. `None` when waiting on a creep to
        /// first harvest it.
        pub next_regeneration_time: Option<u64>,
        /// The number of ticks between when a source is first harvested after regeneration and when it next
        /// regenerates.
        pub ticks_to_regeneration: u32,
    }

    /// The update structure for a source object.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct SourceUpdate {
        - energy: u32,
        - energy_capacity: u32,
        - invader_harvested: u32,
        - next_regeneration_time: Option<u64>,
        - ticks_to_regeneration: u32,
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;
    use serde_json;

    use crate::data::RoomName;

    use super::Source;

    #[test]
    fn parse_source_and_update() {
        let json = json!({
            "_id": "57ef9dba86f108ae6e60e2fc",
            "energy": 260,
            "energyCapacity": 3000,
            "invaderHarvested": 29240,
            "nextRegenerationTime": 19894026,
            "room": "E4S61",
            "ticksToRegeneration": 300,
            "type": "source",
            "x": 26,
            "y": 9,
        });

        let mut obj = Source::deserialize(&json).unwrap();

        assert_eq!(
            obj,
            Source {
                id: "57ef9dba86f108ae6e60e2fc".to_owned(),
                room: RoomName::new("E4S61").unwrap(),
                x: 26,
                y: 9,
                energy: 260,
                energy_capacity: 3000,
                invader_harvested: 29240,
                next_regeneration_time: Some(19894026),
                ticks_to_regeneration: 300,
            }
        );

        obj.update(
            serde_json::from_value(json!({
                "x": 40,
                "y": 50,
                "energy": 0,
            }))
            .unwrap(),
        );

        assert_eq!(
            obj,
            Source {
                id: "57ef9dba86f108ae6e60e2fc".to_owned(),
                room: RoomName::new("E4S61").unwrap(),
                x: 40,
                y: 50,
                energy: 0,
                energy_capacity: 3000,
                invader_harvested: 29240,
                next_regeneration_time: Some(19894026),
                ticks_to_regeneration: 300,
            }
        );
    }

    fn handle_no_invader_harvested() {
        let json = json!({
            "_id": "5bbcad499099fc012e6370ab",
            "energy": 4000,
            "energyCapacity": 4000,
            "nextRegenerationTime": null,
            "room": "E6S26",
            "ticksToRegeneration": 300,
            "type": "source",
            "x": 40,
            "y": 34,
        });

        let mut obj = Source::deserialize(&json).unwrap();

        assert_eq!(
            obj,
            Source {
                id: "5bbcad499099fc012e6370ab".to_owned(),
                room: RoomName::new("E6S26").unwrap(),
                x: 40,
                y: 34,
                energy: 4000,
                energy_capacity: 4000,
                invader_harvested: 0,
                next_regeneration_time: None,
                ticks_to_regeneration: 300,
            }
        );
    }
}
<|endoftext|>


<commit_before>/*
gl/src/gl_wrapper/buffer.rs, 2017-07-18

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

use super::gl_raw;
use self::gl_raw::types::*;

use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr;

/// Send static data to GPU with Vertex Buffer Object
struct VertexBufferStatic {
    id: GLuint,
    attribute_component_count: GLint,
}

impl VertexBufferStatic {
    /// Sends static data to GPU.
    ///
    /// # Arguments
    /// * `data` - Float data which is sent to GPU.
    /// * `attribute_component_count` - Number of floats in one vertex attribute.
    ///
    /// # Safety
    /// This function does not check if data length and `attribute_component_count` match.
    unsafe fn new(data: &[f32], attribute_component_count: GLint) -> VertexBufferStatic {
        let mut id: GLuint = 0;

        gl_raw::GenBuffers(1, &mut id);
        gl_raw::BindBuffer(gl_raw::ARRAY_BUFFER, id);

        let size: GLsizeiptr = (size_of::<f32>() * data.len()) as GLsizeiptr;
        let data_ptr = data.as_ptr() as *const c_void;

        gl_raw::BufferData(gl_raw::ARRAY_BUFFER, size, data_ptr, gl_raw::STATIC_DRAW);

        VertexBufferStatic {id, attribute_component_count}
    }

    /// Set vertex attribute to match buffer data.
    ///
    /// # Arguments
    /// * `attribute_index` - Index of vertex attribute.
    fn set_vertex_attributes(&mut self, attribute_index: GLuint) {
        unsafe {
            gl_raw::BindBuffer(gl_raw::ARRAY_BUFFER, self.id);

            let stride = (self.attribute_component_count * size_of::<f32>() as GLint) as GLsizei;
            gl_raw::VertexAttribPointer(attribute_index, self.attribute_component_count, gl_raw::FLOAT, gl_raw::FALSE, stride, ptr::null());
            gl_raw::EnableVertexAttribArray(attribute_index);
        }
    }
}

impl Drop for VertexBufferStatic {

    /// Deletes OpenGL's buffer object.
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteBuffers(1, &self.id);
        }
    }
}

/// Send multiple buffers of data to GPU
#[cfg(not(feature = "gles"))]
pub struct VertexArray {
    id: GLuint,
    vertex_buffers: Vec<VertexBufferStatic>,
    vertex_count: GLsizei,
}

#[cfg(not(feature = "gles"))]
impl VertexArray {

    /// Creates new Vertex Array Object
    pub fn new(vertex_count: GLsizei) -> VertexArray {
        let mut id: GLuint = 0;
        let vertex_buffers = vec![];

        unsafe {
            gl_raw::GenVertexArrays(1, &mut id);
            VertexArray {id, vertex_buffers, vertex_count}
        }
    }

    /// Adds new buffer to Vertex Array Object
    ///
    /// # Arguments
    /// * `data` - Float data to send to the GPU.
    /// * `attribute_component_count` -
    /// * `attribute_index` -
    ///
    /// # Panics
    pub fn add_static_buffer(&mut self, data: &[f32], attribute_component_count: GLint, attribute_index: GLuint) {
        if data.len() / attribute_component_count as usize != self.vertex_count as usize {
            panic!("buffer size doesn't match with vertex array's vertex count");
        }

        if data.len() % attribute_component_count as usize != 0 {
            panic!("count of elements in data does not match vector size");
        }

        let mut buffer;

        unsafe {
            buffer = VertexBufferStatic::new(data, attribute_component_count);
        }

        self.bind();

        buffer.set_vertex_attributes(attribute_index);
        self.vertex_buffers.push(buffer);
    }

    fn bind(&self) {
        unsafe {
            gl_raw::BindVertexArray(self.id);
        }
    }

    pub fn draw(&mut self) {
        self.bind();

        unsafe {
            gl_raw::DrawArrays(gl_raw::TRIANGLES, 0, self.vertex_count);
        }
    }
}

#[cfg(not(feature = "gles"))]
impl Drop for VertexArray {
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteBuffers(1, &self.id);
        }
    }
}

#[cfg(feature = "gles")]
pub struct VertexArray {
    vertex_buffers: Vec<(VertexBufferStatic, GLuint)>,
    vertex_count: GLsizei,
}

#[cfg(feature = "gles")]
impl VertexArray {
    pub fn new(vertex_count: GLsizei) -> VertexArray {
        let vertex_buffers = vec![];

        unsafe {
            VertexArray {vertex_buffers, vertex_count}
        }
    }

    pub fn add_static_buffer(&mut self, data: &[f32], vector_size: GLint, attribute_index: GLuint) {
        if data.len() / vector_size as usize != self.vertex_count as usize {
            panic!("buffer size doesn't match with vertex array's vertex count");
        }

        if data.len() % vector_size as usize != 0 {
            panic!("count of elements in data does not match vector size");
        }

        let mut buffer;

        unsafe {
            buffer = VertexBufferStatic::new(data, vector_size);
        }

        self.vertex_buffers.push((buffer, attribute_index));
    }

    pub fn draw(&mut self) {
        for &mut (ref mut buffer, attribute_index) in &mut self.vertex_buffers {
            buffer.set_vertex_attributes(attribute_index);
        }

        unsafe {
            gl_raw::DrawArrays(gl_raw::TRIANGLES, 0, self.vertex_count);
        }
    }
}<commit_msg>documentation changes and code updates<commit_after>/*
gl/src/gl_wrapper/buffer.rs, 2017-07-19

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

use super::gl_raw;
use self::gl_raw::types::*;

use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr;

/// Send static data to GPU with Vertex Buffer Object
struct VertexBufferStatic {
    id: GLuint,
    attribute_component_count: GLint,
}

impl VertexBufferStatic {
    /// Sends static data to GPU.
    ///
    /// # Arguments
    /// * `data` - Float data which is sent to GPU.
    /// * `attribute_component_count` - Number of floats in one vertex attribute.
    ///
    /// # Safety
    /// This function does not check if data length and `attribute_component_count` match.
    unsafe fn new(data: &[f32], attribute_component_count: GLint) -> VertexBufferStatic {
        let mut id: GLuint = 0;

        gl_raw::GenBuffers(1, &mut id);
        gl_raw::BindBuffer(gl_raw::ARRAY_BUFFER, id);

        let size: GLsizeiptr = (size_of::<f32>() * data.len()) as GLsizeiptr;
        let data_ptr = data.as_ptr() as *const c_void;

        gl_raw::BufferData(gl_raw::ARRAY_BUFFER, size, data_ptr, gl_raw::STATIC_DRAW);

        VertexBufferStatic {id, attribute_component_count}
    }

    /// Set vertex attribute to match buffer data.
    ///
    /// # Arguments
    /// * `attribute_index` - Index of vertex attribute.
    fn set_vertex_attributes(&mut self, attribute_index: GLuint) {
        unsafe {
            gl_raw::BindBuffer(gl_raw::ARRAY_BUFFER, self.id);

            let stride = (self.attribute_component_count * size_of::<f32>() as GLint) as GLsizei;
            gl_raw::VertexAttribPointer(attribute_index, self.attribute_component_count, gl_raw::FLOAT, gl_raw::FALSE, stride, ptr::null());
            gl_raw::EnableVertexAttribArray(attribute_index);
        }
    }
}

impl Drop for VertexBufferStatic {

    /// Deletes OpenGL's buffer object.
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteBuffers(1, &self.id);
        }
    }
}

/// Send multiple buffers of data to GPU.
///
/// OpenGL 3.3 version of this struct is implemented
/// with OpenGL's Vertex Array Object.
///
/// OpenGL ES 2.0 does not support Vertex Array Objects, so vertex
/// attributes are set for every buffer
/// when `draw` method is called if using OpenGL ES version of this struct.
#[cfg(not(feature = "gles"))]
pub struct VertexArray {
    id: GLuint,
    vertex_buffers: Vec<VertexBufferStatic>,
    vertex_count: GLsizei,
}

#[cfg(feature = "gles")]
pub struct VertexArray {
    vertex_buffers: Vec<(VertexBufferStatic, GLuint)>,
    vertex_count: GLsizei,
}

impl VertexArray {

    /// Creates new Vertex Array Object
    #[cfg(not(feature = "gles"))]
    pub fn new(vertex_count: GLsizei) -> VertexArray {
        let mut id: GLuint = 0;
        let vertex_buffers = vec![];

        unsafe {
            gl_raw::GenVertexArrays(1, &mut id);
            VertexArray {id, vertex_buffers, vertex_count}
        }
    }

    #[cfg(feature = "gles")]
    pub fn new(vertex_count: GLsizei) -> VertexArray {
        let vertex_buffers = vec![];
        VertexArray {vertex_buffers, vertex_count}
    }

    /// Adds new buffer to Vertex Array Object
    ///
    /// # Arguments
    /// * `data` - Float data to send to the GPU.
    /// * `attribute_component_count` - Number of floats in one attribute.
    /// * `attribute_index` - Index of vertex attribute.
    ///
    /// # Panics
    /// * If buffer length doesn't match with `VertexArray`'s vertex count.
    /// * If buffer length doesn't match with attribute_component_count.
    pub fn add_static_buffer(&mut self, data: &[f32], attribute_component_count: GLint, attribute_index: GLuint) {
        if data.len() / attribute_component_count as usize != self.vertex_count as usize {
            panic!("buffer length doesn't match with VertexArray's vertex count");
        }

        if data.len() % attribute_component_count as usize != 0 {
            panic!("buffer length doesn't match with attribute_component_count");
        }

        #[cfg(not(feature = "gles"))]
        {
            let mut buffer;

            unsafe {
                buffer = VertexBufferStatic::new(data, attribute_component_count);
            }

            self.bind();
            buffer.set_vertex_attributes(attribute_index);
            self.vertex_buffers.push(buffer);
        }

        #[cfg(feature = "gles")]
        {
            let buffer;

            unsafe {
                buffer = VertexBufferStatic::new(data, attribute_component_count);
            }

            self.vertex_buffers.push((buffer, attribute_index));
        }
    }

    /// Bind OpenGL's Vertex Array Object. This method
    /// only exists for OpenGL 3.3 version of `VertexArray` struct.
    #[cfg(not(feature = "gles"))]
    fn bind(&self) {
        unsafe {
            gl_raw::BindVertexArray(self.id);
        }
    }

    /// Draw with buffers currently existing buffers in `VertexArray`. Remember to enable
    /// correct shader `Program` with it's `use_program` method before calling this method.
    pub fn draw(&mut self) {
        #[cfg(not(feature = "gles"))]
        {
            self.bind();
        }

        #[cfg(feature = "gles")]
        {
            for &mut (ref mut buffer, attribute_index) in &mut self.vertex_buffers {
                buffer.set_vertex_attributes(attribute_index);
            }
        }

        unsafe {
            gl_raw::DrawArrays(gl_raw::TRIANGLES, 0, self.vertex_count);
        }
    }
}

#[cfg(not(feature = "gles"))]
impl Drop for VertexArray {
    /// Delete OpenGL's Vertex Array Object. This implementation of Drop trait
    /// only exists for OpenGL 3.3 version of `VertexArray` struct.
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteVertexArrays(1, &self.id);
        }
    }
}<|endoftext|>


<commit_before>//! This module provides casting iterators for certain types of accessors.

/// Casting iterator and accompanying types for `Colors`.
pub mod colors;
/// Casting iterator and accompanying types for `Indices`.
pub mod indices;
/// Casting iterator and accompanying types for `Joints`.
pub mod joints;
/// Casting iterator and accompanying types for `TexCoords`.
pub mod tex_coords;
/// Casting iterator and accompanying types for `Weights`.
pub mod weights;
/// Casting iterator and accompanying types for `MorphWeights`.
pub mod morph_weights;
/// Casting iterator and accompanying types for `Rotations`.
pub mod rotations;

#[inline(always)]
fn norm_i8_as_f32(x: i8) -> f32 {
    (x as f32 * (1.0 / i8::max_value() as f32)).max(-1.0)
}

#[inline(always)]
fn norm_u8_as_u16(x: u8) -> u16 {
    x as u16 * 0x100
}

#[inline(always)]
fn norm_u8_as_f32(x: u8) -> f32 {
    x as f32 * (1.0 / u8::max_value() as f32)
}

#[inline(always)]
fn norm_i16_as_f32(x: i16) -> f32 {
    (x as f32 * (1.0 / i16::max_value() as f32)).max(-1.0)
}

#[inline(always)]
fn norm_u16_as_u8(x: u16) -> u8 {
    (x / 0x100) as u8
}

#[inline(always)]
fn norm_u16_as_f32(x: u16) -> f32 {
    x as f32 * (1.0 / u16::max_value() as f32)
}

#[inline(always)]
fn norm_f32_as_u8(x: f32) -> u8 {
    (x * u8::max_value() as f32) as u8
}

#[inline(always)]
fn norm_f32_as_u16(x: f32) -> u16 {
    (x * u16::max_value() as f32) as u16
}
<commit_msg>#[inline] in place of #[inline(always)]<commit_after>//! This module provides casting iterators for certain types of accessors.

/// Casting iterator and accompanying types for `Colors`.
pub mod colors;
/// Casting iterator and accompanying types for `Indices`.
pub mod indices;
/// Casting iterator and accompanying types for `Joints`.
pub mod joints;
/// Casting iterator and accompanying types for `TexCoords`.
pub mod tex_coords;
/// Casting iterator and accompanying types for `Weights`.
pub mod weights;
/// Casting iterator and accompanying types for `MorphWeights`.
pub mod morph_weights;
/// Casting iterator and accompanying types for `Rotations`.
pub mod rotations;

#[inline]
fn norm_i8_as_f32(x: i8) -> f32 {
    (x as f32 * (1.0 / i8::max_value() as f32)).max(-1.0)
}

#[inline]
fn norm_u8_as_u16(x: u8) -> u16 {
    x as u16 * 0x100
}

#[inline]
fn norm_u8_as_f32(x: u8) -> f32 {
    x as f32 * (1.0 / u8::max_value() as f32)
}

#[inline]
fn norm_i16_as_f32(x: i16) -> f32 {
    (x as f32 * (1.0 / i16::max_value() as f32)).max(-1.0)
}

#[inline]
fn norm_u16_as_u8(x: u16) -> u8 {
    (x / 0x100) as u8
}

#[inline]
fn norm_u16_as_f32(x: u16) -> f32 {
    x as f32 * (1.0 / u16::max_value() as f32)
}

#[inline]
fn norm_f32_as_u8(x: f32) -> u8 {
    (x * u8::max_value() as f32) as u8
}

#[inline]
fn norm_f32_as_u16(x: f32) -> u16 {
    (x * u16::max_value() as f32) as u16
}
<|endoftext|>


<commit_before>use crate::dep_graph;
use crate::hir::exports::Export;
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintLevelMap;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::AccessLevels;
use crate::middle::region;
use crate::middle::resolve_lifetime::{
    LifetimeScopeForPath, ObjectLifetimeDefault, Region, ResolveLifetimes,
};
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
use crate::mir::interpret::GlobalId;
use crate::mir::interpret::{ConstAlloc, LitToConstError, LitToConstInput};
use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
use crate::mir::mono::CodegenUnit;
use crate::thir;
use crate::traits::query::{
    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
};
use crate::traits::query::{
    DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult,
    OutlivesBound,
};
use crate::traits::specialization_graph;
use crate::traits::{self, ImplSource};
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
use rustc_session::utils::NativeLibKind;
use rustc_session::Limits;
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;

use rustc_ast as ast;
use rustc_attr as attr;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use std::collections::BTreeMap;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;

pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;

#[derive(Copy, Clone)]
pub struct TyCtxtAt<'tcx> {
    pub tcx: TyCtxt<'tcx>,
    pub span: Span,
}

impl Deref for TyCtxtAt<'tcx> {
    type Target = TyCtxt<'tcx>;
    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &self.tcx
    }
}

#[derive(Copy, Clone)]
pub struct TyCtxtEnsure<'tcx> {
    pub tcx: TyCtxt<'tcx>,
}

impl TyCtxt<'tcx> {
    /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
    /// are executed instead of just returning their results.
    #[inline(always)]
    pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
        TyCtxtEnsure { tcx: self }
    }

    /// Returns a transparent wrapper for `TyCtxt` which uses
    /// `span` as the location of queries performed through it.
    #[inline(always)]
    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
        TyCtxtAt { tcx: self, span }
    }

    pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
        self.queries.try_mark_green(self, dep_node)
    }
}

macro_rules! query_helper_param_ty {
    (DefId) => { impl IntoQueryParam<DefId> };
    ($K:ty) => { $K };
}

macro_rules! query_storage {
    ([][$K:ty, $V:ty]) => {
        <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
    };
    ([(storage $ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
        <$ty as CacheSelector<$K, $V>>::Cache
    };
    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
        query_storage!([$($modifiers)*][$($args)*])
    };
}

macro_rules! define_callbacks {
    (<$tcx:tt>
     $($(#[$attr:meta])*
        [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {

        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
        // below, but using type aliases instead of associated types, to bypass
        // the limitations around normalizing under HRTB - for example, this:
        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
        // This is primarily used by the `provide!` macro in `rustc_metadata`.
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_keys {
            use super::*;

            $(pub type $name<$tcx> = $($K)*;)*
        }
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_values {
            use super::*;

            $(pub type $name<$tcx> = $V;)*
        }
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_storage {
            use super::*;

            $(pub type $name<$tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
        }
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_stored {
            use super::*;

            $(pub type $name<$tcx> = <query_storage::$name<$tcx> as QueryStorage>::Stored;)*
        }

        #[derive(Default)]
        pub struct QueryCaches<$tcx> {
            $($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
        }

        impl TyCtxtEnsure<$tcx> {
            $($(#[$attr])*
            #[inline(always)]
            pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
                let key = key.into_query_param();
                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {});

                let lookup = match cached {
                    Ok(()) => return,
                    Err(lookup) => lookup,
                };

                self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
            })*
        }

        impl TyCtxt<$tcx> {
            $($(#[$attr])*
            #[inline(always)]
            #[must_use]
            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
            {
                self.at(DUMMY_SP).$name(key)
            })*
        }

        impl TyCtxtAt<$tcx> {
            $($(#[$attr])*
            #[inline(always)]
            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
            {
                let key = key.into_query_param();
                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| {
                    value.clone()
                });

                let lookup = match cached {
                    Ok(value) => return value,
                    Err(lookup) => lookup,
                };

                self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
            })*
        }

        pub struct Providers {
            $(pub $name: for<'tcx> fn(
                TyCtxt<'tcx>,
                query_keys::$name<'tcx>,
            ) -> query_values::$name<'tcx>,)*
        }

        impl Default for Providers {
            fn default() -> Self {
                Providers {
                    $($name: |_, key| bug!(
                        "`tcx.{}({:?})` unsupported by its crate; \
                         perhaps the `{}` query was never assigned a provider function",
                        stringify!($name),
                        key,
                        stringify!($name),
                    ),)*
                }
            }
        }

        impl Copy for Providers {}
        impl Clone for Providers {
            fn clone(&self) -> Self { *self }
        }

        pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
            fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;

            fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;

            $($(#[$attr])*
            fn $name(
                &'tcx self,
                tcx: TyCtxt<$tcx>,
                span: Span,
                key: query_keys::$name<$tcx>,
                lookup: QueryLookup,
                mode: QueryMode,
            ) -> Option<query_stored::$name<$tcx>>;)*
        }
    };
}

// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
// which memoizes and does dep-graph tracking, wrapping around the actual
// `Providers` that the driver creates (using several `rustc_*` crates).
//
// The result type of each query must implement `Clone`, and additionally
// `ty::query::values::Value`, which produces an appropriate placeholder
// (error) value if the query resulted in a query cycle.
// Queries marked with `fatal_cycle` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.

rustc_query_append! { [define_callbacks!][<'tcx>] }

mod sealed {
    use super::{DefId, LocalDefId};

    /// An analogue of the `Into` trait that's intended only for query paramaters.
    ///
    /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
    /// user call `to_def_id` to convert between them everywhere else.
    pub trait IntoQueryParam<P> {
        fn into_query_param(self) -> P;
    }

    impl<P> IntoQueryParam<P> for P {
        #[inline(always)]
        fn into_query_param(self) -> P {
            self
        }
    }

    impl IntoQueryParam<DefId> for LocalDefId {
        #[inline(always)]
        fn into_query_param(self) -> DefId {
            self.to_def_id()
        }
    }
}

use sealed::IntoQueryParam;

impl TyCtxt<'tcx> {
    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
        let def_id = def_id.into_query_param();
        self.opt_def_kind(def_id)
            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
    }
}

impl TyCtxtAt<'tcx> {
    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
        let def_id = def_id.into_query_param();
        self.opt_def_kind(def_id)
            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
    }
}
<commit_msg>Avoid trivial lambdas.<commit_after>use crate::dep_graph;
use crate::hir::exports::Export;
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintLevelMap;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::AccessLevels;
use crate::middle::region;
use crate::middle::resolve_lifetime::{
    LifetimeScopeForPath, ObjectLifetimeDefault, Region, ResolveLifetimes,
};
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
use crate::mir::interpret::GlobalId;
use crate::mir::interpret::{ConstAlloc, LitToConstError, LitToConstInput};
use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
use crate::mir::mono::CodegenUnit;
use crate::thir;
use crate::traits::query::{
    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
};
use crate::traits::query::{
    DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult,
    OutlivesBound,
};
use crate::traits::specialization_graph;
use crate::traits::{self, ImplSource};
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
use rustc_session::utils::NativeLibKind;
use rustc_session::Limits;
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;

use rustc_ast as ast;
use rustc_attr as attr;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use std::collections::BTreeMap;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;

pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;

#[derive(Copy, Clone)]
pub struct TyCtxtAt<'tcx> {
    pub tcx: TyCtxt<'tcx>,
    pub span: Span,
}

impl Deref for TyCtxtAt<'tcx> {
    type Target = TyCtxt<'tcx>;
    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &self.tcx
    }
}

#[derive(Copy, Clone)]
pub struct TyCtxtEnsure<'tcx> {
    pub tcx: TyCtxt<'tcx>,
}

impl TyCtxt<'tcx> {
    /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
    /// are executed instead of just returning their results.
    #[inline(always)]
    pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
        TyCtxtEnsure { tcx: self }
    }

    /// Returns a transparent wrapper for `TyCtxt` which uses
    /// `span` as the location of queries performed through it.
    #[inline(always)]
    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
        TyCtxtAt { tcx: self, span }
    }

    pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
        self.queries.try_mark_green(self, dep_node)
    }
}

/// Helper for `TyCtxtEnsure` to avoid a closure.
#[inline(always)]
fn noop<T>(_: &T) {}

macro_rules! query_helper_param_ty {
    (DefId) => { impl IntoQueryParam<DefId> };
    ($K:ty) => { $K };
}

macro_rules! query_storage {
    ([][$K:ty, $V:ty]) => {
        <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
    };
    ([(storage $ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
        <$ty as CacheSelector<$K, $V>>::Cache
    };
    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
        query_storage!([$($modifiers)*][$($args)*])
    };
}

macro_rules! define_callbacks {
    (<$tcx:tt>
     $($(#[$attr:meta])*
        [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {

        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
        // below, but using type aliases instead of associated types, to bypass
        // the limitations around normalizing under HRTB - for example, this:
        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
        // This is primarily used by the `provide!` macro in `rustc_metadata`.
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_keys {
            use super::*;

            $(pub type $name<$tcx> = $($K)*;)*
        }
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_values {
            use super::*;

            $(pub type $name<$tcx> = $V;)*
        }
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_storage {
            use super::*;

            $(pub type $name<$tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
        }
        #[allow(nonstandard_style, unused_lifetimes)]
        pub mod query_stored {
            use super::*;

            $(pub type $name<$tcx> = <query_storage::$name<$tcx> as QueryStorage>::Stored;)*
        }

        #[derive(Default)]
        pub struct QueryCaches<$tcx> {
            $($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
        }

        impl TyCtxtEnsure<$tcx> {
            $($(#[$attr])*
            #[inline(always)]
            pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
                let key = key.into_query_param();
                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);

                let lookup = match cached {
                    Ok(()) => return,
                    Err(lookup) => lookup,
                };

                self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
            })*
        }

        impl TyCtxt<$tcx> {
            $($(#[$attr])*
            #[inline(always)]
            #[must_use]
            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
            {
                self.at(DUMMY_SP).$name(key)
            })*
        }

        impl TyCtxtAt<$tcx> {
            $($(#[$attr])*
            #[inline(always)]
            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
            {
                let key = key.into_query_param();
                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone);

                let lookup = match cached {
                    Ok(value) => return value,
                    Err(lookup) => lookup,
                };

                self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
            })*
        }

        pub struct Providers {
            $(pub $name: for<'tcx> fn(
                TyCtxt<'tcx>,
                query_keys::$name<'tcx>,
            ) -> query_values::$name<'tcx>,)*
        }

        impl Default for Providers {
            fn default() -> Self {
                Providers {
                    $($name: |_, key| bug!(
                        "`tcx.{}({:?})` unsupported by its crate; \
                         perhaps the `{}` query was never assigned a provider function",
                        stringify!($name),
                        key,
                        stringify!($name),
                    ),)*
                }
            }
        }

        impl Copy for Providers {}
        impl Clone for Providers {
            fn clone(&self) -> Self { *self }
        }

        pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
            fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;

            fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;

            $($(#[$attr])*
            fn $name(
                &'tcx self,
                tcx: TyCtxt<$tcx>,
                span: Span,
                key: query_keys::$name<$tcx>,
                lookup: QueryLookup,
                mode: QueryMode,
            ) -> Option<query_stored::$name<$tcx>>;)*
        }
    };
}

// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
// which memoizes and does dep-graph tracking, wrapping around the actual
// `Providers` that the driver creates (using several `rustc_*` crates).
//
// The result type of each query must implement `Clone`, and additionally
// `ty::query::values::Value`, which produces an appropriate placeholder
// (error) value if the query resulted in a query cycle.
// Queries marked with `fatal_cycle` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.

rustc_query_append! { [define_callbacks!][<'tcx>] }

mod sealed {
    use super::{DefId, LocalDefId};

    /// An analogue of the `Into` trait that's intended only for query paramaters.
    ///
    /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
    /// user call `to_def_id` to convert between them everywhere else.
    pub trait IntoQueryParam<P> {
        fn into_query_param(self) -> P;
    }

    impl<P> IntoQueryParam<P> for P {
        #[inline(always)]
        fn into_query_param(self) -> P {
            self
        }
    }

    impl IntoQueryParam<DefId> for LocalDefId {
        #[inline(always)]
        fn into_query_param(self) -> DefId {
            self.to_def_id()
        }
    }
}

use sealed::IntoQueryParam;

impl TyCtxt<'tcx> {
    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
        let def_id = def_id.into_query_param();
        self.opt_def_kind(def_id)
            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
    }
}

impl TyCtxtAt<'tcx> {
    pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
        let def_id = def_id.into_query_param();
        self.opt_def_kind(def_id)
            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
    }
}
<|endoftext|>