<commit_before>use std::fmt;
use std::ops;

use super::Value;
use map::Map;

/// A type that can be used to index into a `serde_json::Value`. See the `get`
/// and `get_mut` methods of `Value`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_json`.
pub trait Index: private::Sealed {
    /// Return None if the key is not already in the array or object.
    #[doc(hidden)]
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;

    /// Return None if the key is not already in the array or object.
    #[doc(hidden)]
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;

    /// Panic if array index out of bounds. If key is not already in the object,
    /// insert it with a value of null. Panic if Value is a type that cannot be
    /// indexed into, except if Value is null then it can be treated as an empty
    /// object.
    #[doc(hidden)]
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}

impl Index for usize {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match *v {
            Value::Array(ref vec) => vec.get(*self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match *v {
            Value::Array(ref mut vec) => vec.get_mut(*self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        match *v {
            Value::Array(ref mut vec) => {
                let len = vec.len();
                vec.get_mut(*self)
                    .unwrap_or_else(
                        || {
                            panic!(
                                "cannot access index {} of JSON array of length {}",
                                self,
                                len
                            )
                        },
                    )
            }
            _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
        }
    }
}

impl Index for str {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match *v {
            Value::Object(ref map) => map.get(self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match *v {
            Value::Object(ref mut map) => map.get_mut(self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        if let Value::Null = *v {
            let mut map = Map::new();
            map.insert(self.to_owned(), Value::Null);
            *v = Value::Object(map);
        }
        match *v {
            Value::Object(ref mut map) => {
                // TODO: use entry() once LinkedHashMap supports entry()
                // https://github.com/contain-rs/linked-hash-map/issues/5
                if !map.contains_key(self) {
                    map.insert(self.to_owned(), Value::Null);
                }
                map.get_mut(self).unwrap()
            }
            _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
        }
    }
}

impl Index for String {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        self[..].index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        self[..].index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        self[..].index_or_insert(v)
    }
}

impl<'a, T: ?Sized> Index for &'a T
where
    T: Index,
{
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        (**self).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        (**self).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        (**self).index_or_insert(v)
    }
}

// Prevent users from implementing the Index trait.
mod private {
    pub trait Sealed {}
    impl Sealed for usize {}
    impl Sealed for str {}
    impl Sealed for String {}
    impl<'a, T: ?Sized> Sealed for &'a T
    where
        T: Sealed,
    {
    }
}

/// Used in panic messages.
struct Type<'a>(&'a Value);

impl<'a> fmt::Display for Type<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            Value::Null => formatter.write_str("null"),
            Value::Bool(_) => formatter.write_str("boolean"),
            Value::Number(_) => formatter.write_str("number"),
            Value::String(_) => formatter.write_str("string"),
            Value::Array(_) => formatter.write_str("array"),
            Value::Object(_) => formatter.write_str("object"),
        }
    }
}

// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like Vec and BTreeMap which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some JSON from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// value.as_array() and working with the Vec directly, or matching on
// Value::Array and getting the Vec directly. The Index impl means you can skip
// that and index directly into the thing using a concise syntax. You don't have
// to check the type, you don't have to check the len, it is all about what you
// expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: get and get_mut,
// as_array, or match. The value of this impl is that it adds a way of working
// with Value that is not well served by the existing approaches: concise and
// careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
    I: Index,
{
    type Output = Value;

    /// Index into a `serde_json::Value` using the syntax `value[0]` or
    /// `value["k"]`.
    ///
    /// Returns `Value::Null` if the type of `self` does not match the type of
    /// the index, for example if the index is a string and `self` is an array
    /// or a number. Also returns `Value::Null` if the given key does not exist
    /// in the map or the given index is not within the bounds of the array.
    ///
    /// For retrieving deeply nested values, you should have a look at the
    /// `Value::pointer` method.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let data = json!({
    ///     "x": {
    ///         "y": ["z", "zz"]
    ///     }
    /// });
    ///
    /// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
    /// assert_eq!(data["x"]["y"][0], json!("z"));
    ///
    /// assert_eq!(data["a"], json!(null)); // returns null for undefined values
    /// assert_eq!(data["a"]["b"], json!(null)); // does not panic
    /// # }
    /// ```
    fn index(&self, index: I) -> &Value {
        static NULL: Value = Value::Null;
        index.index_into(self).unwrap_or(&NULL)
    }
}

impl<I> ops::IndexMut<I> for Value
where
    I: Index,
{
    /// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
    /// `value["k"] = ...`.
    ///
    /// If the index is a number, the value must be an array of length bigger
    /// than the index. Indexing into a value that is not an array or an array
    /// that is too small will panic.
    ///
    /// If the index is a string, the value must be an object or null which is
    /// treated like an empty object. If the key is not already present in the
    /// object, it will be inserted with a value of null. Indexing into a value
    /// that is neither an object nor null will panic.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let mut data = json!({ "x": 0 });
    ///
    /// // replace an existing key
    /// data["x"] = json!(1);
    ///
    /// // insert a new key
    /// data["y"] = json!([false, false, false]);
    ///
    /// // replace an array value
    /// data["y"][0] = json!(true);
    ///
    /// // inserted a deeply nested key
    /// data["a"]["b"]["c"]["d"] = json!(true);
    ///
    /// println!("{}", data);
    /// # }
    /// ```
    fn index_mut(&mut self, index: I) -> &mut Value {
        index.index_or_insert(self)
    }
}
<commit_msg>Use the new linked-hash-map entry API<commit_after>use std::fmt;
use std::ops;

use super::Value;
use map::Map;

/// A type that can be used to index into a `serde_json::Value`. See the `get`
/// and `get_mut` methods of `Value`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_json`.
pub trait Index: private::Sealed {
    /// Return None if the key is not already in the array or object.
    #[doc(hidden)]
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;

    /// Return None if the key is not already in the array or object.
    #[doc(hidden)]
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;

    /// Panic if array index out of bounds. If key is not already in the object,
    /// insert it with a value of null. Panic if Value is a type that cannot be
    /// indexed into, except if Value is null then it can be treated as an empty
    /// object.
    #[doc(hidden)]
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}

impl Index for usize {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match *v {
            Value::Array(ref vec) => vec.get(*self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match *v {
            Value::Array(ref mut vec) => vec.get_mut(*self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        match *v {
            Value::Array(ref mut vec) => {
                let len = vec.len();
                vec.get_mut(*self)
                    .unwrap_or_else(
                        || {
                            panic!(
                                "cannot access index {} of JSON array of length {}",
                                self,
                                len
                            )
                        },
                    )
            }
            _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
        }
    }
}

impl Index for str {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match *v {
            Value::Object(ref map) => map.get(self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match *v {
            Value::Object(ref mut map) => map.get_mut(self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        if let Value::Null = *v {
            let mut map = Map::new();
            map.insert(self.to_owned(), Value::Null);
            *v = Value::Object(map);
        }
        match *v {
            Value::Object(ref mut map) => {
                map.entry(self.to_owned()).or_insert(Value::Null)
            }
            _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
        }
    }
}

impl Index for String {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        self[..].index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        self[..].index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        self[..].index_or_insert(v)
    }
}

impl<'a, T: ?Sized> Index for &'a T
where
    T: Index,
{
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        (**self).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        (**self).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        (**self).index_or_insert(v)
    }
}

// Prevent users from implementing the Index trait.
mod private {
    pub trait Sealed {}
    impl Sealed for usize {}
    impl Sealed for str {}
    impl Sealed for String {}
    impl<'a, T: ?Sized> Sealed for &'a T
    where
        T: Sealed,
    {
    }
}

/// Used in panic messages.
struct Type<'a>(&'a Value);

impl<'a> fmt::Display for Type<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            Value::Null => formatter.write_str("null"),
            Value::Bool(_) => formatter.write_str("boolean"),
            Value::Number(_) => formatter.write_str("number"),
            Value::String(_) => formatter.write_str("string"),
            Value::Array(_) => formatter.write_str("array"),
            Value::Object(_) => formatter.write_str("object"),
        }
    }
}

// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like Vec and BTreeMap which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some JSON from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// value.as_array() and working with the Vec directly, or matching on
// Value::Array and getting the Vec directly. The Index impl means you can skip
// that and index directly into the thing using a concise syntax. You don't have
// to check the type, you don't have to check the len, it is all about what you
// expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: get and get_mut,
// as_array, or match. The value of this impl is that it adds a way of working
// with Value that is not well served by the existing approaches: concise and
// careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
    I: Index,
{
    type Output = Value;

    /// Index into a `serde_json::Value` using the syntax `value[0]` or
    /// `value["k"]`.
    ///
    /// Returns `Value::Null` if the type of `self` does not match the type of
    /// the index, for example if the index is a string and `self` is an array
    /// or a number. Also returns `Value::Null` if the given key does not exist
    /// in the map or the given index is not within the bounds of the array.
    ///
    /// For retrieving deeply nested values, you should have a look at the
    /// `Value::pointer` method.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let data = json!({
    ///     "x": {
    ///         "y": ["z", "zz"]
    ///     }
    /// });
    ///
    /// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
    /// assert_eq!(data["x"]["y"][0], json!("z"));
    ///
    /// assert_eq!(data["a"], json!(null)); // returns null for undefined values
    /// assert_eq!(data["a"]["b"], json!(null)); // does not panic
    /// # }
    /// ```
    fn index(&self, index: I) -> &Value {
        static NULL: Value = Value::Null;
        index.index_into(self).unwrap_or(&NULL)
    }
}

