<commit_before>use schema::{Field, Term, IndexRecordOption};
use query::{Query, Weight, Scorer};
use termdict::{TermDictionary, TermStreamer, TermStreamerBuilder};
use core::SegmentReader;
use common::DocBitSet;
use Result;
use std::any::Any;
use core::Searcher;
use query::BitSetDocSet;
use query::ConstScorer;

#[derive(Clone, Debug)]
enum Boundary {
    Included(Vec<u8>),
    Excluded(Vec<u8>),
    Unbounded,
}

#[derive(Clone, Debug)]
pub struct RangeDefinition {
    field: Field,
    left_bound: Boundary,
    right_bound: Boundary
}

impl RangeDefinition {
    pub fn for_field(field: Field) -> RangeDefinition{
        RangeDefinition {
            field,
            left_bound: Boundary::Unbounded,
            right_bound: Boundary::Unbounded
        }
    }

    pub fn left_included(mut self, left: Term) -> RangeDefinition {
        assert_eq!(left.field(), self.field);
        self.left_bound = Boundary::Included(left.value_bytes().to_owned());
        self
    }

    pub fn left_excluded(mut self, left: Term) -> RangeDefinition {
        assert_eq!(left.field(), self.field);
        self.left_bound = Boundary::Excluded(left.value_bytes().to_owned());
        self
    }

    pub fn right_included(mut self, right: Term) -> RangeDefinition {
        assert_eq!(right.field(), self.field);
        self.right_bound = Boundary::Included(right.value_bytes().to_owned());
        self
    }

    pub fn right_excluded(mut self, right: Term) -> RangeDefinition {
        assert_eq!(right.field(), self.field);
        self.right_bound = Boundary::Excluded(right.value_bytes().to_owned());
        self
    }

    pub fn term_range<'a, T>(&self, term_dict: &'a T) -> T::Streamer
        where T: TermDictionary<'a> + 'a
    {
        use self::Boundary::*;
        let mut term_stream_builder = term_dict.range();
        term_stream_builder =
            match &self.left_bound {
                &Included(ref term_val) => term_stream_builder.ge(term_val),
                &Excluded(ref term_val) => term_stream_builder.gt(term_val),
                &Unbounded => term_stream_builder
            };
        term_stream_builder =
            match &self.right_bound {
                &Included(ref term_val) => term_stream_builder.le(term_val),
                &Excluded(ref term_val) => term_stream_builder.lt(term_val),
                &Unbounded => term_stream_builder
            };
        term_stream_builder.into_stream()
    }
}

#[derive(Debug)]
pub struct RangeQuery {
    range_definition: RangeDefinition
}

impl RangeQuery {
    fn new(range_definition: RangeDefinition) -> RangeQuery {
        RangeQuery {
            range_definition
        }
    }
}

impl Query for RangeQuery {
    fn as_any(&self) -> &Any {
        self
    }

    fn weight(&self, _searcher: &Searcher) -> Result<Box<Weight>> {
        Ok(box RangeWeight {
            range_definition: self.range_definition.clone()
        })
    }
}

pub struct RangeWeight {
    range_definition: RangeDefinition
}

impl Weight for RangeWeight {
    fn scorer<'a>(&'a self, reader: &'a SegmentReader) -> Result<Box<Scorer + 'a>> {
        let max_doc = reader.max_doc();
        let mut doc_bitset = DocBitSet::with_maxdoc(max_doc);

        let inverted_index = reader.inverted_index(self.range_definition.field);
        let term_dict = inverted_index.terms();
        let mut term_range = self.range_definition.term_range(term_dict);
        while term_range.advance() {
            let term_info = term_range.value();
            let mut block_segment_postings = inverted_index.read_block_postings_from_terminfo(term_info,IndexRecordOption::Basic);
            while block_segment_postings.advance() {
                for &doc in block_segment_postings.docs() {
                    doc_bitset.insert(doc);
                }
            }
        }
        let doc_bitset = BitSetDocSet::from(doc_bitset);
        Ok(box ConstScorer::new(doc_bitset))
    }
}

#[cfg(test)]
mod tests {

    use Index;
    use schema::{SchemaBuilder, Field, Document, INT_INDEXED};

    #[test]
    fn test_range_query() {
        let int_field: Field;
        let schema = {
            let mut schema_builder = SchemaBuilder::new();
            int_field = schema_builder.add_i64_field("intfield", INT_INDEXED);
            schema_builder.build()
        };

        let index = Index::create_in_ram(schema);
        {
            let mut index_writer = index.writer_with_num_threads(2, 6_000_000).unwrap();

            for i in 1..100 {
                let mut doc = Document::new();
                for j in 1..100 {
                    if i % j == 0 {
                        doc.add_i64(int_field, j as i64);
                    }
                }
                index_writer.add_document(doc);
            }

            index_writer.commit().unwrap();
        }
        index.load_searchers().unwrap();
        let searcher = index.searcher();
        use collector::CountCollector;
        use schema::Term;
        use query::Query;
        use super::{RangeQuery, RangeDefinition};

        let count_multiples = |range: RangeDefinition| {
            let mut count_collector = CountCollector::default();
            let range_query = RangeQuery::new(range);
            range_query.search(&*searcher, &mut count_collector).unwrap();
            count_collector.count()
        };

        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_included(Term::from_field_i64(int_field, 10))
               .right_excluded(Term::from_field_i64(int_field, 11)))
            , 9
        );
        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_included(Term::from_field_i64(int_field, 10))
                .right_included(Term::from_field_i64(int_field, 11)))
            , 18
        );
        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_excluded(Term::from_field_i64(int_field, 9))
                .right_included(Term::from_field_i64(int_field, 10)))
            , 9
        );
        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_excluded(Term::from_field_i64(int_field, 9)))
            , 90
        );

    }

}<commit_msg>Make constructor of RangeQuery public<commit_after>use schema::{Field, Term, IndexRecordOption};
use query::{Query, Weight, Scorer};
use termdict::{TermDictionary, TermStreamer, TermStreamerBuilder};
use core::SegmentReader;
use common::DocBitSet;
use Result;
use std::any::Any;
use core::Searcher;
use query::BitSetDocSet;
use query::ConstScorer;

#[derive(Clone, Debug)]
enum Boundary {
    Included(Vec<u8>),
    Excluded(Vec<u8>),
    Unbounded,
}

#[derive(Clone, Debug)]
pub struct RangeDefinition {
    field: Field,
    left_bound: Boundary,
    right_bound: Boundary
}

impl RangeDefinition {
    pub fn for_field(field: Field) -> RangeDefinition{
        RangeDefinition {
            field,
            left_bound: Boundary::Unbounded,
            right_bound: Boundary::Unbounded
        }
    }

    pub fn left_included(mut self, left: Term) -> RangeDefinition {
        assert_eq!(left.field(), self.field);
        self.left_bound = Boundary::Included(left.value_bytes().to_owned());
        self
    }

    pub fn left_excluded(mut self, left: Term) -> RangeDefinition {
        assert_eq!(left.field(), self.field);
        self.left_bound = Boundary::Excluded(left.value_bytes().to_owned());
        self
    }

    pub fn right_included(mut self, right: Term) -> RangeDefinition {
        assert_eq!(right.field(), self.field);
        self.right_bound = Boundary::Included(right.value_bytes().to_owned());
        self
    }

    pub fn right_excluded(mut self, right: Term) -> RangeDefinition {
        assert_eq!(right.field(), self.field);
        self.right_bound = Boundary::Excluded(right.value_bytes().to_owned());
        self
    }

    pub fn term_range<'a, T>(&self, term_dict: &'a T) -> T::Streamer
        where T: TermDictionary<'a> + 'a
    {
        use self::Boundary::*;
        let mut term_stream_builder = term_dict.range();
        term_stream_builder =
            match &self.left_bound {
                &Included(ref term_val) => term_stream_builder.ge(term_val),
                &Excluded(ref term_val) => term_stream_builder.gt(term_val),
                &Unbounded => term_stream_builder
            };
        term_stream_builder =
            match &self.right_bound {
                &Included(ref term_val) => term_stream_builder.le(term_val),
                &Excluded(ref term_val) => term_stream_builder.lt(term_val),
                &Unbounded => term_stream_builder
            };
        term_stream_builder.into_stream()
    }
}

#[derive(Debug)]
pub struct RangeQuery {
    range_definition: RangeDefinition
}

impl RangeQuery {
    pub fn new(range_definition: RangeDefinition) -> RangeQuery {
        RangeQuery {
            range_definition
        }
    }
}

impl Query for RangeQuery {
    fn as_any(&self) -> &Any {
        self
    }

    fn weight(&self, _searcher: &Searcher) -> Result<Box<Weight>> {
        Ok(box RangeWeight {
            range_definition: self.range_definition.clone()
        })
    }
}

pub struct RangeWeight {
    range_definition: RangeDefinition
}

impl Weight for RangeWeight {
    fn scorer<'a>(&'a self, reader: &'a SegmentReader) -> Result<Box<Scorer + 'a>> {
        let max_doc = reader.max_doc();
        let mut doc_bitset = DocBitSet::with_maxdoc(max_doc);

        let inverted_index = reader.inverted_index(self.range_definition.field);
        let term_dict = inverted_index.terms();
        let mut term_range = self.range_definition.term_range(term_dict);
        while term_range.advance() {
            let term_info = term_range.value();
            let mut block_segment_postings = inverted_index.read_block_postings_from_terminfo(term_info,IndexRecordOption::Basic);
            while block_segment_postings.advance() {
                for &doc in block_segment_postings.docs() {
                    doc_bitset.insert(doc);
                }
            }
        }
        let doc_bitset = BitSetDocSet::from(doc_bitset);
        Ok(box ConstScorer::new(doc_bitset))
    }
}

#[cfg(test)]
mod tests {

    use Index;
    use schema::{SchemaBuilder, Field, Document, INT_INDEXED};