impl<I> ops::IndexMut<I> for Value
where
    I: Index,
{
    /// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
    /// `value["k"] = ...`.
    ///
    /// If the index is a number, the value must be an array of length bigger
    /// than the index. Indexing into a value that is not an array or an array
    /// that is too small will panic.
    ///
    /// If the index is a string, the value must be an object or null which is
    /// treated like an empty object. If the key is not already present in the
    /// object, it will be inserted with a value of null. Indexing into a value
    /// that is neither an object nor null will panic.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let mut data = json!({ "x": 0 });
    ///
    /// // replace an existing key
    /// data["x"] = json!(1);
    ///
    /// // insert a new key
    /// data["y"] = json!([false, false, false]);
    ///
    /// // replace an array value
    /// data["y"][0] = json!(true);
    ///
    /// // inserted a deeply nested key
    /// data["a"]["b"]["c"]["d"] = json!(true);
    ///
    /// println!("{}", data);
    /// # }
    /// ```
    fn index_mut(&mut self, index: I) -> &mut Value {
        index.index_or_insert(self)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::io;
use std::collections::VecDeque;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::{self, task, Async, Poll};
use futures::future::Future;
use futures::sync::oneshot;

use capnp::{Error};

use serialize::{self, AsOutputSegments};

enum State<W, M> where W: io::Write, M: AsOutputSegments {
    Writing(serialize::Write<W, M>, oneshot::Sender<M>),
    BetweenWrites(W),
    Empty,
}

/// A queue of messages being written.
#[must_use = "futures do nothing unless polled"]
pub struct WriteQueue<W, M> where W: io::Write, M: AsOutputSegments {
    inner: Rc<RefCell<Inner<M>>>,
    state: State<W, M>,
}

struct Inner<M> {
    queue: VecDeque<(M, oneshot::Sender<M>)>,
    sender_count: usize,
    task: Option<task::Task>,

    // If set, then the queue has been requested to end, and we should complete the oneshot once
    // the queue has been emptied.
    end_notifier: Option<(Result<(), Error>, oneshot::Sender<()>)>
}

/// A handle that allows message to be sent to a `WriteQueue`.
pub struct Sender<M> where M: AsOutputSegments {
    inner: Weak<RefCell<Inner<M>>>,
}

impl <M> Clone for Sender<M> where M: AsOutputSegments {
    fn clone(&self) -> Sender<M> {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.borrow_mut().sender_count += 1;
            }
        }
        Sender { inner: self.inner.clone() }
    }
}

impl <M> Drop for Sender<M> where M: AsOutputSegments {
    fn drop(&mut self) {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.borrow_mut().sender_count -= 1;
            }
        }
    }
}

/// Creates a new WriteQueue that wraps the given writer.
pub fn write_queue<W, M>(writer: W) -> (Sender<M>, WriteQueue<W, M>)
    where W: io::Write, M: AsOutputSegments
{
    let inner = Rc::new(RefCell::new(Inner {
        queue: VecDeque::new(),
        task: None,
        sender_count: 1,
        end_notifier: None,
    }));

    let sender = Sender { inner: Rc::downgrade(&inner) };

    let queue = WriteQueue {
        inner: inner,
        state: State::BetweenWrites(writer),
    };

    (sender, queue)
}

impl <M> Sender<M> where M: AsOutputSegments + 'static {
    /// Enqueues a message to be written.
    pub fn send(&mut self, message: M) -> Box<Future<Item=M, Error=Error>> {
        let (complete, oneshot) = futures::oneshot();

        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                if rc_inner.borrow().end_notifier.is_some() {
                    drop(complete)
                } else {
                    rc_inner.borrow_mut().queue.push_back((message, complete));
                }

                match rc_inner.borrow_mut().task.take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }

        Box::new(
            oneshot.map_err(
                |oneshot::Canceled| Error::disconnected("WriteQueue has terminated".into())))
    }

    /// Returns the number of messages queued to be written, not including any in-progress write.
    pub fn len(&mut self) -> usize {
        match self.inner.upgrade() {
            None => 0,
            Some(rc_inner) => rc_inner.borrow().queue.len(),
        }

    }

    /// Commands the queue to stop writing messages once it is empty. After this method has been called,
    /// any new calls to `send()` will return a future that immediately resolves to an error.
    /// If the passed-in `result` is an error, then the `WriteQueue` will resolve to that error.
    pub fn terminate(&mut self, result: Result<(), Error>) -> Box<Future<Item=(), Error=Error>> {
        let (complete, receiver) = futures::oneshot();

        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                // TODO: what if end_notifier is already full? Maybe it should be a vector?
                rc_inner.borrow_mut().end_notifier = Some((result, complete));

                match rc_inner.borrow_mut().task.take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }

        Box::new(
            receiver.map_err(
                |oneshot::Canceled| Error::disconnected("WriteQueue has terminated".into())))
    }
}

enum IntermediateState<W, M> where W: io::Write, M: AsOutputSegments {
    WriteDone(M, W),
    StartWrite(M, oneshot::Sender<M>),
    Resolve,
}

impl <W, M> Future for WriteQueue<W, M> where W: io::Write, M: AsOutputSegments {
    type Item = W; // Resolves when all senders have been dropped and all messages written.
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let next = match self.state {
                State::Writing(ref mut write, ref mut _complete) => {
                    let (w, m) = try_ready!(Future::poll(write));
                    IntermediateState::WriteDone(m, w)
                }
                State::BetweenWrites(ref mut _writer) => {
                    let front = self.inner.borrow_mut().queue.pop_front();
                    match front {
                        Some((m, complete)) => {
                            IntermediateState::StartWrite(m, complete)
                        }
                        None => {
                            let count = self.inner.borrow().sender_count;
                            let ended = self.inner.borrow().end_notifier.is_some();
                            if count == 0 || ended {
                                IntermediateState::Resolve
                            } else {
                                self.inner.borrow_mut().task = Some(task::park());
                                return Ok(Async::NotReady)
                            }
                        }
                    }
                }
                State::Empty => unreachable!(),
            };

            match next {
                IntermediateState::WriteDone(m, w) => {
                    match ::std::mem::replace(&mut self.state, State::BetweenWrites(w)) {
                        State::Writing(_, complete) => {
                            complete.send(m).unwrap_or(());
                        }
                        _ => unreachable!(),
                    }
                }
                IntermediateState::StartWrite(m, c) => {
                    let new_state = match ::std::mem::replace(&mut self.state, State::Empty) {
                        State::BetweenWrites(w) => {
                            State::Writing(::serialize::write_message(w, m), c)
                        }
                        _ => unreachable!(),
                    };
                    self.state = new_state;
                }
                IntermediateState::Resolve => {
                    let end_notifier = self.inner.borrow_mut().end_notifier.take();
                    match end_notifier {
                        None => (),
                        Some((result, complete)) => {
                            complete.send(()).unwrap_or(());
                            if let Err(e) = result {
                                return Err(e)
                            }
                        }
                    }
                    match ::std::mem::replace(&mut self.state, State::Empty) {
                        State::BetweenWrites(w) => {
                            return Ok(Async::Ready(w))
                        }
                        _ => unreachable!(),
                    }
                }
            }
        }
    }
}
<commit_msg>Cleaned up deprecation and unused warnings.<commit_after>// Copyright (c) 2016 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::io;
use std::collections::VecDeque;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::{task, Async, Poll};
use futures::future::Future;
use futures::sync::oneshot;

use capnp::{Error};

use serialize::{self, AsOutputSegments};

enum State<W, M> where W: io::Write, M: AsOutputSegments {
    Writing(serialize::Write<W, M>, oneshot::Sender<M>),
    BetweenWrites(W),
    Empty,
}

/// A queue of messages being written.
#[must_use = "futures do nothing unless polled"]
pub struct WriteQueue<W, M> where W: io::Write, M: AsOutputSegments {
    inner: Rc<RefCell<Inner<M>>>,
    state: State<W, M>,
}

struct Inner<M> {
    queue: VecDeque<(M, oneshot::Sender<M>)>,
    sender_count: usize,
    task: Option<task::Task>,

    // If set, then the queue has been requested to end, and we should complete the oneshot once
    // the queue has been emptied.
    end_notifier: Option<(Result<(), Error>, oneshot::Sender<()>)>
}

/// A handle that allows message to be sent to a `WriteQueue`.
pub struct Sender<M> where M: AsOutputSegments {
    inner: Weak<RefCell<Inner<M>>>,
}

impl <M> Clone for Sender<M> where M: AsOutputSegments {
    fn clone(&self) -> Sender<M> {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.borrow_mut().sender_count += 1;
            }
        }
        Sender { inner: self.inner.clone() }
    }
}

impl <M> Drop for Sender<M> where M: AsOutputSegments {
    fn drop(&mut self) {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.borrow_mut().sender_count -= 1;
            }
        }
    }
}

/// Creates a new WriteQueue that wraps the given writer.
pub fn write_queue<W, M>(writer: W) -> (Sender<M>, WriteQueue<W, M>)
    where W: io::Write, M: AsOutputSegments
{
    let inner = Rc::new(RefCell::new(Inner {
        queue: VecDeque::new(),
        task: None,
        sender_count: 1,
        end_notifier: None,
    }));

    let sender = Sender { inner: Rc::downgrade(&inner) };

    let queue = WriteQueue {
        inner: inner,
        state: State::BetweenWrites(writer),
    };

    (sender, queue)
}

impl <M> Sender<M> where M: AsOutputSegments + 'static {
    /// Enqueues a message to be written.
    pub fn send(&mut self, message: M) -> Box<Future<Item=M, Error=Error>> {
        let (complete, oneshot) = oneshot::channel();

        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                if rc_inner.borrow().end_notifier.is_some() {
                    drop(complete)
                } else {
                    rc_inner.borrow_mut().queue.push_back((message, complete));
                }

                match rc_inner.borrow_mut().task.take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }

        Box::new(
            oneshot.map_err(
                |oneshot::Canceled| Error::disconnected("WriteQueue has terminated".into())))
    }

    /// Returns the number of messages queued to be written, not including any in-progress write.
    pub fn len(&mut self) -> usize {
        match self.inner.upgrade() {
            None => 0,
            Some(rc_inner) => rc_inner.borrow().queue.len(),
        }

    }

    /// Commands the queue to stop writing messages once it is empty. After this method has been called,
    /// any new calls to `send()` will return a future that immediately resolves to an error.
    /// If the passed-in `result` is an error, then the `WriteQueue` will resolve to that error.
    pub fn terminate(&mut self, result: Result<(), Error>) -> Box<Future<Item=(), Error=Error>> {
        let (complete, receiver) = oneshot::channel();

        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                // TODO: what if end_notifier is already full? Maybe it should be a vector?
                rc_inner.borrow_mut().end_notifier = Some((result, complete));

                match rc_inner.borrow_mut().task.take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }

        Box::new(
            receiver.map_err(
                |oneshot::Canceled| Error::disconnected("WriteQueue has terminated".into())))
    }
}

enum IntermediateState<W, M> where W: io::Write, M: AsOutputSegments {
    WriteDone(M, W),
    StartWrite(M, oneshot::Sender<M>),
    Resolve,
}

impl <W, M> Future for WriteQueue<W, M> where W: io::Write, M: AsOutputSegments {
    type Item = W; // Resolves when all senders have been dropped and all messages written.
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let next = match self.state {
                State::Writing(ref mut write, ref mut _complete) => {
                    let (w, m) = try_ready!(Future::poll(write));
                    IntermediateState::WriteDone(m, w)
                }
                State::BetweenWrites(ref mut _writer) => {
                    let front = self.inner.borrow_mut().queue.pop_front();
                    match front {
                        Some((m, complete)) => {
                            IntermediateState::StartWrite(m, complete)
                        }
                        None => {
                            let count = self.inner.borrow().sender_count;
                            let ended = self.inner.borrow().end_notifier.is_some();
                            if count == 0 || ended {
                                IntermediateState::Resolve
                            } else {
                                self.inner.borrow_mut().task = Some(task::park());
                                return Ok(Async::NotReady)
                            }
                        }
                    }
                }
                State::Empty => unreachable!(),
            };

            match next {
                IntermediateState::WriteDone(m, w) => {
                    match ::std::mem::replace(&mut self.state, State::BetweenWrites(w)) {
                        State::Writing(_, complete) => {
                            complete.send(m).unwrap_or(());
                        }
                        _ => unreachable!(),
                    }
                }
                IntermediateState::StartWrite(m, c) => {
                    let new_state = match ::std::mem::replace(&mut self.state, State::Empty) {
                        State::BetweenWrites(w) => {
                            State::Writing(::serialize::write_message(w, m), c)
                        }
                        _ => unreachable!(),
                    };
                    self.state = new_state;
                }
                IntermediateState::Resolve => {
                    let end_notifier = self.inner.borrow_mut().end_notifier.take();
                    match end_notifier {
                        None => (),
                        Some((result, complete)) => {
                            complete.send(()).unwrap_or(());
                            if let Err(e) = result {
                                return Err(e)
                            }
                        }
                    }
                    match ::std::mem::replace(&mut self.state, State::Empty) {
                        State::BetweenWrites(w) => {
                            return Ok(Async::Ready(w))
                        }
                        _ => unreachable!(),
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

//! A pairing of call arguments and the arguments of the called function.
//!
//! This module takes a list of arguments passed to a function or task call, and
//! matches them against the argument list of the function or task declaration.

use crate::crate_prelude::*;
use crate::func_args::{FuncArg, FuncArgList};
use std::{collections::HashMap, sync::Arc};

/// A mapping of call arguments to function/task declaration arguments.
#[derive(Debug)]
pub struct CallMapping<'a> {
    /// The span of the call.
    pub span: Span,
    /// The mapping from declaration arguments to call arguments.
    pub args: Vec<CallArgMapping<'a>>,
    /// Set if the mapping is incomplete due to an error.
    error: bool,
}

impl<'a> CallMapping<'a> {
    /// Create a new tombstone mapping.
    pub fn error(span: Span) -> Self {
        Self {
            span,
            args: Default::default(),
            error: true,
        }
    }

    /// Is this a tombstone?
    pub fn is_error(&self) -> bool {
        self.error
    }
}

/// A mapping of a single call argument to a function/task declaration argument.
#[derive(Debug, Clone, Copy)]
pub struct CallArgMapping<'a> {
    /// A representative span of this argument. Either at the call site, or if
    /// omitted, the default at the declaration site.
    pub span: Span,
    /// The argument in the function/task declaration.
    pub decl: &'a FuncArg<'a>,
    /// The source of the argument in the call.
    pub call: CallArgSource<'a>,
    /// The expression ultimately assigned. This is either the expression in the
    /// call argument, or the default expression in the declaration.
    pub expr: &'a ast::Expr<'a>,
    /// The parameter environment to evaluate the call argument.
    pub env: ParamEnv,
}

/// Whether an argument is explicitly provided by the call, or uses the default.
#[derive(Debug, Clone, Copy)]
pub enum CallArgSource<'a> {
    /// Argument explicitly provided in the call.
    Call(&'a ast::CallArg<'a>),
    /// Argument implicitly set to the default provided in the declaration.
    Default(&'a ast::Expr<'a>),
}

/// Map the arguments of a call to the arguments of the callee declaration.
#[moore_derive::query]
pub(crate) fn call_mapping<'a>(
    cx: &impl Context<'a>,
    Ref(decl_args): Ref<'a, FuncArgList<'a>>,
    Ref(call_args): Ref<'a, [ast::CallArg<'a>]>,
    call_span: Span,
) -> Arc<CallMapping<'a>> {
    debug!("Computing argument mapping");

    // Ensure that the call does not have more arguments than the declaration.
    if call_args.len() > decl_args.args.len() {
        cx.emit(
            DiagBuilder2::error(format!(
                "argument mismatch: {} only has {} arguments, but {} provided",
                decl_args.func,
                decl_args.args.len(),
                call_args.len(),
            ))
            .span(call_span),
        );
        return Arc::new(CallMapping::error(call_span));
    }

    // Build a lookup table of declaration argument names.
    let decl_args_by_name: HashMap<_, _> = decl_args
        .args
        .iter()
        .flat_map(|a| a.name.map(|n| (n.value, a)))
        .collect();
    trace!("Declaration args lookup: {:?}", decl_args_by_name);

    // Process call arguments and match them.
    let mut seen_named = false;
    let mut failed = false;
    let mut partial_mapping = HashMap::<Ref<FuncArg>, &ast::CallArg>::new();

    for (decl_arg, call_arg) in decl_args.args.iter().zip(call_args.iter()) {
        trace!("Matching up `{}`", call_arg.span().extract());

        // Match
        let matched_decl_arg = match call_arg.name {
            Some(call_name) => {
                seen_named = true;
                if let Some(decl_arg) = decl_args_by_name.get(&call_name.value).copied() {
                    decl_arg
                } else {
                    cx.emit(
                        DiagBuilder2::error(format!("unknown argument: `{}`", call_name))
                            .span(call_name.span)
                            .add_note(format!(
                                "Subroutine `{}` was declared here:",
                                decl_args.func.prototype.name
                            ))
                            .span(decl_args.func.span()),
                    );
                    failed = true;
                    continue;
                }
            }
            None if seen_named => {
                cx.emit(
                    DiagBuilder2::error("positional argument after named")
                        .span(call_arg.span())
                        .add_note(
                            "IEEE 1800-2017 requires all positional arguments to appear before \
                             named arguments.",
                        ),
                );
                failed = true;
                continue;
            }
            None => decl_arg,
        };

        if let Some(previous) = partial_mapping.get(&Ref(matched_decl_arg)) {
            cx.emit(
                DiagBuilder2::error(format!(
                    "argument assigned multiple times: `{}`",
                    matched_decl_arg
                        .name
                        .map(|x| x.to_string())
                        .unwrap_or_else(|| "<unnamed>".to_string())
                ))
                .span(call_arg.span())
                .add_note("Previous assignment was here:")
                .span(previous.span()),
            );
            continue;
        } else {
            partial_mapping.insert(Ref(matched_decl_arg), call_arg);
        }
    }
    trace!("Mapping before assigning defaults: {:#?}", partial_mapping);

    // Abort here if we had any failures thus far.
    if failed {
        return Arc::new(CallMapping::error(call_span));
    }

    // Make a canonical with one entry for each declaration argument, and
    // populate default values.
    let mut mapping = vec![];

    for decl_arg in &decl_args.args {
        // Establish the assigned value, either as explicitly provided in the
        // call, or from the default value in the declaration.
        let src = match partial_mapping.get(&Ref(decl_arg)) {
            Some(call_arg) => match &call_arg.expr {
                Some(expr) => Some((expr, call_arg)),
                None => None,
            },
            None => None,
        };
        let span = match src {
            Some((_, call_arg)) => call_arg.span(),
            None => decl_arg.span,
        };
        let (expr, src) = match src {
            Some((expr, call_arg)) => (expr, CallArgSource::Call(call_arg)),
            None => match decl_arg.default {
                Some(default) => (default, CallArgSource::Default(default)),
                None => {
                    cx.emit(
                        DiagBuilder2::error(format!(
                            "argument without default: `{}` must be passed a value",
                            decl_arg
                                .name
                                .map(|x| x.to_string())
                                .unwrap_or_else(|| "<unnamed>".to_string())
                        ))
                        .span(call_span)
                        .add_note("Argument was declared here:")
                        .span(decl_arg.span),
                    );
                    failed = true;
                    continue;
                }
            },
        };

        // Assemble the data struct.
        let arg = CallArgMapping {
            span,
            decl: decl_arg,
            call: src,
            expr,
            env: cx.default_param_env(), // TODO(fschuiki): this needs to change
        };
        mapping.push(arg);
    }

    // Assemble the final struct.
    Arc::new(CallMapping {
        span: call_span,
        args: mapping,
        error: failed,
    })
}

/// A visitor that emits diagnostics for the mapping of a call's arguments to
/// the callee's argument list.
pub struct CallMappingVerbosityVisitor<'cx, C> {
    cx: &'cx C,
}

impl<'cx, C> CallMappingVerbosityVisitor<'cx, C> {
    /// Create a new visitor.
    pub fn new(cx: &'cx C) -> Self {
        CallMappingVerbosityVisitor { cx }
    }
}