    #[test]
    fn test_range_query() {
        let int_field: Field;
        let schema = {
            let mut schema_builder = SchemaBuilder::new();
            int_field = schema_builder.add_i64_field("intfield", INT_INDEXED);
            schema_builder.build()
        };

        let index = Index::create_in_ram(schema);
        {
            let mut index_writer = index.writer_with_num_threads(2, 6_000_000).unwrap();

            for i in 1..100 {
                let mut doc = Document::new();
                for j in 1..100 {
                    if i % j == 0 {
                        doc.add_i64(int_field, j as i64);
                    }
                }
                index_writer.add_document(doc);
            }

            index_writer.commit().unwrap();
        }
        index.load_searchers().unwrap();
        let searcher = index.searcher();
        use collector::CountCollector;
        use schema::Term;
        use query::Query;
        use super::{RangeQuery, RangeDefinition};

        let count_multiples = |range: RangeDefinition| {
            let mut count_collector = CountCollector::default();
            let range_query = RangeQuery::new(range);
            range_query.search(&*searcher, &mut count_collector).unwrap();
            count_collector.count()
        };

        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_included(Term::from_field_i64(int_field, 10))
               .right_excluded(Term::from_field_i64(int_field, 11)))
            , 9
        );
        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_included(Term::from_field_i64(int_field, 10))
                .right_included(Term::from_field_i64(int_field, 11)))
            , 18
        );
        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_excluded(Term::from_field_i64(int_field, 9))
                .right_included(Term::from_field_i64(int_field, 10)))
            , 9
        );
        assert_eq!(
            count_multiples(RangeDefinition::for_field(int_field)
                .left_excluded(Term::from_field_i64(int_field, 9)))
            , 90
        );

    }

}<|endoftext|>


<commit_before>
use std::io;
use std::borrow::Cow;
use std::fmt;
use std::error;

use common::{Position, TextPosition};

use super::{Error, ErrorKind};

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.pos, self.msg())
    }
}

impl Position for Error {
    #[inline]
    fn position(&self) -> TextPosition { self.pos }
}

impl Error {
    // /// Creates a new error using position information from the provided
    // /// `Position` object and a message.
    // #[inline]
    // pub fn new<O: Position, S: Into<Cow<'static, str>>>(o: &O, msg: S) -> Error {
    //     Error { pos: o.position(), msg: msg.into() }
    // }

    /// Returns a reference to a message which is contained inside this error.
    #[inline]
    pub fn msg(&self) -> &str {
    	use super::ErrorKind::*;
    	match self.kind {
    		UnexpectedEof => &"Unexpected EOF",
    		Utf8( ref reason ) => error_description( reason ),
    		Io( ref io_error ) => error_description( io_error ),
    		Syntax( ref msg ) => msg.as_ref(),
    	}
    }
}

impl error::Error for Error {
    #[inline]
    fn description(&self) -> &str { self.msg() }
}

impl<'a, P, M> From<( &'a P, M )> for Error where P: Position, M: Into<Cow<'static, str>> {
	fn from( orig: (&'a P, M) ) -> Self {
		Error{
			pos: orig.0.position(),
			kind: ErrorKind::Syntax( orig.1.into() )
		}
	}
}

impl From<::util::CharReadError> for Error {
	fn from( e: ::util::CharReadError ) -> Self {
		use ::util::CharReadError::*;
		Error{
			pos: TextPosition::new(),
			kind: match e {
				UnexpectedEof => ErrorKind::UnexpectedEof,
				Utf8( ref reason ) => ErrorKind::Utf8( reason.clone() ),
				Io( ref io_error ) =>
					ErrorKind::Io(
						io::Error::new(
							io_error.kind(),
							error_description( io_error )
						)
					),
			}
		}
	}
}

impl Clone for ErrorKind {
	fn clone( &self ) -> Self {
		use super::ErrorKind::*;
		match *self {
			UnexpectedEof => UnexpectedEof,
			Utf8( ref reason ) => Utf8( reason.clone() ),
			Io( ref io_error ) => Io( io::Error::new( io_error.kind(), error_description( io_error ) ) ),
			Syntax( ref msg ) => Syntax( msg.clone() ),
		}
	}
}
impl PartialEq for ErrorKind {
	fn eq( &self, other: &ErrorKind ) -> bool {
		use super::ErrorKind::*;
		match ( self, other ) {
			( &UnexpectedEof, &UnexpectedEof ) => true,
			( &Utf8( ref left ), &Utf8( ref right ) ) => left == right,
			( &Io( ref left ), &Io( ref right ) ) =>
				left.kind() == right.kind() &&
				error_description( left ) == error_description( right ),
			( &Syntax( ref left ), &Syntax( ref right ) ) =>
				left == right,

			( _, _ ) => false,
		}
	}
}
impl Eq for ErrorKind {}

fn error_description( e: &error::Error ) -> &str { e.description() }<commit_msg>Expose `reader::ErrorKind` via `reader::Error::kind( .. )`<commit_after>
use std::io;
use std::borrow::Cow;
use std::fmt;
use std::error;

use common::{Position, TextPosition};

use super::{Error, ErrorKind};

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.pos, self.msg())
    }
}

impl Position for Error {
    #[inline]
    fn position(&self) -> TextPosition { self.pos }
}

impl Error {
    /// Returns a reference to a message which is contained inside this error.
    #[inline]
    pub fn msg(&self) -> &str {
    	use super::ErrorKind::*;
    	match self.kind {
    		UnexpectedEof => &"Unexpected EOF",
    		Utf8( ref reason ) => error_description( reason ),
    		Io( ref io_error ) => error_description( io_error ),
    		Syntax( ref msg ) => msg.as_ref(),
    	}
    }

    pub fn kind( &self ) -> &ErrorKind { &self.kind }
}

impl error::Error for Error {
    #[inline]
    fn description(&self) -> &str { self.msg() }
}

impl<'a, P, M> From<( &'a P, M )> for Error where P: Position, M: Into<Cow<'static, str>> {
	fn from( orig: (&'a P, M) ) -> Self {
		Error{
			pos: orig.0.position(),
			kind: ErrorKind::Syntax( orig.1.into() )
		}
	}
}

impl From<::util::CharReadError> for Error {
	fn from( e: ::util::CharReadError ) -> Self {
		use ::util::CharReadError::*;
		Error{
			pos: TextPosition::new(),
			kind: match e {
				UnexpectedEof => ErrorKind::UnexpectedEof,
				Utf8( ref reason ) => ErrorKind::Utf8( reason.clone() ),
				Io( ref io_error ) =>
					ErrorKind::Io(
						io::Error::new(
							io_error.kind(),
							error_description( io_error )
						)
					),
			}
		}
	}
}

impl Clone for ErrorKind {
	fn clone( &self ) -> Self {
		use super::ErrorKind::*;
		match *self {
			UnexpectedEof => UnexpectedEof,
			Utf8( ref reason ) => Utf8( reason.clone() ),
			Io( ref io_error ) => Io( io::Error::new( io_error.kind(), error_description( io_error ) ) ),
			Syntax( ref msg ) => Syntax( msg.clone() ),
		}
	}
}
impl PartialEq for ErrorKind {
	fn eq( &self, other: &ErrorKind ) -> bool {
		use super::ErrorKind::*;
		match ( self, other ) {
			( &UnexpectedEof, &UnexpectedEof ) => true,
			( &Utf8( ref left ), &Utf8( ref right ) ) => left == right,
			( &Io( ref left ), &Io( ref right ) ) =>
				left.kind() == right.kind() &&
				error_description( left ) == error_description( right ),
			( &Syntax( ref left ), &Syntax( ref right ) ) =>
				left == right,

			( _, _ ) => false,
		}
	}
}
impl Eq for ErrorKind {}

fn error_description( e: &error::Error ) -> &str { e.description() }<|endoftext|>


<commit_before>use std::{
    fmt::{self, Debug},
    ops::Deref,
    sync::atomic::Ordering::{Acquire, Release, AcqRel},
};

use crossbeam_epoch::{
    unprotected, Atomic, Guard,
    Owned, Shared,
};

use crate::pagecache::debug::debug_delay;

type CompareAndSwapResult<'g, T> = std::result::Result<
    Shared<'g, Node<T>>,
    (Shared<'g, Node<T>>, Owned<Node<T>>),
>;

/// A node in the lock-free `Stack`.
#[derive(Debug)]
pub struct Node<T: Send + 'static> {
    pub(crate) inner: T,
    pub(crate) next: Atomic<Node<T>>,
}

impl<T: Send + 'static> Drop for Node<T> {
    fn drop(&mut self) {
        unsafe {
            let next = self.next.load(Acquire, unprotected());
            if !next.as_raw().is_null() {
                drop(next.into_owned());
            }
        }
    }
}

/// A simple lock-free stack, with the ability to atomically
/// append or entirely swap-out entries.
pub struct Stack<T: Send + 'static> {
    head: Atomic<Node<T>>,
}

impl<T: Send + 'static> Default for Stack<T> {
    fn default() -> Self {
        Self {
            head: Atomic::null(),
        }
    }
}

impl<T: Send + 'static> Drop for Stack<T> {
    fn drop(&mut self) {
        unsafe {
            let curr = self.head.load(Acquire, unprotected());
            if !curr.as_raw().is_null() {
                drop(curr.into_owned());
            }
        }
    }
}

impl<T> Debug for Stack<T>
where
    T: Clone + Debug + Send + 'static + Sync,
{
    fn fmt(
        &self,
        formatter: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let guard = crossbeam_epoch::pin();
        let head = self.head(&guard);
        let iter = StackIter::from_ptr(head, &guard);

        formatter.write_str("Stack [")?;
        let mut written = false;
        for node in iter {
            if written {
                formatter.write_str(", ")?;
            }
            formatter.write_str(&*format!("({:?}) ", &node as *const _))?;
            node.fmt(formatter)?;
            written = true;
        }
        formatter.write_str("]")?;
        Ok(())
    }
}

impl<T: Send + 'static> Deref for Node<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.inner
    }
}

impl<T: Clone + Send + Sync + 'static> Stack<T> {
    /// Add an item to the stack, spinning until successful.
    pub fn push(&self, inner: T, guard: &Guard) {
        debug_delay();
        let node = Owned::new(Node {
            inner,
            next: Atomic::null(),
        });

        unsafe {
            let node = node.into_shared(guard);

            loop {
                let head = self.head(guard);
                node.deref().next.store(head, Release);
                if self
                    .head
                    .compare_and_set(head, node, Release, guard)
                    .is_ok()
                {
                    return;
                }
            }
        }
    }

    /// Pop the next item off the stack. Returns None if nothing is there.
    fn _pop(&self, guard: &Guard) -> Option<T> {
        use std::ptr;
        debug_delay();
        let mut head = self.head(&guard);
        loop {
            match unsafe { head.as_ref() } {
                Some(h) => {
                    let next = h.next.load(Acquire, &guard);
                    match self.head.compare_and_set(head, next, Release, &guard)
                    {
                        Ok(_) => unsafe {
                            guard.defer_destroy(head);
                            return Some(ptr::read(&h.inner));
                        },
                        Err(h) => head = h.current,
                    }
                }
                None => return None,
            }
        }
    }

    /// compare and push
    pub fn cap_node<'g>(
        &self,
        old: Shared<'_, Node<T>>,
        mut node: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        // properly set next ptr
        node.next = Atomic::from(old);
        let res = self.head.compare_and_set(old, node, AcqRel, guard);

        match res {
            Err(e) => {
                // we want to set next to null to prevent
                // the current shared head from being
                // dropped when we drop this node.
                let mut returned = e.new;
                returned.next = Atomic::null();
                Err((e.current, returned))
            }
            Ok(success) => Ok(success),
        }
    }

    /// compare and swap
    pub fn cas<'g>(
        &self,
        old: Shared<'g, Node<T>>,
        new: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        debug_delay();
        let res = self.head.compare_and_set(old, new, AcqRel, guard);

        match res {
            Ok(success) => {
                if !old.is_null() {
                    unsafe {
                        guard.defer_destroy(old);
                    };
                }
                Ok(success)
            }
            Err(e) => Err((e.current, e.new)),
        }
    }

    /// Returns the current head pointer of the stack, which can
    /// later be used as the key for cas and cap operations.
    pub fn head<'g>(&self, guard: &'g Guard) -> Shared<'g, Node<T>> {
        self.head.load(Acquire, guard)
    }
}

/// An iterator over nodes in a lock-free stack.
pub struct StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    inner: Shared<'a, Node<T>>,
    guard: &'a Guard,
}

impl<'a, T> StackIter<'a, T>
where
    T: 'a + Send + 'static + Sync,
{
    /// Creates a StackIter from a pointer to one.
    pub fn from_ptr<'b>(
        ptr: Shared<'b, Node<T>>,
        guard: &'b Guard,
    ) -> StackIter<'b, T> {
        StackIter { inner: ptr, guard }
    }
}

impl<'a, T> Iterator for StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        debug_delay();
        if self.inner.is_null() {
            None
        } else {
            unsafe {
                let ret = &self.inner.deref().inner;
                self.inner = self.inner.deref().next.load(Acquire, self.guard);
                Some(ret)
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut size = 0;
        let mut cursor = self.inner;

        while !cursor.is_null() {
            unsafe {
                cursor = cursor.deref().next.load(Acquire, self.guard);
            }
            size += 1;
        }

        (size, Some(size))
    }
}

/// Turns a vector of elements into a lock-free stack
/// of them, and returns the head of the stack.
pub fn node_from_frag_vec<T>(from: Vec<T>) -> Owned<Node<T>>
where
    T: Send + 'static + Sync,
{
    let mut last = None;

    for item in from.into_iter().rev() {
        last = if let Some(last) = last {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::from(last),
            }))
        } else {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::null(),
            }))
        }
    }

    last.expect("at least one frag was provided in the from Vec")
}

#[test]
fn basic_functionality() {
    use std::sync::Arc;
    use std::thread;
    use crossbeam_epoch::pin;
    use crossbeam_utils::CachePadded;

    let guard = pin();
    let ll = Arc::new(Stack::default());
    assert_eq!(ll._pop(&guard), None);
    ll.push(CachePadded::new(1), &guard);
    let ll2 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        ll2.push(CachePadded::new(2), &guard);
        ll2.push(CachePadded::new(3), &guard);
        ll2.push(CachePadded::new(4), &guard);
        guard.flush();
    });
    t.join().unwrap();
    ll.push(CachePadded::new(5), &guard);
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(5)));
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(4)));
    let ll3 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll3._pop(&guard), Some(CachePadded::new(3)));
        assert_eq!(ll3._pop(&guard), Some(CachePadded::new(2)));
        guard.flush();
    });
    t.join().unwrap();
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(1)));
    let ll4 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll4._pop(&guard), None);
        guard.flush();
    });
    t.join().unwrap();
    drop(ll);
    guard.flush();
    drop(guard);
}
<commit_msg>Fix double-free in test-only stack pop code<commit_after>use std::{
    fmt::{self, Debug},
    ops::Deref,
    sync::atomic::Ordering::{Acquire, Release, AcqRel},
};

use crossbeam_epoch::{
    unprotected, Atomic, Guard,
    Owned, Shared,
};

use crate::pagecache::debug::debug_delay;

type CompareAndSwapResult<'g, T> = std::result::Result<
    Shared<'g, Node<T>>,
    (Shared<'g, Node<T>>, Owned<Node<T>>),
>;

/// A node in the lock-free `Stack`.
#[derive(Debug)]
pub struct Node<T: Send + 'static> {
    pub(crate) inner: T,
    pub(crate) next: Atomic<Node<T>>,
}

impl<T: Send + 'static> Drop for Node<T> {
    fn drop(&mut self) {
        unsafe {
            let next = self.next.load(Acquire, unprotected());
            if !next.as_raw().is_null() {
                drop(next.into_owned());
            }
        }
    }
}

/// A simple lock-free stack, with the ability to atomically
/// append or entirely swap-out entries.
pub struct Stack<T: Send + 'static> {
    head: Atomic<Node<T>>,
}

impl<T: Send + 'static> Default for Stack<T> {
    fn default() -> Self {
        Self {
            head: Atomic::null(),
        }
    }
}

impl<T: Send + 'static> Drop for Stack<T> {
    fn drop(&mut self) {
        unsafe {
            let curr = self.head.load(Acquire, unprotected());
            if !curr.as_raw().is_null() {
                drop(curr.into_owned());
            }
        }
    }
}

impl<T> Debug for Stack<T>
where
    T: Clone + Debug + Send + 'static + Sync,
{
    fn fmt(
        &self,
        formatter: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let guard = crossbeam_epoch::pin();
        let head = self.head(&guard);
        let iter = StackIter::from_ptr(head, &guard);

        formatter.write_str("Stack [")?;
        let mut written = false;
        for node in iter {
            if written {
                formatter.write_str(", ")?;
            }
            formatter.write_str(&*format!("({:?}) ", &node as *const _))?;
            node.fmt(formatter)?;
            written = true;
        }
        formatter.write_str("]")?;
        Ok(())
    }
}

impl<T: Send + 'static> Deref for Node<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.inner
    }
}

impl<T: Clone + Send + Sync + 'static> Stack<T> {
    /// Add an item to the stack, spinning until successful.
    pub fn push(&self, inner: T, guard: &Guard) {
        debug_delay();
        let node = Owned::new(Node {
            inner,
            next: Atomic::null(),
        });

        unsafe {
            let node = node.into_shared(guard);

            loop {
                let head = self.head(guard);
                node.deref().next.store(head, Release);
                if self
                    .head
                    .compare_and_set(head, node, Release, guard)
                    .is_ok()
                {
                    return;
                }
            }
        }
    }

    /// Pop the next item off the stack. Returns None if nothing is there.
    fn _pop(&self, guard: &Guard) -> Option<T> {
        use std::ptr;
        debug_delay();
        let mut head = self.head(&guard);
        loop {
            match unsafe { head.as_ref() } {
                Some(h) => {
                    let next = h.next.load(Acquire, &guard);
                    match self.head.compare_and_set(head, next, Release, &guard)
                    {
                        Ok(_) => unsafe {
                            // we use Acquire because we want to unset
                            // the next pointer before destruction
                            // to avoid double-frees.
                            h.next.store(Shared::default(), Acquire);
                            guard.defer_destroy(head);
                            return Some(ptr::read(&h.inner));
                        },
                        Err(h) => head = h.current,
                    }
                }
                None => return None,
            }
        }
    }

    /// compare and push
    pub fn cap_node<'g>(
        &self,
        old: Shared<'_, Node<T>>,
        mut node: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        // properly set next ptr
        node.next = Atomic::from(old);
        let res = self.head.compare_and_set(old, node, AcqRel, guard);

        match res {
            Err(e) => {
                // we want to set next to null to prevent
                // the current shared head from being
                // dropped when we drop this node.
                let mut returned = e.new;
                returned.next = Atomic::null();
                Err((e.current, returned))
            }
            Ok(success) => Ok(success),
        }
    }

    /// compare and swap
    pub fn cas<'g>(
        &self,
        old: Shared<'g, Node<T>>,
        new: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        debug_delay();
        let res = self.head.compare_and_set(old, new, AcqRel, guard);

        match res {
            Ok(success) => {
                if !old.is_null() {
                    unsafe {
                        guard.defer_destroy(old);
                    };
                }
                Ok(success)
            }
            Err(e) => Err((e.current, e.new)),
        }
    }

    /// Returns the current head pointer of the stack, which can
    /// later be used as the key for cas and cap operations.
    pub fn head<'g>(&self, guard: &'g Guard) -> Shared<'g, Node<T>> {
        self.head.load(Acquire, guard)
    }
}

/// An iterator over nodes in a lock-free stack.
pub struct StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    inner: Shared<'a, Node<T>>,
    guard: &'a Guard,
}

impl<'a, T> StackIter<'a, T>
where
    T: 'a + Send + 'static + Sync,
{
    /// Creates a StackIter from a pointer to one.
    pub fn from_ptr<'b>(
        ptr: Shared<'b, Node<T>>,
        guard: &'b Guard,
    ) -> StackIter<'b, T> {
        StackIter { inner: ptr, guard }
    }
}

impl<'a, T> Iterator for StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        debug_delay();
        if self.inner.is_null() {
            None
        } else {
            unsafe {
                let ret = &self.inner.deref().inner;
                self.inner = self.inner.deref().next.load(Acquire, self.guard);
                Some(ret)
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut size = 0;
        let mut cursor = self.inner;

        while !cursor.is_null() {
            unsafe {
                cursor = cursor.deref().next.load(Acquire, self.guard);
            }
            size += 1;
        }

        (size, Some(size))
    }
}

/// Turns a vector of elements into a lock-free stack
/// of them, and returns the head of the stack.
pub fn node_from_frag_vec<T>(from: Vec<T>) -> Owned<Node<T>>
where
    T: Send + 'static + Sync,
{
    let mut last = None;

    for item in from.into_iter().rev() {
        last = if let Some(last) = last {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::from(last),
            }))
        } else {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::null(),
            }))
        }
    }

    last.expect("at least one frag was provided in the from Vec")
}