impl<'a, 'cx, C> ast::Visitor<'a> for CallMappingVerbosityVisitor<'cx, C>
where
    C: Context<'a>,
    'a: 'cx,
{
    fn pre_visit_expr(&mut self, node: &'a ast::Expr<'a>) -> bool {
        // We're only interested in function calls. Get the call target and
        // arguments.
        let (target, args) = match self.cx.hir_of_expr(Ref(node)) {
            Ok(hir::Expr {
                kind: hir::ExprKind::FunctionCall(target, args),
                ..
            }) => (target, args),
            _ => return true,
        };

        // Canonicalize the target's function arguments and establish the
        // mapping to the call arguments.
        let decl_args = self.cx.canonicalize_func_args(Ref(target));
        let mapping = self.cx.call_mapping(Ref(decl_args), Ref(args), node.span());
        if mapping.is_error() {
            return true;
        }

        let mut d = DiagBuilder2::note("call argument mapping")
            .span(node.span())
            .add_note(format!(
                "Call to subroutine `{}` has the following argument mapping:",
                target.prototype.name
            ));
        for m in &mapping.args {
            let name = match m.decl.name {
                Some(name) => format!(" {}", name),
                None => format!(""),
            };
            let ty = self.cx.unpacked_type_from_ast(
                Ref(m.decl.ty),
                Ref(m.decl.unpacked_dims),
                m.env,
                None,
            );
            let value = format!(
                "{} {}",
                m.expr.span().extract(),
                match m.call {
                    CallArgSource::Call(..) => "(call)",
                    CallArgSource::Default(..) => "(default)",
                }
            );
            d = d.add_note(format!("{} {}{} = {}", m.decl.dir, ty, name, value));
        }
        self.cx.emit(d);
        true
    }
}
<commit_msg>svlog: Make CallArgSource Eq/PartialEq/Hash<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

//! A pairing of call arguments and the arguments of the called function.
//!
//! This module takes a list of arguments passed to a function or task call, and
//! matches them against the argument list of the function or task declaration.

use crate::crate_prelude::*;
use crate::func_args::{FuncArg, FuncArgList};
use std::{collections::HashMap, sync::Arc};

/// A mapping of call arguments to function/task declaration arguments.
#[derive(Debug)]
pub struct CallMapping<'a> {
    /// The span of the call.
    pub span: Span,
    /// The mapping from declaration arguments to call arguments.
    pub args: Vec<CallArgMapping<'a>>,
    /// Set if the mapping is incomplete due to an error.
    error: bool,
}

impl<'a> CallMapping<'a> {
    /// Create a new tombstone mapping.
    pub fn error(span: Span) -> Self {
        Self {
            span,
            args: Default::default(),
            error: true,
        }
    }

    /// Is this a tombstone?
    pub fn is_error(&self) -> bool {
        self.error
    }
}

/// A mapping of a single call argument to a function/task declaration argument.
#[derive(Debug, Clone, Copy)]
pub struct CallArgMapping<'a> {
    /// A representative span of this argument. Either at the call site, or if
    /// omitted, the default at the declaration site.
    pub span: Span,
    /// The argument in the function/task declaration.
    pub decl: &'a FuncArg<'a>,
    /// The source of the argument in the call.
    pub call: CallArgSource<'a>,
    /// The expression ultimately assigned. This is either the expression in the
    /// call argument, or the default expression in the declaration.
    pub expr: &'a ast::Expr<'a>,
    /// The parameter environment to evaluate the call argument.
    pub env: ParamEnv,
}

/// Whether an argument is explicitly provided by the call, or uses the default.
#[derive(Debug, Clone, Copy)]
pub enum CallArgSource<'a> {
    /// Argument explicitly provided in the call.
    Call(&'a ast::CallArg<'a>),
    /// Argument implicitly set to the default provided in the declaration.
    Default(&'a ast::Expr<'a>),
}

impl Eq for CallArgSource<'_> {}
impl PartialEq for CallArgSource<'_> {
    fn eq(&self, other: &Self) -> bool {
        match (*self, *other) {
            (Self::Call(a), Self::Call(b)) => std::ptr::eq(a, b),
            (Self::Default(a), Self::Default(b)) => std::ptr::eq(a, b),
            _ => false,
        }
    }
}

impl std::hash::Hash for CallArgSource<'_> {
    fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
        match *self {
            Self::Call(x) => std::ptr::hash(x, h),
            Self::Default(x) => std::ptr::hash(x, h),
        }
    }
}

/// Map the arguments of a call to the arguments of the callee declaration.
#[moore_derive::query]
pub(crate) fn call_mapping<'a>(
    cx: &impl Context<'a>,
    Ref(decl_args): Ref<'a, FuncArgList<'a>>,
    Ref(call_args): Ref<'a, [ast::CallArg<'a>]>,
    call_span: Span,
) -> Arc<CallMapping<'a>> {
    debug!("Computing argument mapping");

    // Ensure that the call does not have more arguments than the declaration.
    if call_args.len() > decl_args.args.len() {
        cx.emit(
            DiagBuilder2::error(format!(
                "argument mismatch: {} only has {} arguments, but {} provided",
                decl_args.func,
                decl_args.args.len(),
                call_args.len(),
            ))
            .span(call_span),
        );
        return Arc::new(CallMapping::error(call_span));
    }

    // Build a lookup table of declaration argument names.
    let decl_args_by_name: HashMap<_, _> = decl_args
        .args
        .iter()
        .flat_map(|a| a.name.map(|n| (n.value, a)))
        .collect();
    trace!("Declaration args lookup: {:?}", decl_args_by_name);

    // Process call arguments and match them.
    let mut seen_named = false;
    let mut failed = false;
    let mut partial_mapping = HashMap::<Ref<FuncArg>, &ast::CallArg>::new();

    for (decl_arg, call_arg) in decl_args.args.iter().zip(call_args.iter()) {
        trace!("Matching up `{}`", call_arg.span().extract());

        // Match
        let matched_decl_arg = match call_arg.name {
            Some(call_name) => {
                seen_named = true;
                if let Some(decl_arg) = decl_args_by_name.get(&call_name.value).copied() {
                    decl_arg
                } else {
                    cx.emit(
                        DiagBuilder2::error(format!("unknown argument: `{}`", call_name))
                            .span(call_name.span)
                            .add_note(format!(
                                "Subroutine `{}` was declared here:",
                                decl_args.func.prototype.name
                            ))
                            .span(decl_args.func.span()),
                    );
                    failed = true;
                    continue;
                }
            }
            None if seen_named => {
                cx.emit(
                    DiagBuilder2::error("positional argument after named")
                        .span(call_arg.span())
                        .add_note(
                            "IEEE 1800-2017 requires all positional arguments to appear before \
                             named arguments.",
                        ),
                );
                failed = true;
                continue;
            }
            None => decl_arg,
        };

        if let Some(previous) = partial_mapping.get(&Ref(matched_decl_arg)) {
            cx.emit(
                DiagBuilder2::error(format!(
                    "argument assigned multiple times: `{}`",
                    matched_decl_arg
                        .name
                        .map(|x| x.to_string())
                        .unwrap_or_else(|| "<unnamed>".to_string())
                ))
                .span(call_arg.span())
                .add_note("Previous assignment was here:")
                .span(previous.span()),
            );
            continue;
        } else {
            partial_mapping.insert(Ref(matched_decl_arg), call_arg);
        }
    }
    trace!("Mapping before assigning defaults: {:#?}", partial_mapping);

    // Abort here if we had any failures thus far.
    if failed {
        return Arc::new(CallMapping::error(call_span));
    }

    // Make a canonical with one entry for each declaration argument, and
    // populate default values.
    let mut mapping = vec![];

    for decl_arg in &decl_args.args {
        // Establish the assigned value, either as explicitly provided in the
        // call, or from the default value in the declaration.
        let src = match partial_mapping.get(&Ref(decl_arg)) {
            Some(call_arg) => match &call_arg.expr {
                Some(expr) => Some((expr, call_arg)),
                None => None,
            },
            None => None,
        };
        let span = match src {
            Some((_, call_arg)) => call_arg.span(),
            None => decl_arg.span,
        };
        let (expr, src) = match src {
            Some((expr, call_arg)) => (expr, CallArgSource::Call(call_arg)),
            None => match decl_arg.default {
                Some(default) => (default, CallArgSource::Default(default)),
                None => {
                    cx.emit(
                        DiagBuilder2::error(format!(
                            "argument without default: `{}` must be passed a value",
                            decl_arg
                                .name
                                .map(|x| x.to_string())
                                .unwrap_or_else(|| "<unnamed>".to_string())
                        ))
                        .span(call_span)
                        .add_note("Argument was declared here:")
                        .span(decl_arg.span),
                    );
                    failed = true;
                    continue;
                }
            },
        };

        // Assemble the data struct.
        let arg = CallArgMapping {
            span,
            decl: decl_arg,
            call: src,
            expr,
            env: cx.default_param_env(), // TODO(fschuiki): this needs to change
        };
        mapping.push(arg);
    }

    // Assemble the final struct.
    Arc::new(CallMapping {
        span: call_span,
        args: mapping,
        error: failed,
    })
}

/// A visitor that emits diagnostics for the mapping of a call's arguments to
/// the callee's argument list.
pub struct CallMappingVerbosityVisitor<'cx, C> {
    cx: &'cx C,
}

impl<'cx, C> CallMappingVerbosityVisitor<'cx, C> {
    /// Create a new visitor.
    pub fn new(cx: &'cx C) -> Self {
        CallMappingVerbosityVisitor { cx }
    }
}

impl<'a, 'cx, C> ast::Visitor<'a> for CallMappingVerbosityVisitor<'cx, C>
where
    C: Context<'a>,
    'a: 'cx,
{
    fn pre_visit_expr(&mut self, node: &'a ast::Expr<'a>) -> bool {
        // We're only interested in function calls. Get the call target and
        // arguments.
        let (target, args) = match self.cx.hir_of_expr(Ref(node)) {
            Ok(hir::Expr {
                kind: hir::ExprKind::FunctionCall(target, args),
                ..
            }) => (target, args),
            _ => return true,
        };

        // Canonicalize the target's function arguments and establish the
        // mapping to the call arguments.
        let decl_args = self.cx.canonicalize_func_args(Ref(target));
        let mapping = self.cx.call_mapping(Ref(decl_args), Ref(args), node.span());
        if mapping.is_error() {
            return true;
        }

        let mut d = DiagBuilder2::note("call argument mapping")
            .span(node.span())
            .add_note(format!(
                "Call to subroutine `{}` has the following argument mapping:",
                target.prototype.name
            ));
        for m in &mapping.args {
            let name = match m.decl.name {
                Some(name) => format!(" {}", name),
                None => format!(""),
            };
            let ty = self.cx.unpacked_type_from_ast(
                Ref(m.decl.ty),
                Ref(m.decl.unpacked_dims),
                m.env,
                None,
            );
            let value = format!(
                "{} {}",
                m.expr.span().extract(),
                match m.call {
                    CallArgSource::Call(..) => "(call)",
                    CallArgSource::Default(..) => "(default)",
                }
            );
            d = d.add_note(format!("{} {}{} = {}", m.decl.dir, ty, name, value));
        }
        self.cx.emit(d);
        true
    }
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]

extern crate graphics;
extern crate gfx as gfx_core;
extern crate gfx_device_gl as gfx_device;
extern crate gfx_graphics;
extern crate piston;
extern crate glutin_window;

use std::cell::RefCell;
use std::rc::Rc;

use gfx_core::traits::*;
use gfx_graphics::Gfx2d;

use piston::event::*;
use piston::input::{Button, MouseButton};
use piston::window::{WindowSettings, Size, OpenGLWindow};
use glutin_window::{GlutinWindow, OpenGL};

#[macro_use]
extern crate r3;
pub use r3::{cfg, gfx, ui};

use ui::Px;
use ui::color::Scheme;
use ui::draw::DrawCx;
use ui::event::Dispatch;
use ui::text::FontFaces;