#[test]
fn basic_functionality() {
    use std::sync::Arc;
    use std::thread;
    use crossbeam_epoch::pin;
    use crossbeam_utils::CachePadded;

    let guard = pin();
    let ll = Arc::new(Stack::default());
    assert_eq!(ll._pop(&guard), None);
    ll.push(CachePadded::new(1), &guard);
    let ll2 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        ll2.push(CachePadded::new(2), &guard);
        ll2.push(CachePadded::new(3), &guard);
        ll2.push(CachePadded::new(4), &guard);
        guard.flush();
    });
    t.join().unwrap();
    ll.push(CachePadded::new(5), &guard);
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(5)));
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(4)));
    let ll3 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll3._pop(&guard), Some(CachePadded::new(3)));
        assert_eq!(ll3._pop(&guard), Some(CachePadded::new(2)));
        guard.flush();
    });
    t.join().unwrap();
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(1)));
    let ll4 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll4._pop(&guard), None);
        guard.flush();
    });
    t.join().unwrap();
    drop(ll);
    guard.flush();
    drop(guard);
}
<|endoftext|>


<commit_before>extern crate image;
extern crate time;

use std::iter;
use std::path::Path;

use vector::*;
use objects::*;
mod lighting;

pub type Image = image::RgbImage;

pub fn write_image(image: Image, filename: &str) {
    let _ = image.save(&Path::new(filename));
}

pub fn raytrace(scene: &Scene, width: u32, height: u32, h_fov: f64) {
    let f_width = width as f64;
    let f_height = height as f64;
    let v_fov = h_fov * (f_height / f_width);

    let vw_per_pixel = 2.0 * (h_fov / 2.0).tan() / f_width;
    let vh_per_pixel = 2.0 * (v_fov / 2.0).tan() / f_height;

    let norm_up = scene.camera.up.normalized();
    let norm_right = scene.camera.direction.cross(scene.camera.up).normalized();

    let mut image = image::RgbImage::new(width, height);
    let start_time = time::precise_time_ns();

    let mut rays: u64 = 0;

    // This is ugly, but splitting it out into a let binding makes the
    // compiler sad.
    for ((x, y), pixel) in (0..width).flat_map(|y| {
        iter::repeat(y).zip(0..height)
    }).map(|coord| {
        let (x, y) = coord;
        let cast_ray = |dx: f64, dy: f64, rays: &mut u64| {
            *rays += 1;
            let fi = (x as f64) + dx;
            let fj = (y as f64) + dy;

            let u_rel = vw_per_pixel * (fi - (f_width / 2.0));
            let v_rel = vh_per_pixel * (fj - (f_height / 2.0));

            let pixel_loc = scene.camera.position + scene.camera.direction +
                (norm_right * u_rel) + (norm_up * v_rel);

            let ray = Ray {
                origin: scene.camera.position,
                direction: pixel_loc - scene.camera.position
            };

            let (color, new_rays) = lighting::get_color(&scene, &ray, 3);
            *rays += new_rays;
            color
        };
        // This makes the compiler happy. I'm not really sure what's going
        // on though.
        let c1 = cast_ray(0.25, 0.25, &mut rays);
        let c2 = cast_ray(0.75, 0.25, &mut rays);
        let c3 = cast_ray(0.50, 0.50, &mut rays);
        let c4 = cast_ray(0.75, 0.75, &mut rays);
        let c5 = cast_ray(0.25, 0.75, &mut rays);

        (coord, (c1 + c2 + c3 + c4 + c5) / 5.0)
    }) {
        image.put_pixel(x as u32, y as u32, pixel.to_rgb());
    }

    write_image(image, "test.png");

    let elapsed_time = ((time::precise_time_ns() - start_time) as f64) /
        1000000.0;
    let rays_per_s = 1000.0 * (rays as f64) / elapsed_time;
    println!("Traced {} rays in {} ms ({} rays per second).",
             rays, elapsed_time, rays_per_s);
}
<commit_msg>Refactor tracing loop<commit_after>extern crate image;
extern crate time;

use std::iter;
use std::path::Path;

use vector::*;
use objects::*;
mod lighting;

pub type Image = image::RgbImage;

pub fn write_image(image: Image, filename: &str) {
    let _ = image.save(&Path::new(filename));
}

pub fn raytrace(scene: &Scene, width: u32, height: u32, h_fov: f64) {
    let f_width = width as f64;
    let f_height = height as f64;
    let v_fov = h_fov * (f_height / f_width);

    let vw_per_pixel = 2.0 * (h_fov / 2.0).tan() / f_width;
    let vh_per_pixel = 2.0 * (v_fov / 2.0).tan() / f_height;

    let norm_up = scene.camera.up.normalized();
    let norm_right = scene.camera.direction.cross(scene.camera.up).normalized();

    let mut image = image::RgbImage::new(width, height);
    let start_time = time::precise_time_ns();

    let mut rays: u64 = 0;

    let tracer = |image: &mut image::RgbImage, rays: &mut u64| {
        let coords = (0..width).flat_map(|y| {
            iter::repeat(y).zip(0..height)
        });
        let trace_coord = |coord| {
            let (x, y) = coord;
            let cast_ray = |dx: f64, dy: f64, rays: &mut u64| {
                *rays += 1;
                let fi = (x as f64) + dx;
                let fj = (y as f64) + dy;

                let u_rel = vw_per_pixel * (fi - (f_width / 2.0));
                let v_rel = vh_per_pixel * (fj - (f_height / 2.0));

                let pixel_loc = scene.camera.position + scene.camera.direction +
                    (norm_right * u_rel) + (norm_up * v_rel);

                let ray = Ray {
                    origin: scene.camera.position,
                    direction: pixel_loc - scene.camera.position
                };

                let (color, new_rays) = lighting::get_color(&scene, &ray, 3);
                *rays += new_rays;
                color
            };

            let c1 = cast_ray(0.25, 0.25, rays);
            let c2 = cast_ray(0.75, 0.25, rays);
            let c3 = cast_ray(0.50, 0.50, rays);
            let c4 = cast_ray(0.75, 0.75, rays);
            let c5 = cast_ray(0.25, 0.75, rays);

            (coord, (c1 + c2 + c3 + c4 + c5) / 5.0)
        };
        for ((x, y), pixel) in coords.map(trace_coord) {
            image.put_pixel(x as u32, y as u32, pixel.to_rgb());
        }
    };
    tracer(&mut image, &mut rays);

    write_image(image, "test.png");

    let elapsed_time = ((time::precise_time_ns() - start_time) as f64) /
        1000000.0;
    let rays_per_s = 1000.0 * (rays as f64) / elapsed_time;
    println!("Traced {} rays in {} ms ({} rays per second).",
             rays, elapsed_time, rays_per_s);
}
<|endoftext|>


<commit_before>use hyper;

pub type HyperResponse = hyper::client::response::Response;

#[derive(Debug)]
pub struct Response {
    raw: HyperResponse,
    pub url: String,
    pub status_code: u16,
    pub reason: String,
}

impl Response {
    pub fn from_hyper(raw: HyperResponse) -> Self {
        let status_code;
        let reason;
        {
            let &hyper::http::RawStatus(sc, ref r) = raw.status_raw();
            status_code = sc;
            reason = r.to_string();
        }
        Response {
            raw: raw,
            url: "".to_string(),
            status_code: status_code,
            reason: reason,
        }
    }
}
<commit_msg>Fix Response.url content<commit_after>use hyper;

pub type HyperResponse = hyper::client::response::Response;

#[derive(Debug)]
pub struct Response {
    raw: HyperResponse,
    pub url: String,
    pub status_code: u16,
    pub reason: String,
}

impl Response {
    pub fn from_hyper(raw: HyperResponse) -> Self {
        let status_code;
        let reason;
        {
            let &hyper::http::RawStatus(sc, ref r) = raw.status_raw();
            status_code = sc;
            reason = r.to_string();
        }
        let url = raw.url.serialize();
        Response {
            raw: raw,
            url: url,
            status_code: status_code,
            reason: reason,
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use image_data::{RenderbufferFormat};
use types::GLError;

pub struct Renderbuffer {
    gl_id: GLuint
}

impl Renderbuffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Renderbuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteRenderbuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

pub struct RenderbufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a,
           RB: 'a + BorrowMut<RenderbufferBinder>,
           TU: 'a
{
    gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>,
    storage_params: Option<(RenderbufferFormat, u32, u32)>
}

impl<'a, AB, EAB, P, FB, RB, TU> RenderbufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a,
           RB: 'a + BorrowMut<RenderbufferBinder>,
           TU: 'a
{
    fn new(gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>) -> Self {
        RenderbufferBuilder {
            gl: gl,
            storage_params: None
        }
    }

    pub fn storage(mut self,
                   format: RenderbufferFormat,
                   width: u32,
                   height: u32)
        -> Self
    {
        self.storage_params = Some((format, width, height));
        self
    }

    pub fn try_unwrap(self) -> Result<Renderbuffer, GLError> {
        let gl = self.gl.borrowed_mut();
        let mut rbo = gl.gen_renderbuffer();

        match self.storage_params {
            Some((format, width, height)) => {
                {
                    let (mut gl_rbo, _) = gl.bind_renderbuffer(&mut rbo);
                    gl_rbo.storage(format, width, height);
                }

                Ok(rbo)
            },
            None => {
                let msg = "Error building renderbuffer: no format or dimensions provided";
                Err(GLError::Message(msg.to_owned()))
            }
        }
    }

    pub fn unwrap(self) -> Renderbuffer {
        self.try_unwrap().unwrap()
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn build_renderbuffer<'a>(&'a mut self)
        -> RenderbufferBuilder<'a, AB, EAB, P, FB, RB, TU>
        where RB: BorrowMut<RenderbufferBinder>
    {
        RenderbufferBuilder::new(self)
    }

    pub fn gen_renderbuffer(&self) -> Renderbuffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenRenderbuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Renderbuffer {
                gl_id: id
            }
        }
    }

    pub fn bind_renderbuffer<'a>(self, renderbuffer: &'a mut Renderbuffer)
        -> (
            RenderbufferBinding<'a>,
            ContextOf<AB, EAB, P, FB, (), TU>
        )
        where RB: BorrowMut<RenderbufferBinder>
    {
        let (mut renderbuffer_binder, gl) = self.split_renderbuffer();
        (renderbuffer_binder.borrow_mut().bind(renderbuffer), gl)
    }
}