fn main() {
    let mut window = GlutinWindow::new(
        OpenGL::_3_2,
        WindowSettings::new(
            "rid3".to_string(),
            Size { width: 800, height: 600 }
        ).exit_on_esc(true)
    );

    let (mut device, mut factory) = gfx_device::create(|s| window.get_proc_address(s));
    let mut renderer = factory.create_renderer();
    let mut g2d = Gfx2d::new(&mut device, &mut factory);

    let factory = Rc::new(RefCell::new(factory));

    let mut fonts = FontFaces {
        regular: gfx::GlyphCache::from_data(include_bytes!("../../assets/NotoSans/NotoSans-Regular.ttf"), factory.clone()).unwrap(),
        mono: gfx::GlyphCache::from_data(include_bytes!("../../assets/Hasklig/Hasklig-Regular.otf"), factory.clone()).unwrap(),
        mono_bold: gfx::GlyphCache::from_data(include_bytes!("../../assets/Hasklig/Hasklig-Bold.otf"), factory.clone()).unwrap()
    };

    let menu_bar = menu_bar![
        ui::menu::Button::new("File"),
        ui::menu::Button::new("Edit"),
        ui::menu::Button::new("Settings"),
        ui::menu::Button::new("Help"),
    ];
    let editor = ui::editor::Editor::open("src/bin/rid3.rs");
    let root = flow![down: menu_bar, editor];

    let (mut x, mut y) = (0.0, 0.0);
    let mut cursor = gfx::MouseCursor::Default;
    let mut dirty = true;

    let window = &Rc::new(RefCell::new(window));
    for e in window.events() {
        if let (true, Some(args)) = (dirty, e.render_args()) {
            let viewport = args.viewport();
            let sz = viewport.draw_size;
            let frame = factory.borrow_mut().make_fake_output(sz[0] as u16, sz[1] as u16);
            g2d.draw(&mut renderer, &frame, viewport, |c, g| {
                ui::layout::compute(&root, &mut fonts, sz[0] as Px, sz[1] as Px);
                graphics::clear(cfg::ColorScheme.background(), g);
                let mut draw_cx = DrawCx {
                    gfx: g,
                    fonts: &mut fonts,
                    transform: c.transform,
                    cursor: gfx::MouseCursor::Default
                };
                draw_cx.draw(&root);
                if (draw_cx.cursor as usize) != (cursor as usize) {
                    window.borrow_mut().window.set_cursor(draw_cx.cursor);
                    cursor = draw_cx.cursor;
                }
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
            dirty = false;
        }

        if let Some(_) = e.after_render_args() {
            device.after_frame();
            factory.borrow_mut().cleanup();
        }

        if let Some(Button::Mouse(MouseButton::Left)) = e.press_args() {
            dirty |= root.dispatch(&ui::event::MouseDown::new(x, y));
        }

        if let Some(Button::Mouse(MouseButton::Left)) = e.release_args() {
            dirty |= root.dispatch(&ui::event::MouseUp::new(x, y));
        }

        if let Some([nx, ny]) = e.mouse_cursor_args() {
            x = nx as Px;
            y = ny as Px;
            dirty |= root.dispatch(&ui::event::MouseMove::new(x, y));
        }

        if let Some([dx, dy]) = e.mouse_scroll_args() {
            dirty |= root.dispatch(&ui::event::MouseScroll::with(x, y,
                ui::event::mouse::Scroll([dx as Px, dy as Px])));
        }

        if let Some(_) = e.update_args() {
            dirty |= root.dispatch(&ui::event::Update);
        }

        if let Some(_) = e.resize_args() {
            dirty = true;
        }

        e.text(|s| dirty |= root.dispatch(&ui::event::TextInput(s)));
    }
}
<commit_msg>Lower OpenGL version requirements and avoid (unimplemented) cursor changes on windows.<commit_after>#![feature(slice_patterns)]

extern crate graphics;
extern crate gfx as gfx_core;
extern crate gfx_device_gl as gfx_device;
extern crate gfx_graphics;
extern crate piston;
extern crate glutin_window;

use std::cell::RefCell;
use std::rc::Rc;

use gfx_core::traits::*;
use gfx_graphics::Gfx2d;

use piston::event::*;
use piston::input::{Button, MouseButton};
use piston::window::{WindowSettings, Size, OpenGLWindow};
use glutin_window::{GlutinWindow, OpenGL};

#[macro_use]
extern crate r3;
pub use r3::{cfg, gfx, ui};

use ui::Px;
use ui::color::Scheme;
use ui::draw::DrawCx;
use ui::event::Dispatch;
use ui::text::FontFaces;

fn main() {
    let mut window = GlutinWindow::new(
        OpenGL::_2_1,
        WindowSettings::new(
            "rid3".to_string(),
            Size { width: 800, height: 600 }
        ).exit_on_esc(true)
    );

    let (mut device, mut factory) = gfx_device::create(|s| window.get_proc_address(s));
    let mut renderer = factory.create_renderer();
    let mut g2d = Gfx2d::new(&mut device, &mut factory);

    let factory = Rc::new(RefCell::new(factory));

    let mut fonts = FontFaces {
        regular: gfx::GlyphCache::from_data(include_bytes!("../../assets/NotoSans/NotoSans-Regular.ttf"), factory.clone()).unwrap(),
        mono: gfx::GlyphCache::from_data(include_bytes!("../../assets/Hasklig/Hasklig-Regular.otf"), factory.clone()).unwrap(),
        mono_bold: gfx::GlyphCache::from_data(include_bytes!("../../assets/Hasklig/Hasklig-Bold.otf"), factory.clone()).unwrap()
    };

    let menu_bar = menu_bar![
        ui::menu::Button::new("File"),
        ui::menu::Button::new("Edit"),
        ui::menu::Button::new("Settings"),
        ui::menu::Button::new("Help"),
    ];
    let editor = ui::editor::Editor::open("src/bin/rid3.rs");
    let root = flow![down: menu_bar, editor];

    let (mut x, mut y) = (0.0, 0.0);
    let mut cursor = gfx::MouseCursor::Default;
    let mut dirty = true;

    let window = &Rc::new(RefCell::new(window));
    for e in window.events() {
        if let (true, Some(args)) = (dirty, e.render_args()) {
            let viewport = args.viewport();
            let sz = viewport.draw_size;
            let frame = factory.borrow_mut().make_fake_output(sz[0] as u16, sz[1] as u16);
            g2d.draw(&mut renderer, &frame, viewport, |c, g| {
                ui::layout::compute(&root, &mut fonts, sz[0] as Px, sz[1] as Px);
                graphics::clear(cfg::ColorScheme.background(), g);
                let mut draw_cx = DrawCx {
                    gfx: g,
                    fonts: &mut fonts,
                    transform: c.transform,
                    cursor: gfx::MouseCursor::Default
                };
                draw_cx.draw(&root);
                if (draw_cx.cursor as usize) != (cursor as usize) {
                    if !cfg!(windows) {
                        window.borrow_mut().window.set_cursor(draw_cx.cursor);
                    }
                    cursor = draw_cx.cursor;
                }
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
            dirty = false;
        }

        if let Some(_) = e.after_render_args() {
            device.after_frame();
            factory.borrow_mut().cleanup();
        }

        if let Some(Button::Mouse(MouseButton::Left)) = e.press_args() {
            dirty |= root.dispatch(&ui::event::MouseDown::new(x, y));
        }

        if let Some(Button::Mouse(MouseButton::Left)) = e.release_args() {
            dirty |= root.dispatch(&ui::event::MouseUp::new(x, y));
        }

        if let Some([nx, ny]) = e.mouse_cursor_args() {
            x = nx as Px;
            y = ny as Px;
            dirty |= root.dispatch(&ui::event::MouseMove::new(x, y));
        }

        if let Some([dx, dy]) = e.mouse_scroll_args() {
            dirty |= root.dispatch(&ui::event::MouseScroll::with(x, y,
                ui::event::mouse::Scroll([dx as Px, dy as Px])));
        }

        if let Some(_) = e.update_args() {
            dirty |= root.dispatch(&ui::event::Update);
        }

        if let Some(_) = e.resize_args() {
            dirty = true;
        }

        e.text(|s| dirty |= root.dispatch(&ui::event::TextInput(s)));
    }
}
<|endoftext|>


<commit_before>use {Epoch, Index, StorageId};

#[derive(Copy, Clone, Debug, PartialEq, Hash)]
pub struct PointerData(u64);

#[cfg(target_pointer_width = "32")]
const INDEX_BITS: u8 = 20;
#[cfg(target_pointer_width = "32")]
const EPOCH_BITS: u8 = 8;
#[cfg(target_pointer_width = "32")]
const STORAGE_ID_BITS: u8 = 4;

#[cfg(target_pointer_width = "64")]
const INDEX_BITS: u8 = 40;
#[cfg(target_pointer_width = "64")]
const EPOCH_BITS: u8 = 16;
#[cfg(target_pointer_width = "64")]
const STORAGE_ID_BITS: u8 = 8;

const INDEX_MASK: u64 = (1 << INDEX_BITS) - 1;
const EPOCH_OFFSET: u8 = INDEX_BITS;
const EPOCH_MASK: u64 = ((1 << EPOCH_BITS) - 1) << EPOCH_OFFSET;
const STORAGE_ID_OFFSET: u8 = EPOCH_OFFSET + EPOCH_BITS;
const STORAGE_ID_MASK: u64 = ((1 << STORAGE_ID_BITS) - 1) << STORAGE_ID_OFFSET;

impl PointerData {
    #[inline]
    pub fn new(index: Index, epoch: Epoch, storage: StorageId) -> Self {
        debug_assert_eq!(index >> INDEX_BITS, 0);
        PointerData(index as u64 + ((epoch as u64) << EPOCH_OFFSET) +
            ((storage as u64) << STORAGE_ID_OFFSET))
    }

    #[inline]
    pub fn get_index(&self) -> Index {
        (self.0 & INDEX_MASK) as Index
    }

    #[inline]
    pub fn get_epoch(&self) -> Epoch {
        ((self.0 & EPOCH_MASK) >> EPOCH_OFFSET) as Epoch
    }

    #[inline]
    pub fn get_storage_id(&self) -> StorageId {
        ((self.0 & STORAGE_ID_MASK) >> STORAGE_ID_OFFSET) as StorageId
    }

    #[inline]
    pub fn with_epoch(&self, epoch: Epoch) -> PointerData {
        PointerData((self.0 & !EPOCH_MASK) + ((epoch as u64) << EPOCH_OFFSET))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::mem::size_of;

    #[test]
    fn sizes() {
        #[cfg(target_pointer_width = "32")]
        assert_eq!(INDEX_BITS + EPOCH_BITS + STORAGE_ID_BITS, 32);
        #[cfg(target_pointer_width = "64")]
        assert_eq!(INDEX_BITS + EPOCH_BITS + STORAGE_ID_BITS, 64);
        assert!(size_of::<Index>() * 8 >= INDEX_BITS as usize);
        assert!(size_of::<Epoch>() * 8 >= EPOCH_BITS as usize);
        assert!(size_of::<StorageId>() * 8 >= STORAGE_ID_BITS as usize);
    }

    #[test]
    fn new() {
        let pd = PointerData::new(1, 2, 3);
        assert_eq!(pd.get_index(), 1);
        assert_eq!(pd.get_epoch(), 2);
        assert_eq!(pd.get_storage_id(), 3);
        assert_eq!(pd.with_epoch(5).get_epoch(), 5);
    }
}
<commit_msg>Fix clippy issues in bitfield module<commit_after>use {Epoch, Index, StorageId};

#[derive(Copy, Clone, Debug, PartialEq, Hash)]
pub struct PointerData(u64);

#[cfg(target_pointer_width = "32")]
const INDEX_BITS: u8 = 20;
#[cfg(target_pointer_width = "32")]
const EPOCH_BITS: u8 = 8;
#[cfg(target_pointer_width = "32")]
const STORAGE_ID_BITS: u8 = 4;

#[cfg(target_pointer_width = "64")]
const INDEX_BITS: u8 = 40;
#[cfg(target_pointer_width = "64")]
const EPOCH_BITS: u8 = 16;
#[cfg(target_pointer_width = "64")]
const STORAGE_ID_BITS: u8 = 8;

const INDEX_MASK: u64 = (1 << INDEX_BITS) - 1;
const EPOCH_OFFSET: u8 = INDEX_BITS;
const EPOCH_MASK: u64 = ((1 << EPOCH_BITS) - 1) << EPOCH_OFFSET;
const STORAGE_ID_OFFSET: u8 = EPOCH_OFFSET + EPOCH_BITS;
const STORAGE_ID_MASK: u64 = ((1 << STORAGE_ID_BITS) - 1) << STORAGE_ID_OFFSET;

impl PointerData {
    #[inline]
    pub fn new(index: Index, epoch: Epoch, storage: StorageId) -> Self {
        debug_assert_eq!(index >> INDEX_BITS, 0);
        PointerData(index as u64 + ((u64::from(epoch)) << EPOCH_OFFSET) +
            ((u64::from(storage)) << STORAGE_ID_OFFSET))
    }

    #[inline]
    pub fn get_index(self) -> Index {
        (self.0 & INDEX_MASK) as Index
    }

    #[inline]
    pub fn get_epoch(self) -> Epoch {
        ((self.0 & EPOCH_MASK) >> EPOCH_OFFSET) as Epoch
    }

    #[inline]
    pub fn get_storage_id(self) -> StorageId {
        ((self.0 & STORAGE_ID_MASK) >> STORAGE_ID_OFFSET) as StorageId
    }

    #[inline]
    pub fn with_epoch(self, epoch: Epoch) -> PointerData {
        PointerData((self.0 & !EPOCH_MASK) + ((u64::from(epoch)) << EPOCH_OFFSET))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::mem::size_of;

    #[test]
    fn sizes() {
        #[cfg(target_pointer_width = "32")]
        assert_eq!(INDEX_BITS + EPOCH_BITS + STORAGE_ID_BITS, 32);
        #[cfg(target_pointer_width = "64")]
        assert_eq!(INDEX_BITS + EPOCH_BITS + STORAGE_ID_BITS, 64);
        assert!(size_of::<Index>() * 8 >= INDEX_BITS as usize);
        assert!(size_of::<Epoch>() * 8 >= EPOCH_BITS as usize);
        assert!(size_of::<StorageId>() * 8 >= STORAGE_ID_BITS as usize);
    }

    #[test]
    fn new() {
        let pd = PointerData::new(1, 2, 3);
        assert_eq!(pd.get_index(), 1);
        assert_eq!(pd.get_epoch(), 2);
        assert_eq!(pd.get_storage_id(), 3);
        assert_eq!(pd.with_epoch(5).get_epoch(), 5);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![experimental]
#![macro_escape]

//! A typesafe bitmask flag generator.

/// The `bitflags!` macro generates a `struct` that holds a set of C-style
/// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
///
/// The flags should only be defined for integer types, otherwise unexpected
/// type errors may occur at compile time.
///
/// # Example
///
/// ```{.rust}
/// bitflags! {
///     flags Flags: u32 {
///         const FLAG_A       = 0b00000001,
///         const FLAG_B       = 0b00000010,
///         const FLAG_C       = 0b00000100,
///         const FLAG_ABC     = FLAG_A.bits
///                            | FLAG_B.bits
///                            | FLAG_C.bits,
///     }
/// }
///
/// fn main() {
///     let e1 = FLAG_A | FLAG_C;
///     let e2 = FLAG_B | FLAG_C;
///     assert!((e1 | e2) == FLAG_ABC);   // union
///     assert!((e1 & e2) == FLAG_C);     // intersection
///     assert!((e1 - e2) == FLAG_A);     // set difference
///     assert!(!e2 == FLAG_A);           // set complement
/// }
/// ```
///
/// The generated `struct`s can also be extended with type and trait implementations:
///
/// ```{.rust}
/// use std::fmt;
///
/// bitflags! {
///     flags Flags: u32 {
///         const FLAG_A   = 0b00000001,
///         const FLAG_B   = 0b00000010,
///     }
/// }
///
/// impl Flags {
///     pub fn clear(&mut self) {
///         self.bits = 0;  // The `bits` field can be accessed from within the
///                         // same module where the `bitflags!` macro was invoked.
///     }
/// }
///
/// impl fmt::Show for Flags {
///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
///         write!(f, "hi!")
///     }
/// }
///
/// fn main() {
///     let mut flags = FLAG_A | FLAG_B;
///     flags.clear();
///     assert!(flags.is_empty());
///     assert_eq!(format!("{}", flags).as_slice(), "hi!");
/// }
/// ```
///
/// # Attributes
///
/// Attributes can be attached to the generated `struct` by placing them
/// before the `flags` keyword.
///
/// # Derived traits
///
/// The `PartialEq` and `Clone` traits are automatically derived for the `struct` using
/// the `deriving` attribute. Additional traits can be derived by providing an
/// explicit `deriving` attribute on `flags`.
///
/// # Operators
///
/// The following operator traits are implemented for the generated `struct`:
///
/// - `BitOr`: union
/// - `BitAnd`: intersection
/// - `BitXor`: toggle
/// - `Sub`: set difference
/// - `Not`: set complement
///
/// # Methods
///
/// The following methods are defined for the generated `struct`:
///
/// - `empty`: an empty set of flags
/// - `all`: the set of all flags
/// - `bits`: the raw value of the flags currently stored
/// - `from_bits`: convert from underlying bit representation, unless that
///                representation contains bits that do not correspond to a flag
/// - `from_bits_truncate`: convert from underlying bit representation, dropping
///                         any bits that do not correspond to flags
/// - `is_empty`: `true` if no flags are currently stored
/// - `is_all`: `true` if all flags are currently set
/// - `intersects`: `true` if there are flags common to both `self` and `other`
/// - `contains`: `true` all of the flags in `other` are contained within `self`
/// - `insert`: inserts the specified flags in-place
/// - `remove`: removes the specified flags in-place
/// - `toggle`: the specified flags will be inserted if not present, and removed
///             if they are.
#[macro_export]
macro_rules! bitflags {
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+
    }) => {
        #[deriving(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            #[inline]
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the set containing all flags.
            #[inline]
            pub fn all() -> $BitFlags {
                $BitFlags { bits: $($value)|+ }
            }

            /// Returns the raw value of the flags currently stored.
            #[inline]
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Convert from underlying bit representation, unless that
            /// representation contains bits that do not correspond to a flag.
            #[inline]
            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
                if (bits & !$BitFlags::all().bits()) != 0 {
                    ::std::option::Option::None
                } else {
                    ::std::option::Option::Some($BitFlags { bits: bits })
                }
            }

            /// Convert from underlying bit representation, dropping any bits
            /// that do not correspond to flags.
            #[inline]
            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
                $BitFlags { bits: bits } & $BitFlags::all()
            }

            /// Returns `true` if no flags are currently stored.
            #[inline]
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if all flags are currently set.
            #[inline]
            pub fn is_all(&self) -> bool {
                *self == $BitFlags::all()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            #[inline]
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(*self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            #[inline]
            pub fn contains(&self, other: $BitFlags) -> bool {
                (*self & other) == other
            }

            /// Inserts the specified flags in-place.
            #[inline]
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            #[inline]
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }

            /// Toggles the specified flags in-place.
            #[inline]
            pub fn toggle(&mut self, other: $BitFlags) {
                self.bits ^= other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the left flags, but with all the right flags toggled.
            #[inline]
            fn bitxor(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits ^ other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }

        // NOTE(stage0): Remove impl after a snapshot
        #[cfg(stage0)]
        impl Not<$BitFlags> for $BitFlags {
            /// Returns the complement of this set of flags.
            #[inline]
            fn not(&self) -> $BitFlags {
                $BitFlags { bits: !self.bits } & $BitFlags::all()
            }
        }

        #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
        impl Not<$BitFlags> for $BitFlags {
            /// Returns the complement of this set of flags.
            #[inline]
            fn not(self) -> $BitFlags {
                $BitFlags { bits: !self.bits } & $BitFlags::all()
            }
        }
    };
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+,
    }) => {
        bitflags! {
            $(#[$attr])*
            flags $BitFlags: $T {
                $($(#[$Flag_attr])* const $Flag = $value),+
            }
        }
    };
}

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
    use hash;
    use option::Option::{Some, None};
    use ops::{BitOr, BitAnd, BitXor, Sub, Not};

    bitflags! {
        #[doc = "> The first principle is that you must not fool yourself — and"]
        #[doc = "> you are the easiest person to fool."]
        #[doc = "> "]
        #[doc = "> - Richard Feynman"]
        flags Flags: u32 {
            const FlagA       = 0b00000001,
            #[doc = "<pcwalton> macros are way better at generating code than trans is"]
            const FlagB       = 0b00000010,
            const FlagC       = 0b00000100,
            #[doc = "* cmr bed"]
            #[doc = "* strcat table"]
            #[doc = "<strcat> wait what?"]
            const FlagABC     = FlagA.bits
                               | FlagB.bits
                               | FlagC.bits,
        }
    }

    bitflags! {
        flags AnotherSetOfFlags: i8 {
            const AnotherFlag = -1_i8,
        }
    }

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0b00000000);
        assert_eq!(FlagA.bits(), 0b00000001);
        assert_eq!(FlagABC.bits(), 0b00000111);

        assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
        assert_eq!(AnotherFlag.bits(), !0_i8);
    }

    #[test]
    fn test_from_bits() {
        assert!(Flags::from_bits(0) == Some(Flags::empty()));
        assert!(Flags::from_bits(0b1) == Some(FlagA));
        assert!(Flags::from_bits(0b10) == Some(FlagB));
        assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB));
        assert!(Flags::from_bits(0b1000) == None);

        assert!(AnotherSetOfFlags::from_bits(!0_i8) == Some(AnotherFlag));
    }

    #[test]
    fn test_from_bits_truncate() {
        assert!(Flags::from_bits_truncate(0) == Flags::empty());
        assert!(Flags::from_bits_truncate(0b1) == FlagA);
        assert!(Flags::from_bits_truncate(0b10) == FlagB);
        assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB));
        assert!(Flags::from_bits_truncate(0b1000) == Flags::empty());
        assert!(Flags::from_bits_truncate(0b1001) == FlagA);

        assert!(AnotherSetOfFlags::from_bits_truncate(0_i8) == AnotherSetOfFlags::empty());
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());

        assert!(!AnotherFlag.is_empty());
    }

    #[test]
    fn test_is_all() {
        assert!(Flags::all().is_all());
        assert!(!FlagA.is_all());
        assert!(FlagABC.is_all());

        assert!(AnotherFlag.is_all());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));

        assert!(AnotherFlag.intersects(AnotherFlag));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));

        assert!(AnotherFlag.contains(AnotherFlag));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);

        let mut e3 = AnotherSetOfFlags::empty();
        e3.insert(AnotherFlag);
        assert!(e3 == AnotherFlag);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);

        let mut e3 = AnotherFlag;
        e3.remove(AnotherFlag);
        assert!(e3 == AnotherSetOfFlags::empty());
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);     // union
        assert!((e1 & e2) == FlagC);       // intersection
        assert!((e1 - e2) == FlagA);       // set difference
        assert!(!e2 == FlagA);             // set complement
        assert!(e1 ^ e2 == FlagA | FlagB); // toggle
        let mut e3 = e1;
        e3.toggle(e2);
        assert!(e3 == FlagA | FlagB);

        let mut m4 = AnotherSetOfFlags::empty();
        m4.toggle(AnotherSetOfFlags::empty());
        assert!(m4 == AnotherSetOfFlags::empty());
    }

    #[test]
    fn test_lt() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(!(a < b) && !(b < a));
        b = FlagB;
        assert!(a < b);
        a = FlagC;
        assert!(!(a < b) && b < a);
        b = FlagC | FlagB;
        assert!(a < b);
    }

    #[test]
    fn test_ord() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(a <= b && a >= b);
        a = FlagA;
        assert!(a > b && a >= b);
        assert!(b < a && b <= a);
        b = FlagB;
        assert!(b > a && b >= a);
        assert!(a < b && a <= b);
    }

    #[test]
    fn test_hash() {
      let mut x = Flags::empty();
      let mut y = Flags::empty();
      assert!(hash::hash(&x) == hash::hash(&y));
      x = Flags::all();
      y = FlagABC;
      assert!(hash::hash(&x) == hash::hash(&y));
    }
}
<commit_msg>remove unneeded bitflags macro (for now)<commit_after><|endoftext|>


<commit_before>mod bxdf;
mod fresnel;

pub use self::bxdf::*;
pub use self::fresnel::*;

use std::mem;
use na::{self, Cross, Dot, zero, Norm, clamp};

use ::{Vector, Point2f};
use colour::Colourf;
use intersection::Intersection;
use interaction::SurfaceInteraction;

bitflags! {
    pub flags BxDFType: u32 {
        const BSDF_REFLECTION   = 0b_00000001,
        const BSDF_TRANSMISSION = 0b_00000010,
        const BSDF_DIFFUSE      = 0b_00000100,
        const BSDF_GLOSSY       = 0b_00001000,
        const BSDF_SPECULAR     = 0b_00010000,
    }
}

/// Represents the Bidirectional Scattering Distribution Function.
/// It represents the properties of a material at a given point.
#[derive(Copy, Clone)]
pub struct BSDF<'a> {
    /// Index of refraction of the surface
    eta: f32,
    /// Shading normal (i.e. potentially affected by bump-mapping)
    ns: Vector,
    /// Geometry normal
    ng: Vector,
    ss: Vector,
    ts: Vector,
    bxdfs: &'a [Box<BxDF + Sync + Send>],
}

impl<'a> BSDF<'a> {
    pub fn new(isect: &SurfaceInteraction,
               eta: f32,
               bxdfs: &'a [Box<BxDF + Sync + Send>])
               -> BSDF<'a> {
        let ss = isect.dpdu.normalize();
        BSDF {
            eta: eta,
            ns: isect.shading.n,
            ng: isect.n,
            ss: ss,
            ts: isect.shading.n.cross(&ss),
            bxdfs: bxdfs,
        }
    }

    /// Evaluate the BSDF for the given incoming light direction and outgoing light direction.
    pub fn f(&self, wi_w: &Vector, wo_w: &Vector, flags: BxDFType) -> Colourf {
        let wi = self.world_to_local(wi_w);
        let wo = self.world_to_local(wo_w);
        let reflect = wi_w.dot(&self.ng) * wo_w.dot(&self.ng) > 0.0;
        self.bxdfs
            .iter()
            .filter(|b| {
                // Make sure we only evaluate reflection or transmission based on whether wi and wo
                // lie in the same hemisphere.
                b.matches(flags) &&
                ((reflect && (b.get_type().contains(BSDF_REFLECTION))) ||
                 (!reflect && (b.get_type().contains(BSDF_TRANSMISSION))))
            })
            .fold(Colourf::black(), |c, b| c + b.f(&wi, &wo))
    }

    pub fn sample_f(&self,
                    wo_w: &Vector,
                    sample: (f32, f32),
                    flags: BxDFType)
                    -> (Colourf, Vector, f32) {
        if !flags.contains(BSDF_SPECULAR) {
            unimplemented!();
        }

        if flags.contains(BSDF_REFLECTION) {
            let wo = self.world_to_local(&wo_w);
            let wi = Vector::new(-wo.x, -wo.y, wo.z);
            let cos_theta_i = wi.z;
            let kr = fr_dielectric(cos_theta_i, 1.0, self.eta);
            let colour = Colourf::rgb(1.0, 1.0, 1.0) * kr / cos_theta_i.abs();

            assert!(!colour.has_nan());
            return (colour, self.local_to_world(&wi), 1.0);
        } else if flags.contains(BSDF_TRANSMISSION) {
            let wo = self.world_to_local(&wo_w);
            let entering = wo.z > 0.0;
            let (eta_i, eta_t) = if entering {
                (1.0, self.eta)
            } else {
                (self.eta, 1.0)
            };
            let n = if wo.z < 0.0 {
                -Vector::z()
            } else {
                Vector::z()
            };
            return refract(&wo, &n, eta_i / eta_t)
                .map(|wi| {
                    let cos_theta_i = wi.z;
                    let kr = fr_dielectric(cos_theta_i, 1.0, self.eta);
                    let colour = Colourf::rgb(1.0, 1.0, 1.0) * (1.0 - kr) / cos_theta_i.abs();

                    assert!(!colour.has_nan());
                    (colour, self.local_to_world(&wi), 1.0)
                })
                .unwrap_or((Colourf::black(), zero(), 0.0));
        }

        (Colourf::black(), zero(), 0.0)
    }