gl_enum! {
    pub gl_enum RenderbufferTarget {
        Renderbuffer as RENDERBUFFER = gl::RENDERBUFFER
    }
}

pub struct RenderbufferBinding<'a> {
    phantom: PhantomData<&'a mut Renderbuffer>
}

impl<'a> RenderbufferBinding<'a> {
    fn target(&self) -> RenderbufferTarget {
        RenderbufferTarget::Renderbuffer
    }

    pub fn storage(&mut self,
                   format: RenderbufferFormat,
                   width: u32,
                   height: u32)
    {
        unsafe {
            gl::RenderbufferStorage(self.target().gl_enum(),
                                    format.gl_enum(),
                                    width as GLint,
                                    height as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER` or `internalformat` is not an accepted format",
                GLError::InvalidValue => "`width` or `height` is less than zero or greater than `GL_MAX_RENDERBUFFER_SIZE`",
                GLError::OutOfMemory => "Unable to allocate enough memory for requested size",
                GLError::InvalidOperation => "Renderbuffer object 0 is bound",
                _ => "Unknown error"
            }
        }
    }
}

pub struct RenderbufferBinder;
impl RenderbufferBinder {
    pub fn bind<'a>(&mut self, renderbuffer: &'a mut Renderbuffer)
        -> RenderbufferBinding<'a>
    {
        let binding = RenderbufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindRenderbuffer(binding.target().gl_enum(),
                                 renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Mark `Context.gen_renderbuffer()` as unsafe<commit_after>use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use image_data::{RenderbufferFormat};
use types::GLError;

pub struct Renderbuffer {
    gl_id: GLuint
}

impl Renderbuffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Renderbuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteRenderbuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

pub struct RenderbufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a,
           RB: 'a + BorrowMut<RenderbufferBinder>,
           TU: 'a
{
    gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>,
    storage_params: Option<(RenderbufferFormat, u32, u32)>
}

impl<'a, AB, EAB, P, FB, RB, TU> RenderbufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a,
           RB: 'a + BorrowMut<RenderbufferBinder>,
           TU: 'a
{
    fn new(gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>) -> Self {
        RenderbufferBuilder {
            gl: gl,
            storage_params: None
        }
    }

    pub fn storage(mut self,
                   format: RenderbufferFormat,
                   width: u32,
                   height: u32)
        -> Self
    {
        self.storage_params = Some((format, width, height));
        self
    }

    pub fn try_unwrap(self) -> Result<Renderbuffer, GLError> {
        let gl = self.gl.borrowed_mut();
        let mut rbo = unsafe { gl.gen_renderbuffer() };

        match self.storage_params {
            Some((format, width, height)) => {
                {
                    let (mut gl_rbo, _) = gl.bind_renderbuffer(&mut rbo);
                    gl_rbo.storage(format, width, height);
                }

                Ok(rbo)
            },
            None => {
                let msg = "Error building renderbuffer: no format or dimensions provided";
                Err(GLError::Message(msg.to_owned()))
            }
        }
    }

    pub fn unwrap(self) -> Renderbuffer {
        self.try_unwrap().unwrap()
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn build_renderbuffer<'a>(&'a mut self)
        -> RenderbufferBuilder<'a, AB, EAB, P, FB, RB, TU>
        where RB: BorrowMut<RenderbufferBinder>
    {
        RenderbufferBuilder::new(self)
    }

    pub unsafe fn gen_renderbuffer(&self) -> Renderbuffer {
        let mut id : GLuint = 0;

        gl::GenRenderbuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Renderbuffer {
            gl_id: id
        }
    }

    pub fn bind_renderbuffer<'a>(self, renderbuffer: &'a mut Renderbuffer)
        -> (
            RenderbufferBinding<'a>,
            ContextOf<AB, EAB, P, FB, (), TU>
        )
        where RB: BorrowMut<RenderbufferBinder>
    {
        let (mut renderbuffer_binder, gl) = self.split_renderbuffer();
        (renderbuffer_binder.borrow_mut().bind(renderbuffer), gl)
    }
}

gl_enum! {
    pub gl_enum RenderbufferTarget {
        Renderbuffer as RENDERBUFFER = gl::RENDERBUFFER
    }
}

pub struct RenderbufferBinding<'a> {
    phantom: PhantomData<&'a mut Renderbuffer>
}

impl<'a> RenderbufferBinding<'a> {
    fn target(&self) -> RenderbufferTarget {
        RenderbufferTarget::Renderbuffer
    }

    pub fn storage(&mut self,
                   format: RenderbufferFormat,
                   width: u32,
                   height: u32)
    {
        unsafe {
            gl::RenderbufferStorage(self.target().gl_enum(),
                                    format.gl_enum(),
                                    width as GLint,
                                    height as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER` or `internalformat` is not an accepted format",
                GLError::InvalidValue => "`width` or `height` is less than zero or greater than `GL_MAX_RENDERBUFFER_SIZE`",
                GLError::OutOfMemory => "Unable to allocate enough memory for requested size",
                GLError::InvalidOperation => "Renderbuffer object 0 is bound",
                _ => "Unknown error"
            }
        }
    }
}