    fn world_to_local(&self, v: &Vector) -> Vector {
        Vector::new(v.dot(&self.ss), v.dot(&self.ts), v.dot(&self.ns))
    }

    fn local_to_world(&self, v: &Vector) -> Vector {
        Vector::new(self.ss.x * v.x + self.ts.x * v.y + self.ns.x * v.z,
                    self.ss.y * v.x + self.ts.y * v.y + self.ns.y * v.z,
                    self.ss.z * v.z + self.ts.z * v.y + self.ns.z * v.z)
    }
}

// Common geometric functions
#[inline]
pub fn cos_theta(w: &Vector) -> f32 {
    w.z
}

#[inline]
pub fn cos2_theta(w: &Vector) -> f32 {
    w.z * w.z
}

#[inline]
pub fn abs_cos_theta(w: &Vector) -> f32 {
    w.z.abs()
}

#[inline]
pub fn sin2_theta(w: &Vector) -> f32 {
    (1.0 - cos2_theta(w)).max(0.0)
}

#[inline]
pub fn sin_theta(w: &Vector) -> f32 {
    sin2_theta(w).sqrt()
}

#[inline]
pub fn tan_theta(w: &Vector) -> f32 {
    sin_theta(w) / cos_theta(w)
}

#[inline]
pub fn tan2_theta(w: &Vector) -> f32 {
    sin2_theta(w) / cos2_theta(w)
}

#[inline]
pub fn cos_phi(w: &Vector) -> f32 {
    let sin_theta = sin_theta(w);
    if sin_theta == 0.0 {
        0.0
    } else {
        na::clamp(w.x / sin_theta, -1.0, 1.0)
    }
}

#[inline]
pub fn sin_phi(w: &Vector) -> f32 {
    let sin_theta = sin_theta(w);
    if sin_theta == 0.0 {
        0.0
    } else {
        na::clamp(w.y / sin_theta, -1.0, 1.0)
    }
}

#[inline]
pub fn cos2_phi(w: &Vector) -> f32 {
    cos_phi(w) / cos_phi(w)
}

#[inline]
pub fn sin2_phi(w: &Vector) -> f32 {
    sin_phi(w) / sin_phi(w)
}

#[inline]
pub fn cos_d_phi(wa: &Vector, wb: &Vector) -> f32 {
    na::clamp((wa.x * wb.x + wa.y * wa.y) /
              ((wa.x * wa.x + wa.y * wa.y) * (wb.x * wb.x + wb.y * wb.y)).sqrt(),
              -1.0,
              1.0)
}
<commit_msg>Add same_hemisphere function<commit_after>mod bxdf;
mod fresnel;

pub use self::bxdf::*;
pub use self::fresnel::*;

use std::mem;
use na::{self, Cross, Dot, zero, Norm, clamp};

use ::{Vector, Point2f};
use colour::Colourf;
use intersection::Intersection;
use interaction::SurfaceInteraction;

bitflags! {
    pub flags BxDFType: u32 {
        const BSDF_REFLECTION   = 0b_00000001,
        const BSDF_TRANSMISSION = 0b_00000010,
        const BSDF_DIFFUSE      = 0b_00000100,
        const BSDF_GLOSSY       = 0b_00001000,
        const BSDF_SPECULAR     = 0b_00010000,
    }
}

/// Represents the Bidirectional Scattering Distribution Function.
/// It represents the properties of a material at a given point.
#[derive(Copy, Clone)]
pub struct BSDF<'a> {
    /// Index of refraction of the surface
    eta: f32,
    /// Shading normal (i.e. potentially affected by bump-mapping)
    ns: Vector,
    /// Geometry normal
    ng: Vector,
    ss: Vector,
    ts: Vector,
    bxdfs: &'a [Box<BxDF + Sync + Send>],
}

impl<'a> BSDF<'a> {
    pub fn new(isect: &SurfaceInteraction,
               eta: f32,
               bxdfs: &'a [Box<BxDF + Sync + Send>])
               -> BSDF<'a> {
        let ss = isect.dpdu.normalize();
        BSDF {
            eta: eta,
            ns: isect.shading.n,
            ng: isect.n,
            ss: ss,
            ts: isect.shading.n.cross(&ss),
            bxdfs: bxdfs,
        }
    }

    /// Evaluate the BSDF for the given incoming light direction and outgoing light direction.
    pub fn f(&self, wi_w: &Vector, wo_w: &Vector, flags: BxDFType) -> Colourf {
        let wi = self.world_to_local(wi_w);
        let wo = self.world_to_local(wo_w);
        let reflect = wi_w.dot(&self.ng) * wo_w.dot(&self.ng) > 0.0;
        self.bxdfs
            .iter()
            .filter(|b| {
                // Make sure we only evaluate reflection or transmission based on whether wi and wo
                // lie in the same hemisphere.
                b.matches(flags) &&
                ((reflect && (b.get_type().contains(BSDF_REFLECTION))) ||
                 (!reflect && (b.get_type().contains(BSDF_TRANSMISSION))))
            })
            .fold(Colourf::black(), |c, b| c + b.f(&wi, &wo))
    }

    pub fn sample_f(&self,
                    wo_w: &Vector,
                    sample: (f32, f32),
                    flags: BxDFType)
                    -> (Colourf, Vector, f32) {
        if !flags.contains(BSDF_SPECULAR) {
            unimplemented!();
        }

        if flags.contains(BSDF_REFLECTION) {
            let wo = self.world_to_local(&wo_w);
            let wi = Vector::new(-wo.x, -wo.y, wo.z);
            let cos_theta_i = wi.z;
            let kr = fr_dielectric(cos_theta_i, 1.0, self.eta);
            let colour = Colourf::rgb(1.0, 1.0, 1.0) * kr / cos_theta_i.abs();

            assert!(!colour.has_nan());
            return (colour, self.local_to_world(&wi), 1.0);
        } else if flags.contains(BSDF_TRANSMISSION) {
            let wo = self.world_to_local(&wo_w);
            let entering = wo.z > 0.0;
            let (eta_i, eta_t) = if entering {
                (1.0, self.eta)
            } else {
                (self.eta, 1.0)
            };
            let n = if wo.z < 0.0 {
                -Vector::z()
            } else {
                Vector::z()
            };
            return refract(&wo, &n, eta_i / eta_t)
                .map(|wi| {
                    let cos_theta_i = wi.z;
                    let kr = fr_dielectric(cos_theta_i, 1.0, self.eta);
                    let colour = Colourf::rgb(1.0, 1.0, 1.0) * (1.0 - kr) / cos_theta_i.abs();

                    assert!(!colour.has_nan());
                    (colour, self.local_to_world(&wi), 1.0)
                })
                .unwrap_or((Colourf::black(), zero(), 0.0));
        }

        (Colourf::black(), zero(), 0.0)
    }

    fn world_to_local(&self, v: &Vector) -> Vector {
        Vector::new(v.dot(&self.ss), v.dot(&self.ts), v.dot(&self.ns))
    }

    fn local_to_world(&self, v: &Vector) -> Vector {
        Vector::new(self.ss.x * v.x + self.ts.x * v.y + self.ns.x * v.z,
                    self.ss.y * v.x + self.ts.y * v.y + self.ns.y * v.z,
                    self.ss.z * v.z + self.ts.z * v.y + self.ns.z * v.z)
    }
}

// Common geometric functions
#[inline]
pub fn cos_theta(w: &Vector) -> f32 {
    w.z
}

#[inline]
pub fn cos2_theta(w: &Vector) -> f32 {
    w.z * w.z
}

#[inline]
pub fn abs_cos_theta(w: &Vector) -> f32 {
    w.z.abs()
}

#[inline]
pub fn sin2_theta(w: &Vector) -> f32 {
    (1.0 - cos2_theta(w)).max(0.0)
}

#[inline]
pub fn sin_theta(w: &Vector) -> f32 {
    sin2_theta(w).sqrt()
}

#[inline]
pub fn tan_theta(w: &Vector) -> f32 {
    sin_theta(w) / cos_theta(w)
}

#[inline]
pub fn tan2_theta(w: &Vector) -> f32 {
    sin2_theta(w) / cos2_theta(w)
}

#[inline]
pub fn cos_phi(w: &Vector) -> f32 {
    let sin_theta = sin_theta(w);
    if sin_theta == 0.0 {
        0.0
    } else {
        na::clamp(w.x / sin_theta, -1.0, 1.0)
    }
}

#[inline]
pub fn sin_phi(w: &Vector) -> f32 {
    let sin_theta = sin_theta(w);
    if sin_theta == 0.0 {
        0.0
    } else {
        na::clamp(w.y / sin_theta, -1.0, 1.0)
    }
}

#[inline]
pub fn cos2_phi(w: &Vector) -> f32 {
    cos_phi(w) / cos_phi(w)
}

#[inline]
pub fn sin2_phi(w: &Vector) -> f32 {
    sin_phi(w) / sin_phi(w)
}

#[inline]
pub fn cos_d_phi(wa: &Vector, wb: &Vector) -> f32 {
    na::clamp((wa.x * wb.x + wa.y * wa.y) /
              ((wa.x * wa.x + wa.y * wa.y) * (wb.x * wb.x + wb.y * wb.y)).sqrt(),
              -1.0,
              1.0)
}

#[inline]
pub fn same_hemisphere(w: &Vector, wp: &Vector) -> bool {
    w.z * wp.z > 0.0
}
<|endoftext|>