pub struct RenderbufferBinder;
impl RenderbufferBinder {
    pub fn bind<'a>(&mut self, renderbuffer: &'a mut Renderbuffer)
        -> RenderbufferBinding<'a>
    {
        let binding = RenderbufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindRenderbuffer(binding.target().gl_enum(),
                                 renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>


<commit_before>/*
src/renderer/mod.rs, 2017-07-17

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

mod texture;
mod shader;

use gl::buffer::*;
use gl::texture::*;

use gl::gl_raw;

use cgmath::{Vector3, Matrix4};
use cgmath;

use renderer::texture::Textures;
use renderer::shader::*;

use sdl2::VideoSubsystem;
use sdl2::video::{Window};
use sdl2::video::{GLProfile, GLContext};

use logic::{GameObject, Logic};

pub struct OpenGLRenderer {
    video_system: VideoSubsystem,
    window: Window,
    context: GLContext,
    textures: [TextureRGBA; Textures::TextureCount as usize],
    texture_shader: TextureShader,
    color_shader: ColorShader,
    square: VertexArray,
}

pub trait Renderer {
    fn start(&mut self);
    fn render(&mut self, &Logic);
    fn end(&mut self);
}

impl Renderer for OpenGLRenderer {

    fn start(&mut self) {
        unsafe {
            gl_raw::Clear(gl_raw::COLOR_BUFFER_BIT);
        }
    }

    fn render(&mut self, logic: &Logic) {
        self.texture_shader.use_program();

        self.textures[Textures::Player as usize].bind();

        let size = 1.5;
        let width = 4.0 * size;
        let height = 3.0 * size;
        let projection_matrix = cgmath::ortho::<f32>(-width, width, -height, height, 1.0, -1.0);

        self.texture_shader.send_uniform_data(logic.get_player().model_matrix(), &projection_matrix);

        self.square.draw();

        self.color_shader.use_program();

        let color = Vector3::new(0.0,0.0,1.0);
        for laser in logic.get_player().get_lasers() {
            self.color_shader.send_uniform_data(laser.model_matrix(), &projection_matrix, &color);
            self.square.draw();
        }
    }

    fn end(&mut self) {
        self.window.gl_swap_window();
    }
}

impl OpenGLRenderer {
    pub fn new(video_system: VideoSubsystem) -> OpenGLRenderer {
        let window = video_system.window("Space Boss Battles", 640,480).opengl().build().expect("window creation failed");

        #[cfg(feature = "gles")]
        {
            let gl_attr = video_system.gl_attr();
            gl_attr.set_context_profile(GLProfile::GLES);
            gl_attr.set_context_version(2,0);
        }

        #[cfg(not(feature = "gles"))]
        {
            let gl_attr = video_system.gl_attr();
            gl_attr.set_context_profile(GLProfile::Core);
            gl_attr.set_context_version(3,3);
        }

        let context = window.gl_create_context().expect("opengl context creation failed");
        gl_raw::load_with(|name| video_system.gl_get_proc_address(name) as *const _);

        window.gl_make_current(&context).expect("couldn't set opengl context to current thread");

        let texture_shader = TextureShader::new();
        let color_shader = ColorShader::new();

        //video_system.gl_set_swap_interval(0);

        unsafe {
            gl_raw::Viewport(0,0,640,480);
            gl_raw::ClearColor(0.0,0.0,0.0,1.0);
        }

        let textures = Textures::load_all();
        let square = create_square();

        OpenGLRenderer {video_system, window, context, texture_shader, color_shader, textures, square}
    }

}

fn create_square() -> VertexArray {
    let mut square = VertexArray::new(6);

    let size : f32 = 0.5;

    let vertex_data: [f32; 18]  = [
                size, -size, 0.0,
                size, size, 0.0,
                -size, size, 0.0,

                size, -size, 0.0,
                -size, size, 0.0,
                -size, -size, 0.0,
    ];
    let texture_coordinates_data: [f32; 12]  = [
                1.0, 0.0,
                1.0, 1.0,
                0.0, 1.0,

                1.0, 0.0,
                0.0, 1.0,
                0.0, 0.0,
    ];

    square.add_static_buffer(&vertex_data, 3, 0);
    square.add_static_buffer(&texture_coordinates_data, 2, 1);

    square
}<commit_msg>Check OpenGL errors and print OpenGL version string<commit_after>/*
src/renderer/mod.rs, 2017-07-18

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

mod texture;
mod shader;

use gl::buffer::*;
use gl::texture::*;

use gl::gl_raw;
use gl;

use cgmath::{Vector3, Matrix4};
use cgmath;

use renderer::texture::Textures;
use renderer::shader::*;

use sdl2::VideoSubsystem;
use sdl2::video::{Window};
use sdl2::video::{GLProfile, GLContext};

use logic::{GameObject, Logic};

pub struct OpenGLRenderer {
    video_system: VideoSubsystem,
    window: Window,
    context: GLContext,
    textures: [TextureRGBA; Textures::TextureCount as usize],
    texture_shader: TextureShader,
    color_shader: ColorShader,
    square: VertexArray,
}

pub trait Renderer {
    fn start(&mut self);
    fn render(&mut self, &Logic);
    fn end(&mut self);
}

impl Renderer for OpenGLRenderer {

    fn start(&mut self) {
        unsafe {
            gl_raw::Clear(gl_raw::COLOR_BUFFER_BIT);
        }
    }

    fn render(&mut self, logic: &Logic) {
        self.texture_shader.use_program();

        self.textures[Textures::Player as usize].bind();

        let size = 1.5;
        let width = 4.0 * size;
        let height = 3.0 * size;
        let projection_matrix = cgmath::ortho::<f32>(-width, width, -height, height, 1.0, -1.0);

        self.texture_shader.send_uniform_data(logic.get_player().model_matrix(), &projection_matrix);

        self.square.draw();

        self.color_shader.use_program();

        let color = Vector3::new(0.0,0.0,1.0);
        for laser in logic.get_player().get_lasers() {
            self.color_shader.send_uniform_data(laser.model_matrix(), &projection_matrix, &color);
            self.square.draw();
        }
    }

    fn end(&mut self) {
        self.window.gl_swap_window();

        while let Err(error) = gl::GLError::get_error() {
            println!("OpenGL error: {:?}", error);
        }
    }
}

impl OpenGLRenderer {
    pub fn new(video_system: VideoSubsystem) -> OpenGLRenderer {
        let window = video_system.window("Space Boss Battles", 640,480).opengl().build().expect("window creation failed");

        #[cfg(feature = "gles")]
        {
            let gl_attr = video_system.gl_attr();
            gl_attr.set_context_profile(GLProfile::GLES);
            gl_attr.set_context_version(2,0);
        }

        #[cfg(not(feature = "gles"))]
        {
            let gl_attr = video_system.gl_attr();
            gl_attr.set_context_profile(GLProfile::Core);
            gl_attr.set_context_version(3,3);
        }

        let context = window.gl_create_context().expect("opengl context creation failed");
        gl_raw::load_with(|name| video_system.gl_get_proc_address(name) as *const _);

        window.gl_make_current(&context).expect("couldn't set opengl context to current thread");

        let texture_shader = TextureShader::new();
        let color_shader = ColorShader::new();

        //video_system.gl_set_swap_interval(0);

        unsafe {
            gl_raw::Viewport(0,0,640,480);
            gl_raw::ClearColor(0.0,0.0,0.0,1.0);
        }

        let textures = Textures::load_all();
        let square = create_square();

        println!("OpenGL version: {:?}", gl::get_version_string());

        OpenGLRenderer {video_system, window, context, texture_shader, color_shader, textures, square}
    }

}

fn create_square() -> VertexArray {
    let mut square = VertexArray::new(6);

    let size : f32 = 0.5;

    let vertex_data: [f32; 18]  = [
                size, -size, 0.0,
                size, size, 0.0,
                -size, size, 0.0,

                size, -size, 0.0,
                -size, size, 0.0,
                -size, -size, 0.0,
    ];
    let texture_coordinates_data: [f32; 12]  = [
                1.0, 0.0,
                1.0, 1.0,
                0.0, 1.0,

                1.0, 0.0,
                0.0, 1.0,
                0.0, 0.0,
    ];

    square.add_static_buffer(&vertex_data, 3, 0);
    square.add_static_buffer(&texture_coordinates_data, 2, 1);

    square
}<|endoftext|>


<commit_before>extern crate rand;
extern crate perlin;

use perlin::index::Index;
use perlin::index::boolean_index::*;
use perlin::storage::RamStorage;
use perlin::storage::FsStorage;

#[test]
fn build_and_query_persistent_index() {
    let doc1 = vec![0, 5, 10, 15, 20];
    let doc2 = vec![0, 7, 14, 21, 28];
    let doc3 = vec![0, 3, 6, 9, 12];
    let doc4 = vec![0 as u32, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];

    let folder = std::env::temp_dir().join("bq_persistent_test");

    assert!(std::fs::create_dir_all(folder.as_path()).is_ok());

    let index = IndexBuilder::<u32, FsStorage<_>>::new()
        .persist(folder.as_path())
        .create_persistent(vec![doc1.into_iter(), doc2.into_iter(), doc3.into_iter(), doc4.into_iter()].into_iter())
        .unwrap();

    let pos_query = QueryBuilder::in_order(vec![Some(10), Some(20)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![]);

    let pos_query = QueryBuilder::in_order(vec![Some(0), Some(7), Some(14)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![1]);

    let and_query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&and_query).collect::<Vec<_>>(),
               vec![2, 3]);

    let or_query = QueryBuilder::or(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&or_query).collect::<Vec<_>>(),
               vec![0, 1, 2, 3]);

    let index = IndexBuilder::<usize, FsStorage<_>>::new().persist(folder.as_path()).load().unwrap();

    let pos_query = QueryBuilder::in_order(vec![Some(10), Some(20)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![]);

    let pos_query = QueryBuilder::in_order(vec![Some(0), Some(7), Some(14)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![1]);

    let and_query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&and_query).collect::<Vec<_>>(),
               vec![2, 3]);

    let or_query = QueryBuilder::or(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&or_query).collect::<Vec<_>>(),
               vec![0, 1, 2, 3]);
}

#[derive(Hash, PartialOrd, Ord, PartialEq, Eq)]
enum Color {
    Red,
    Green,
    Blue,
}

#[test]
fn build_and_query_volatile_index() {
    let doc1 = vec![Color::Red, Color::Red, Color::Blue];
    let doc2 = vec![Color::Green, Color::Red, Color::Blue];
    let doc3 = vec![Color::Blue, Color::Blue, Color::Blue];

    let index = IndexBuilder::<_, RamStorage<_>>::new()
        .create(vec![doc1.into_iter(), doc2.into_iter(), doc3.into_iter()].into_iter())
        .unwrap();

    let pos_query = QueryBuilder::in_order(vec![Some(Color::Red), Some(Color::Blue)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(),
               vec![0, 1]);

    let pos_query = QueryBuilder::in_order(vec![Some(Color::Red), Some(Color::Red), Some(Color::Blue)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![0]);

    let and_query = QueryBuilder::and(QueryBuilder::atoms(vec![Color::Green, Color::Blue])).build();
    assert_eq!(index.execute_query(&and_query).collect::<Vec<_>>(), vec![1]);

    let or_query = QueryBuilder::or(QueryBuilder::atoms(vec![Color::Green, Color::Blue])).build();
    assert_eq!(index.execute_query(&or_query).collect::<Vec<_>>(),
               vec![0, 1, 2]);
}

mod random_data {

    use perlin::index::boolean_index::{QueryBuilder, IndexBuilder, BooleanIndex};
    use perlin::storage::RamStorage;
    use perlin::index::Index;

    use rand;
    use rand::{XorShiftRng, Rng};

    #[allow(dead_code)]
    pub fn prepare_index(documents: usize, document_size: usize) -> BooleanIndex<usize> {
        println!("Building Collection!");
        println!("Voc size: {}", voc_size(45, 0.5, documents * document_size));
        let collection: Vec<Vec<usize>> = (0..documents)
            .map(|_| ZipfGenerator::new(voc_size(45, 0.5, documents * document_size)).take(document_size).collect())
            .collect();
        println!("Preparing index with {} documents each {} terms",
                 documents,
                 document_size);
        let index = IndexBuilder::<_, RamStorage<_>>::new()
            .create(collection.iter().map(|i| i.iter().cloned()).inspect(|i| println!("{:?}", i)));
        println!("Done!");
        index.unwrap()
    }

    // Implementation of Heaps' Law
    pub fn voc_size(k: usize, b: f64, tokens: usize) -> usize {
        ((k as f64) * (tokens as f64).powf(b)) as usize
    }

    #[derive(Clone)]
    pub struct ZipfGenerator {
        voc_size: usize,
        factor: f32,
        acc_probs: Vec<f32>,
        rng: XorShiftRng,
    }

    impl ZipfGenerator {
        pub fn new(voc_size: usize) -> Self {
            let mut res = ZipfGenerator {
                voc_size: voc_size,
                factor: (1.78 * voc_size as f32).ln(),
                acc_probs: Vec::with_capacity(voc_size),
                rng: rand::weak_rng(),
            };
            let mut acc = 0.0;
            for i in 1..voc_size {
                acc += 1.0 / (i as f32 * res.factor);
                res.acc_probs.push(acc);
            }
            res.acc_probs.push(1f32);
            res
        }
    }

    impl<'a> Iterator for &'a mut ZipfGenerator {
        type Item = usize;

        fn next(&mut self) -> Option<Self::Item> {
            let dice = self.rng.next_f32();
            let result = match self.acc_probs.binary_search_by(|v| v.partial_cmp(&dice).unwrap()) {
                Ok(index) | Err(index) => index,
            };
            Some(result)
        }
    }

    #[test]
    fn small_collection() {
        let index = prepare_index(10, 50);
        index.execute_query(&QueryBuilder::atom(4).build()).count();
    }

    #[test]
    fn large_collection() {
        let index = prepare_index(50, 50);
        index.execute_query(&QueryBuilder::atom(4).build()).count();
    }

    // #[test]
    // fn huge_collection() {
    //     let index = prepare_index(1000, 5000);
    //     index.execute_query(&QueryBuilder::atom(4).build()).count();
    // }

}
<commit_msg>removed unit test with random data<commit_after>extern crate rand;
extern crate perlin;

use perlin::index::Index;
use perlin::index::boolean_index::*;
use perlin::storage::RamStorage;
use perlin::storage::FsStorage;

#[test]
fn build_and_query_persistent_index() {
    let doc1 = vec![0, 5, 10, 15, 20];
    let doc2 = vec![0, 7, 14, 21, 28];
    let doc3 = vec![0, 3, 6, 9, 12];
    let doc4 = vec![0 as u32, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];

    let folder = std::env::temp_dir().join("bq_persistent_test");

    assert!(std::fs::create_dir_all(folder.as_path()).is_ok());

    let index = IndexBuilder::<u32, FsStorage<_>>::new()
        .persist(folder.as_path())
        .create_persistent(vec![doc1.into_iter(), doc2.into_iter(), doc3.into_iter(), doc4.into_iter()].into_iter())
        .unwrap();

    let pos_query = QueryBuilder::in_order(vec![Some(10), Some(20)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![]);

    let pos_query = QueryBuilder::in_order(vec![Some(0), Some(7), Some(14)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![1]);

    let and_query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&and_query).collect::<Vec<_>>(),
               vec![2, 3]);

    let or_query = QueryBuilder::or(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&or_query).collect::<Vec<_>>(),
               vec![0, 1, 2, 3]);

    let index = IndexBuilder::<usize, FsStorage<_>>::new().persist(folder.as_path()).load().unwrap();

    let pos_query = QueryBuilder::in_order(vec![Some(10), Some(20)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![]);

    let pos_query = QueryBuilder::in_order(vec![Some(0), Some(7), Some(14)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![1]);

    let and_query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&and_query).collect::<Vec<_>>(),
               vec![2, 3]);

    let or_query = QueryBuilder::or(QueryBuilder::atoms(vec![0, 6, 12])).build();
    assert_eq!(index.execute_query(&or_query).collect::<Vec<_>>(),
               vec![0, 1, 2, 3]);
}

#[derive(Hash, PartialOrd, Ord, PartialEq, Eq)]
enum Color {
    Red,
    Green,
    Blue,
}

#[test]
fn build_and_query_volatile_index() {
    let doc1 = vec![Color::Red, Color::Red, Color::Blue];
    let doc2 = vec![Color::Green, Color::Red, Color::Blue];
    let doc3 = vec![Color::Blue, Color::Blue, Color::Blue];

    let index = IndexBuilder::<_, RamStorage<_>>::new()
        .create(vec![doc1.into_iter(), doc2.into_iter(), doc3.into_iter()].into_iter())
        .unwrap();

    let pos_query = QueryBuilder::in_order(vec![Some(Color::Red), Some(Color::Blue)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(),
               vec![0, 1]);

    let pos_query = QueryBuilder::in_order(vec![Some(Color::Red), Some(Color::Red), Some(Color::Blue)]).build();
    assert_eq!(index.execute_query(&pos_query).collect::<Vec<_>>(), vec![0]);

    let and_query = QueryBuilder::and(QueryBuilder::atoms(vec![Color::Green, Color::Blue])).build();
    assert_eq!(index.execute_query(&and_query).collect::<Vec<_>>(), vec![1]);

    let or_query = QueryBuilder::or(QueryBuilder::atoms(vec![Color::Green, Color::Blue])).build();
    assert_eq!(index.execute_query(&or_query).collect::<Vec<_>>(),
               vec![0, 1, 2]);
}
<|endoftext|>


<commit_before>#![cfg(target_os = "macos")]

use CreationError;
use CreationError::OsError;
use ContextError;
use GlAttributes;
use GlContext;
use PixelFormat;
use PixelFormatRequirements;
use Robustness;
use WindowAttributes;
use os::macos::ActivationPolicy;

use objc::runtime::{BOOL, NO};

use cgl::{CGLEnable, kCGLCECrashOnRemovedFunctions, CGLSetParameter, kCGLCPSurfaceOpacity};

use cocoa::base::{id, nil};
use cocoa::foundation::NSAutoreleasePool;
use cocoa::appkit::{self, NSOpenGLContext, NSOpenGLPixelFormat};

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::collections::HashMap;
use std::str::FromStr;
use std::ops::Deref;
use std::sync::{Arc, Mutex, Weak};

use libc;

use winit;
use winit::os::macos::WindowExt;
pub use winit::{MonitorId, NativeMonitorId, get_available_monitors, get_primary_monitor};
pub use self::headless::HeadlessContext;
pub use self::headless::PlatformSpecificHeadlessBuilderAttributes;

mod headless;
mod helpers;

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
    pub activation_policy: ActivationPolicy,
}

pub struct Window {
    // A handle to the GL context associated with this window.
    context: Arc<Context>,
    // The Window must store a handle to the map in order to remove its own context when dropped.
    contexts: Arc<ContextMap>,
    winit_window: winit::Window,
}

pub struct EventsLoop {
    winit_events_loop: winit::EventsLoop,
    window_contexts: Mutex<Weak<ContextMap>>,
}

struct Context {
    // NSOpenGLContext
    gl: IdRef,
    pixel_format: PixelFormat,
}

struct ContextMap {
    map: Mutex<HashMap<winit::WindowId, Weak<Context>>>,
}

unsafe impl Send for ContextMap {}
unsafe impl Sync for ContextMap {}

impl EventsLoop {
    /// Builds a new events loop.
    pub fn new() -> EventsLoop {
        EventsLoop {
            winit_events_loop: winit::EventsLoop::new(),
            window_contexts: Mutex::new(Weak::new()),
        }
    }

    fn handle_event(&self, event: &winit::Event) {
        match *event {
            winit::Event::WindowEvent { window_id, ref event } => match *event {

                // If a `Resized` event was received for a window, update the GL context for that
                // window but only if that window is still alive.
                winit::WindowEvent::Resized(..) => {
                    if let Some(window_contexts) = self.window_contexts.lock().unwrap().upgrade() {
                        if let Some(context) = window_contexts.map.lock().unwrap()[&window_id].upgrade() {
                            unsafe { context.gl.update(); }
                        }
                    }
                },

                // If a `Closed` event was received for a window, remove the associated context
                // from the map.
                winit::WindowEvent::Closed => {
                    if let Some(window_contexts) = self.window_contexts.lock().unwrap().upgrade() {
                        window_contexts.map.lock().unwrap().remove(&window_id);
                    }
                },

                _ => (),
            },
        }
    }

    /// Fetches all the events that are pending, calls the callback function for each of them,
    /// and returns.
    #[inline]
    pub fn poll_events<F>(&self, mut callback: F)
        where F: FnMut(winit::Event)
    {
        self.winit_events_loop.poll_events(|event| {
            self.handle_event(&event);
            callback(event);
        });
    }

    /// Runs forever until `interrupt()` is called. Whenever an event happens, calls the callback.
    #[inline]
    pub fn run_forever<F>(&self, mut callback: F)
        where F: FnMut(winit::Event)
    {
        self.winit_events_loop.run_forever(|event| {
            self.handle_event(&event);
            callback(event);
        })
    }

    /// If we called `run_forever()`, stops the process of waiting for events.
    #[inline]
    pub fn interrupt(&self) {
        self.winit_events_loop.interrupt()
    }
}

unsafe impl Send for Window {}
unsafe impl Sync for Window {}

impl Window {

    pub fn new(events_loop: &EventsLoop,
               _win_attribs: &WindowAttributes,
               pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&Window>,
               _pl_attribs: &PlatformSpecificWindowBuilderAttributes,
               winit_builder: winit::WindowBuilder)
               -> Result<Self, CreationError> {
        if opengl.sharing.is_some() {
            unimplemented!()
        }

        match opengl.robustness {
            Robustness::RobustNoResetNotification |
            Robustness::RobustLoseContextOnReset => {
                return Err(CreationError::RobustnessNotSupported);
            }
            _ => (),
        }

        let transparent = winit_builder.window.transparent;
        let winit_window = winit_builder.build(&events_loop.winit_events_loop).unwrap();
        let window_id = winit_window.id();
        let view = winit_window.get_nsview() as id;
        let context = match Context::new(view, pf_reqs, opengl, transparent) {
            Ok(context) => Arc::new(context),
            Err(e) => {
                return Err(OsError(format!("Couldn't create OpenGL context: {}", e)));
            }
        };
        let weak_context = Arc::downgrade(&context);

        let new_window = |window_contexts| Window {
            context: context,
            winit_window: winit_window,
            contexts: window_contexts,
        };

        // If a `ContextMap` exists, insert the context for this new window and return it.
        if let Some(window_contexts) = events_loop.window_contexts.lock().unwrap().upgrade() {
            window_contexts.map.lock().unwrap().insert(window_id, weak_context);
            return Ok(new_window(window_contexts));
        }

        // If there is not yet a `ContextMap`, this must be the first window so we must create it.
        let mut map = HashMap::new();
        map.insert(window_id, weak_context);
        let window_contexts = Arc::new(ContextMap { map: Mutex::new(map) });
        *events_loop.window_contexts.lock().unwrap() = Arc::downgrade(&window_contexts);
        Ok(new_window(window_contexts))
    }

    pub fn set_title(&self, title: &str) {
        self.winit_window.set_title(title)
    }

    #[inline]
    pub fn as_winit_window(&self) -> &winit::Window {
        &self.winit_window
    }

    #[inline]
    pub fn as_winit_window_mut(&mut self) -> &mut winit::Window {
        &mut self.winit_window
    }

    pub fn show(&self) {
        self.winit_window.show()
    }

    pub fn hide(&self) {
        self.winit_window.hide()
    }

    pub fn get_position(&self) -> Option<(i32, i32)> {
        self.winit_window.get_position()
    }

    pub fn set_position(&self, x: i32, y: i32) {
        self.winit_window.set_position(x, y)
    }

    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        self.winit_window.get_inner_size()
    }

    pub fn get_inner_size_points(&self) -> Option<(u32, u32)> {
        self.winit_window.get_inner_size()
    }

    pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> {
        self.winit_window.get_inner_size().map(|(x, y)| {
            let hidpi = self.hidpi_factor();
            ((x as f32 * hidpi) as u32, (y as f32 * hidpi) as u32)
        })
    }

    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.winit_window.get_outer_size()
    }

    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.winit_window.set_inner_size(x, y)
    }

    #[allow(deprecated)]
    pub unsafe fn platform_display(&self) -> *mut libc::c_void {
        self.winit_window.platform_display()
    }

    #[allow(deprecated)]
    pub unsafe fn platform_window(&self) -> *mut libc::c_void {
        self.winit_window.platform_window()
    }

    pub fn set_cursor(&self, cursor: winit::MouseCursor) {
        self.winit_window.set_cursor(cursor);
    }

    pub fn hidpi_factor(&self) -> f32 {
        self.winit_window.hidpi_factor()
    }

    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        self.winit_window.set_cursor_position(x, y)
    }

    pub fn set_cursor_state(&self, state: winit::CursorState) -> Result<(), String> {
        self.winit_window.set_cursor_state(state)
    }

    pub fn id(&self) -> winit::WindowId {
        self.winit_window.id()
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        self.contexts.map.lock().unwrap().remove(&self.id());
    }
}

impl Context {
    fn new(view: id,
           pf_reqs: &PixelFormatRequirements,
           opengl: &GlAttributes<&Window>,
           transparent: bool) -> Result<Self, CreationError>
    {
        let attributes = try!(helpers::build_nsattributes(pf_reqs, opengl));
        unsafe {
            let pixelformat = IdRef::new(NSOpenGLPixelFormat::alloc(nil)
                .initWithAttributes_(&attributes));

            if let Some(pixelformat) = pixelformat.non_nil() {

                // TODO: Add context sharing
                let context = IdRef::new(NSOpenGLContext::alloc(nil)
                    .initWithFormat_shareContext_(*pixelformat, nil));

                if let Some(cxt) = context.non_nil() {
                    let pf = {
                        let get_attr = |attrib: appkit::NSOpenGLPixelFormatAttribute| -> i32 {
                            let mut value = 0;

                            NSOpenGLPixelFormat::getValues_forAttribute_forVirtualScreen_(
                                *pixelformat,
                                &mut value,
                                attrib,
                                NSOpenGLContext::currentVirtualScreen(*cxt));

                            value
                        };

                        PixelFormat {
                            hardware_accelerated: get_attr(appkit::NSOpenGLPFAAccelerated) != 0,
                            color_bits: (get_attr(appkit::NSOpenGLPFAColorSize) - get_attr(appkit::NSOpenGLPFAAlphaSize)) as u8,
                            alpha_bits: get_attr(appkit::NSOpenGLPFAAlphaSize) as u8,
                            depth_bits: get_attr(appkit::NSOpenGLPFADepthSize) as u8,
                            stencil_bits: get_attr(appkit::NSOpenGLPFAStencilSize) as u8,
                            stereoscopy: get_attr(appkit::NSOpenGLPFAStereo) != 0,
                            double_buffer: get_attr(appkit::NSOpenGLPFADoubleBuffer) != 0,
                            multisampling: if get_attr(appkit::NSOpenGLPFAMultisample) > 0 {
                                Some(get_attr(appkit::NSOpenGLPFASamples) as u16)
                            } else {
                                None
                            },
                            srgb: true,
                        }
                    };

                    cxt.setView_(view);
                    let value = if opengl.vsync { 1 } else { 0 };
                    cxt.setValues_forParameter_(&value, appkit::NSOpenGLContextParameter::NSOpenGLCPSwapInterval);

                    if transparent {
                        let mut opacity = 0;
                        CGLSetParameter(cxt.CGLContextObj() as *mut _, kCGLCPSurfaceOpacity, &mut opacity);
                    }

                    CGLEnable(cxt.CGLContextObj() as *mut _, kCGLCECrashOnRemovedFunctions);

                    Ok(Context { gl: cxt, pixel_format: pf })
                } else {
                    Err(CreationError::NotSupported)
                }
            } else {
                Err(CreationError::NoAvailablePixelFormat)
            }
        }
    }
}

impl GlContext for Window {
    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        let _: () = msg_send![*self.context.gl, update];
        self.context.gl.makeCurrentContext();
        Ok(())
    }

    #[inline]
    fn is_current(&self) -> bool {
        unsafe {
            let current = NSOpenGLContext::currentContext(nil);
            if current != nil {
                let is_equal: BOOL = msg_send![current, isEqual:*self.context.gl];
                is_equal != NO
            } else {
                false
            }
        }
    }

    fn get_proc_address(&self, addr: &str) -> *const () {
        let symbol_name: CFString = FromStr::from_str(addr).unwrap();
        let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
        let framework =
            unsafe { CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef()) };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const _
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        unsafe {
            let pool = NSAutoreleasePool::new(nil);
            self.context.gl.flushBuffer();
            let _: () = msg_send![pool, release];
        }
        Ok(())
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        ::Api::OpenGl
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        self.context.pixel_format.clone()
    }
}

struct IdRef(id);

impl IdRef {
    fn new(i: id) -> IdRef {
        IdRef(i)
    }

    #[allow(dead_code)]
    fn retain(i: id) -> IdRef {
        if i != nil {
            let _: id = unsafe { msg_send![i, retain] };
        }
        IdRef(i)
    }

    fn non_nil(self) -> Option<IdRef> {
        if self.0 == nil { None } else { Some(self) }
    }
}

impl Drop for IdRef {
    fn drop(&mut self) {
        if self.0 != nil {
            let _: () = unsafe { msg_send![self.0, release] };
        }
    }
}

impl Deref for IdRef {
    type Target = id;
    fn deref<'a>(&'a self) -> &'a id {
        &self.0
    }
}

impl Clone for IdRef {
    fn clone(&self) -> IdRef {
        if self.0 != nil {
            let _: id = unsafe { msg_send![self.0, retain] };
        }
        IdRef(self.0)
    }
}
<commit_msg>WIP - Begin updating macos platform to Context redesign. Untested yet.<commit_after>#![cfg(target_os = "macos")]

use CreationError;
use CreationError::OsError;
use ContextError;
use GlAttributes;
use GlContext;
use PixelFormat;
use PixelFormatRequirements;
use Robustness;
use WindowAttributes;
use os::macos::ActivationPolicy;

use objc::runtime::{BOOL, NO};

use cgl::{CGLEnable, kCGLCECrashOnRemovedFunctions, CGLSetParameter, kCGLCPSurfaceOpacity};

use cocoa::base::{id, nil};
use cocoa::foundation::NSAutoreleasePool;
use cocoa::appkit::{self, NSOpenGLContext, NSOpenGLPixelFormat};

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::collections::HashMap;
use std::str::FromStr;
use std::ops::Deref;
use std::sync::{Arc, Mutex, Weak};

use libc;

use winit;
use winit::os::macos::WindowExt;
pub use winit::{MonitorId, NativeMonitorId, get_available_monitors, get_primary_monitor};
pub use self::headless::HeadlessContext;
pub use self::headless::PlatformSpecificHeadlessBuilderAttributes;

mod headless;
mod helpers;

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
    pub activation_policy: ActivationPolicy,
}

pub struct Context {
    // NSOpenGLContext
    gl: IdRef,
    pixel_format: PixelFormat,
}

impl Context {

    pub fn new(
        window: &winit::Window,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
    ) -> Result<Self, CreationError>
    {
        if gl_attr.sharing.is_some() {
            unimplemented!()
        }

        match gl_attr.robustness {
            Robustness::RobustNoResetNotification |
            Robustness::RobustLoseContextOnReset => {
                return Err(CreationError::RobustnessNotSupported);
            }
            _ => (),
        }

        let window_id = window.id();
        let view = window.get_nsview() as id;

        let attributes = try!(helpers::build_nsattributes(pf_reqs, gl_attr));
        unsafe {
            let pixel_format = IdRef::new(NSOpenGLPixelFormat::alloc(nil)
                .initWithAttributes_(&attributes));
            let pixel_format = match pixel_format.non_nil() {
                None => return Err(CreationError::NoAvailablePixelFormat),
                Some(pf) => pf,
            };

            // TODO: Add context sharing
            let gl_context = IdRef::new(NSOpenGLContext::alloc(nil)
                .initWithFormat_shareContext_(*pixel_format, nil));
            let gl_context = match context.non_nil() {
                Some(gl_context) => gl_context,
                None => return Err(CreationError::NotSupported),
            };

            let pixel_format = {
                let get_attr = |attrib: appkit::NSOpenGLPixelFormatAttribute| -> i32 {
                    let mut value = 0;
                    NSOpenGLPixelFormat::getValues_forAttribute_forVirtualScreen_(
                        *pixel_format,
                        &mut value,
                        attrib,
                        NSOpenGLContext::currentVirtualScreen(*gl_context));
                    value
                };

                PixelFormat {
                    hardware_accelerated: get_attr(appkit::NSOpenGLPFAAccelerated) != 0,
                    color_bits: (get_attr(appkit::NSOpenGLPFAColorSize) - get_attr(appkit::NSOpenGLPFAAlphaSize)) as u8,
                    alpha_bits: get_attr(appkit::NSOpenGLPFAAlphaSize) as u8,
                    depth_bits: get_attr(appkit::NSOpenGLPFADepthSize) as u8,
                    stencil_bits: get_attr(appkit::NSOpenGLPFAStencilSize) as u8,
                    stereoscopy: get_attr(appkit::NSOpenGLPFAStereo) != 0,
                    double_buffer: get_attr(appkit::NSOpenGLPFADoubleBuffer) != 0,
                    multisampling: if get_attr(appkit::NSOpenGLPFAMultisample) > 0 {
                        Some(get_attr(appkit::NSOpenGLPFASamples) as u16)
                    } else {
                        None
                    },
                    srgb: true,
                }
            };

            gl_context.setView_(view);
            let value = if gl_attr.vsync { 1 } else { 0 };
            gl_context.setValues_forParameter_(&value, appkit::NSOpenGLContextParameter::NSOpenGLCPSwapInterval);

            if gl_attr.transparent {
                let mut opacity = 0;
                CGLSetParameter(gl_context.CGLContextObj() as *mut _, kCGLCPSurfaceOpacity, &mut opacity);
            }

            CGLEnable(gl_context.CGLContextObj() as *mut _, kCGLCECrashOnRemovedFunctions);

            Ok(Context { gl: gl_context, pixel_format: pixel_format })
        }
    }

    pub fn resize(&self, _width: u32, _height: u32) {
        self.gl.update();
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        let _: () = msg_send![*self.gl, update];
        self.gl.makeCurrentContext();
        Ok(())
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        unsafe {
            let current = NSOpenGLContext::currentContext(nil);
            if current != nil {
                let is_equal: BOOL = msg_send![current, isEqual:*self.gl];
                is_equal != NO
            } else {
                false
            }
        }
    }

    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let symbol_name: CFString = FromStr::from_str(addr).unwrap();
        let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
        let framework =
            unsafe { CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef()) };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const _
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        unsafe {
            let pool = NSAutoreleasePool::new(nil);
            self.gl.flushBuffer();
            let _: () = msg_send![pool, release];
        }
        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> ::Api {
        ::Api::OpenGl
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.pixel_format.clone()
    }
}

struct IdRef(id);

impl IdRef {
    fn new(i: id) -> IdRef {
        IdRef(i)
    }

    #[allow(dead_code)]
    fn retain(i: id) -> IdRef {
        if i != nil {
            let _: id = unsafe { msg_send![i, retain] };
        }
        IdRef(i)
    }

    fn non_nil(self) -> Option<IdRef> {
        if self.0 == nil { None } else { Some(self) }
    }
}

impl Drop for IdRef {
    fn drop(&mut self) {
        if self.0 != nil {
            let _: () = unsafe { msg_send![self.0, release] };
        }
    }
}

impl Deref for IdRef {
    type Target = id;
    fn deref<'a>(&'a self) -> &'a id {
        &self.0
    }
}

impl Clone for IdRef {
    fn clone(&self) -> IdRef {
        if self.0 != nil {
            let _: id = unsafe { msg_send![self.0, retain] };
        }
        IdRef(self.0)
    }
}
<|endoftext|>