<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * 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.
 */

#[macro_export]
#[doc(hidden)]
macro_rules! check_recursion {
    ($widget:ident) => {
        if $widget.try_borrow_mut().is_err() {
            panic!("An event to the same widget was emitted in the update() method, which would cause an infinite \
                   recursion.\nThis can be caused by calling a gtk+ function that is connected to send a message \
                   to the same widget.\nInspect the stack trace to determine which call it is.\nThen you can either \
                   refactor your code to avoid a cyclic event dependency or block events from being emitted by doing \
                   the following:\n{\n    let _lock = self.model.relm.stream().lock();\n    // Your panicking call.\n}\
                   \nSee this example: \
                   https://github.com/antoyo/relm/blob/feature/futures-glib/examples/checkboxes.rs#L88\
                   This issue can also happen when emitting a signal to the same widget, in which case you need to\
                   refactor your code to avoid this cyclic event dependency.");
        }
    };
}

/// Connect events to sending a message.
///
/// Rule #1:
/// Send `$msg` to `$other_component` when the GTK+ `$event` is emitted on `$widget`.
///
/// Rule #2:
/// Optionally send `$msg.0` when the GTK+ `$event` is emitted on `$widget`.
/// Return `$msg.1` in the GTK+ callback.
/// This variant gives more control to the caller since it expects a `$msg` returning `(Option<MSG>,
/// ReturnValue)` where the `ReturnValue` is the value to return in the GTK+ callback.
/// Option<MSG> can be None if no message needs to be emitted.
///
/// Rule #3:
/// Send `$msg` when the GTK+ `$event` is emitted on `$widget`.
///
/// Rule #4:
/// Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect {
    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
        let stream = $other_component.stream().clone();
        $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    };

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), return $msg:expr) => {{
        let stream = $relm.stream().clone();
        $widget.$event(move |$($args),*| {
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    // This variant also give you a widget so that you can call a function that will use and mutate
    // its model.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), with return $widget_clone:ident $msg:expr) => {{
        let stream = $relm.stream().clone();
        #[allow(unused_mut)]
        $widget.$event(move |$($args),*| {
            let $widget_clone = $widget_clone.upgrade().expect("upgrade should always work");
            check_recursion!($widget_clone);
            let mut $widget_clone = $widget_clone.borrow_mut();
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event.
    // This variant allows to call a method that will return the message
    // Option<MSG> can be None if no message needs to be emitted.
    // This variant also give you a widget so that you can call a function that will use and mutate
    // its model.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), with $widget_clone:ident $msg:expr) => {{
        let stream = $relm.stream().clone();
        #[allow(unused_mut)]
        $widget.$event(move |$($args),*| {
            let $widget_clone = $widget_clone.upgrade().expect("upgrade should always work");
            check_recursion!($widget_clone);
            let mut $widget_clone = $widget_clone.borrow_mut();
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // This variant also give you a widget so that you can call a function that will use and mutate
    // its model.
    ($src_component:ident @ $message:pat, $dst_component:ident, with $widget:ident $msg:expr) => {
        let stream = $dst_component.stream().clone();
        $src_component.stream().observe(move |msg| {
            #[allow(unreachable_patterns, unused_mut)]
            match msg {
                &$message =>  {
                    let $widget = $widget.upgrade().expect("upgrade should always work");
                    check_recursion!($widget);
                    let mut $widget = $widget.borrow_mut();
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };

    // Connect to a GTK+ widget event where the return value is retrieved asynchronously.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), async $msg:expr) => {{
        let stream = $relm.stream().clone();
        $widget.$event(move |$($args),*| {
            let (resolver, rx) = ::relm::Resolver::channel();
            let msg: Option<_> = $crate::IntoOption::into_option($msg(resolver));
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            ::gtk::main();
            // TODO: remove unwrap().
            ::futures::Stream::wait(rx).next().unwrap().unwrap()
        });
    }};

    // Connect to a GTK+ widget event.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $relm.stream().clone();
        $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_component:ident @ $message:pat, $dst_component:ident, $msg:expr) => {
        let stream = $dst_component.stream().clone();
        $src_component.stream().observe(move |msg| {
            #[allow(unreachable_patterns)]
            match msg {
                &$message =>  {
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };
}
<commit_msg>Make the connect! macro accept an expr instead of an ident<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * 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.
 */

#[macro_export]
#[doc(hidden)]
macro_rules! check_recursion {
    ($widget:ident) => {
        if $widget.try_borrow_mut().is_err() {
            panic!("An event to the same widget was emitted in the update() method, which would cause an infinite \
                   recursion.\nThis can be caused by calling a gtk+ function that is connected to send a message \
                   to the same widget.\nInspect the stack trace to determine which call it is.\nThen you can either \
                   refactor your code to avoid a cyclic event dependency or block events from being emitted by doing \
                   the following:\n{\n    let _lock = self.model.relm.stream().lock();\n    // Your panicking call.\n}\
                   \nSee this example: \
                   https://github.com/antoyo/relm/blob/feature/futures-glib/examples/checkboxes.rs#L88\
                   This issue can also happen when emitting a signal to the same widget, in which case you need to\
                   refactor your code to avoid this cyclic event dependency.");
        }
    };
}

/// Connect events to sending a message.
///
/// Rule #1:
/// Send `$msg` to `$other_component` when the GTK+ `$event` is emitted on `$widget`.
///
/// Rule #2:
/// Optionally send `$msg.0` when the GTK+ `$event` is emitted on `$widget`.
/// Return `$msg.1` in the GTK+ callback.
/// This variant gives more control to the caller since it expects a `$msg` returning `(Option<MSG>,
/// ReturnValue)` where the `ReturnValue` is the value to return in the GTK+ callback.
/// Option<MSG> can be None if no message needs to be emitted.
///
/// Rule #3:
/// Send `$msg` when the GTK+ `$event` is emitted on `$widget`.
///
/// Rule #4:
/// Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect {
    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
        let stream = $other_component.stream().clone();
        $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    };

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), return $msg:expr) => {{
        let stream = $relm.stream().clone();
        $widget.$event(move |$($args),*| {
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    // This variant also give you a widget so that you can call a function that will use and mutate
    // its model.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), with return $widget_clone:ident $msg:expr) => {{
        let stream = $relm.stream().clone();
        #[allow(unused_mut)]
        $widget.$event(move |$($args),*| {
            let $widget_clone = $widget_clone.upgrade().expect("upgrade should always work");
            check_recursion!($widget_clone);
            let mut $widget_clone = $widget_clone.borrow_mut();
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event.
    // This variant allows to call a method that will return the message
    // Option<MSG> can be None if no message needs to be emitted.
    // This variant also give you a widget so that you can call a function that will use and mutate
    // its model.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), with $widget_clone:ident $msg:expr) => {{
        let stream = $relm.stream().clone();
        #[allow(unused_mut)]
        $widget.$event(move |$($args),*| {
            let $widget_clone = $widget_clone.upgrade().expect("upgrade should always work");
            check_recursion!($widget_clone);
            let mut $widget_clone = $widget_clone.borrow_mut();
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // This variant also give you a widget so that you can call a function that will use and mutate
    // its model.
    ($src_component:ident @ $message:pat, $dst_component:ident, with $widget:ident $msg:expr) => {
        let stream = $dst_component.stream().clone();
        $src_component.stream().observe(move |msg| {
            #[allow(unreachable_patterns, unused_mut)]
            match msg {
                &$message =>  {
                    let $widget = $widget.upgrade().expect("upgrade should always work");
                    check_recursion!($widget);
                    let mut $widget = $widget.borrow_mut();
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };

    // Connect to a GTK+ widget event where the return value is retrieved asynchronously.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), async $msg:expr) => {{
        let stream = $relm.stream().clone();
        $widget.$event(move |$($args),*| {
            let (resolver, rx) = ::relm::Resolver::channel();
            let msg: Option<_> = $crate::IntoOption::into_option($msg(resolver));
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            ::gtk::main();
            // TODO: remove unwrap().
            ::futures::Stream::wait(rx).next().unwrap().unwrap()
        });
    }};

    // Connect to a GTK+ widget event.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $relm.stream().clone();
        $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_component:ident @ $message:pat, $dst_component:expr, $msg:expr) => {
        let stream = $dst_component.stream().clone();
        $src_component.stream().observe(move |msg| {
            #[allow(unreachable_patterns)]
            match msg {
                &$message =>  {
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};

use bytes::{BufMut, Bytes, BytesMut};
use futures::{future, stream, Stream, StreamExt};
use pin_project::pin_project;
use tokio::io::AsyncRead;

/// Stream of bytes.
#[pin_project]
pub struct ByteStream {
    size_hint: Option<usize>,
    #[pin]
    inner: Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static>>,
}

impl ByteStream {
    /// Create a new `ByteStream` by wrapping a `futures` stream.
    pub fn new<S>(stream: S) -> ByteStream
    where
        S: Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static,
    {
        ByteStream {
            size_hint: None,
            inner: Box::pin(stream),
        }
    }

    /// Creates a new `ByteStream` by wrapping a `futures` stream. Allows for the addition of a
    /// size_hint to satisy S3's `PutObject` API.
    pub fn new_with_size<S>(stream: S, size_hint: usize) -> ByteStream
    where
        S: Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static,
    {
        ByteStream {
            size_hint: Some(size_hint),
            inner: Box::pin(stream),
        }
    }

    pub(crate) fn size_hint(&self) -> Option<usize> {
        self.size_hint
    }

    /// Return an implementation of `AsyncRead` that uses async i/o to consume the stream.
    pub fn into_async_read(self) -> impl AsyncRead + Send {
        ImplAsyncRead::new(self.inner)
    }

    /// Return an implementation of `Read` that uses blocking i/o to consume the stream.
    pub fn into_blocking_read(self) -> impl io::Read + Send {
        ImplBlockingRead::new(self.inner)
    }
}

impl From<Vec<u8>> for ByteStream {
    fn from(buf: Vec<u8>) -> ByteStream {
        ByteStream {
            size_hint: Some(buf.len()),
            inner: Box::pin(stream::once(async move { Ok(Bytes::from(buf)) })),
        }
    }
}

impl fmt::Debug for ByteStream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<ByteStream size_hint={:?}>", self.size_hint)
    }
}

impl Stream for ByteStream {
    type Item = Result<Bytes, io::Error>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let this = self.project();
        this.inner.poll_next(cx)
    }
}

#[pin_project]
struct ImplAsyncRead {
    buffer: BytesMut,
    #[pin]
    stream: futures::stream::Fuse<Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send>>>,
}

impl ImplAsyncRead {
    fn new(stream: Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send>>) -> Self {
        ImplAsyncRead {
            buffer: BytesMut::new(),
            stream: stream.fuse(),
        }
    }
}

impl AsyncRead for ImplAsyncRead {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        let this = self.project();
        if this.buffer.is_empty() {
            match futures::ready!(this.stream.poll_next(cx)) {
                None => return Poll::Ready(Ok(0)),
                Some(Err(e)) => return Poll::Ready(Err(e)),
                Some(Ok(bytes)) => {
                    this.buffer.put(bytes);
                }
            }
        }
        let available = std::cmp::min(buf.len(), this.buffer.len());
        let bytes = this.buffer.split_to(available);
        let (left, _) = buf.split_at_mut(available);
        left.copy_from_slice(&bytes[..available]);
        Poll::Ready(Ok(available))
    }
}

#[pin_project]
struct ImplBlockingRead {
    #[pin]
    inner: ImplAsyncRead,
}

impl ImplBlockingRead {
    fn new(stream: Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync>>) -> Self {
        ImplBlockingRead {
            inner: ImplAsyncRead::new(stream),
        }
    }
}

impl io::Read for ImplBlockingRead {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut rt = tokio::runtime::Runtime::new()?;
        rt.block_on(future::poll_fn(|cx| {
            tokio::io::AsyncRead::poll_read(Pin::new(&mut self.inner), cx, buf)
        }))
    }
}

#[tokio::test]
async fn test_async_read() {
    use bytes::Bytes;
    use tokio::io::AsyncReadExt;

    let chunks = vec![
        Ok(Bytes::from_static(b"1234")),
        Ok(Bytes::from_static(b"5678")),
    ];
    let stream = ByteStream::new(stream::iter(chunks));
    let mut async_read = stream.into_async_read();

    let mut buf = [0u8; 3];
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"123");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"4");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"567");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"8");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 0);
}

#[test]
fn test_blocking_read() {
    use bytes::Bytes;
    use std::io::Read;

    let chunks = vec![
        Ok(Bytes::from_static(b"1234")),
        Ok(Bytes::from_static(b"5678")),
    ];
    let stream = ByteStream::new(stream::iter(chunks));
    let mut async_read = stream.into_blocking_read();

    let mut buf = [0u8; 3];
    assert_eq!(async_read.read(&mut buf).unwrap(), 3);
    assert_eq!(&buf[..3], b"123");
    assert_eq!(async_read.read(&mut buf).unwrap(), 1);
    assert_eq!(&buf[..1], b"4");
    assert_eq!(async_read.read(&mut buf).unwrap(), 3);
    assert_eq!(&buf[..3], b"567");
    assert_eq!(async_read.read(&mut buf).unwrap(), 1);
    assert_eq!(&buf[..1], b"8");
    assert_eq!(async_read.read(&mut buf).unwrap(), 0);
}

#[tokio::test]
async fn test_new_with_size_read() {
    use bytes::Bytes;
    use tokio::io::AsyncReadExt;

    let chunks = vec![
        Ok(Bytes::from_static(b"1234")),
        Ok(Bytes::from_static(b"5678")),
    ];
    let stream = ByteStream::new_with_size(stream::iter(chunks), 8);

    assert_eq!(stream.size_hint, Some(8));

    let mut async_read = stream.into_async_read();

    let mut buf = [0u8; 3];
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"123");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"4");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"567");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"8");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 0);
}
<commit_msg>Add Sync bounds to Read impls<commit_after>use std::fmt;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};

use bytes::{BufMut, Bytes, BytesMut};
use futures::{future, stream, Stream, StreamExt};
use pin_project::pin_project;
use tokio::io::AsyncRead;

/// Stream of bytes.
#[pin_project]
pub struct ByteStream {
    size_hint: Option<usize>,
    #[pin]
    inner: Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static>>,
}

impl ByteStream {
    /// Create a new `ByteStream` by wrapping a `futures` stream.
    pub fn new<S>(stream: S) -> ByteStream
    where
        S: Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static,
    {
        ByteStream {
            size_hint: None,
            inner: Box::pin(stream),
        }
    }

    /// Creates a new `ByteStream` by wrapping a `futures` stream. Allows for the addition of a
    /// size_hint to satisy S3's `PutObject` API.
    pub fn new_with_size<S>(stream: S, size_hint: usize) -> ByteStream
    where
        S: Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static,
    {
        ByteStream {
            size_hint: Some(size_hint),
            inner: Box::pin(stream),
        }
    }

    pub(crate) fn size_hint(&self) -> Option<usize> {
        self.size_hint
    }

    /// Return an implementation of `AsyncRead` that uses async i/o to consume the stream.
    pub fn into_async_read(self) -> impl AsyncRead + Send + Sync {
        ImplAsyncRead::new(self.inner)
    }

    /// Return an implementation of `Read` that uses blocking i/o to consume the stream.
    pub fn into_blocking_read(self) -> impl io::Read + Send + Sync {
        ImplBlockingRead::new(self.inner)
    }
}

impl From<Vec<u8>> for ByteStream {
    fn from(buf: Vec<u8>) -> ByteStream {
        ByteStream {
            size_hint: Some(buf.len()),
            inner: Box::pin(stream::once(async move { Ok(Bytes::from(buf)) })),
        }
    }
}

impl fmt::Debug for ByteStream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<ByteStream size_hint={:?}>", self.size_hint)
    }
}

impl Stream for ByteStream {
    type Item = Result<Bytes, io::Error>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let this = self.project();
        this.inner.poll_next(cx)
    }
}

#[pin_project]
struct ImplAsyncRead {
    buffer: BytesMut,
    #[pin]
    stream: futures::stream::Fuse<Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync>>>,
}

impl ImplAsyncRead {
    fn new(stream: Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync>>) -> Self {
        ImplAsyncRead {
            buffer: BytesMut::new(),
            stream: stream.fuse(),
        }
    }
}

impl AsyncRead for ImplAsyncRead {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        let this = self.project();
        if this.buffer.is_empty() {
            match futures::ready!(this.stream.poll_next(cx)) {
                None => return Poll::Ready(Ok(0)),
                Some(Err(e)) => return Poll::Ready(Err(e)),
                Some(Ok(bytes)) => {
                    this.buffer.put(bytes);
                }
            }
        }
        let available = std::cmp::min(buf.len(), this.buffer.len());
        let bytes = this.buffer.split_to(available);
        let (left, _) = buf.split_at_mut(available);
        left.copy_from_slice(&bytes[..available]);
        Poll::Ready(Ok(available))
    }
}

#[pin_project]
struct ImplBlockingRead {
    #[pin]
    inner: ImplAsyncRead,
}

impl ImplBlockingRead {
    fn new(stream: Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync>>) -> Self {
        ImplBlockingRead {
            inner: ImplAsyncRead::new(stream),
        }
    }
}

impl io::Read for ImplBlockingRead {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut rt = tokio::runtime::Runtime::new()?;
        rt.block_on(future::poll_fn(|cx| {
            tokio::io::AsyncRead::poll_read(Pin::new(&mut self.inner), cx, buf)
        }))
    }
}

#[tokio::test]
async fn test_async_read() {
    use bytes::Bytes;
    use tokio::io::AsyncReadExt;

    let chunks = vec![
        Ok(Bytes::from_static(b"1234")),
        Ok(Bytes::from_static(b"5678")),
    ];
    let stream = ByteStream::new(stream::iter(chunks));
    let mut async_read = stream.into_async_read();

    let mut buf = [0u8; 3];
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"123");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"4");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"567");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"8");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 0);
}

#[test]
fn test_blocking_read() {
    use bytes::Bytes;
    use std::io::Read;

    let chunks = vec![
        Ok(Bytes::from_static(b"1234")),
        Ok(Bytes::from_static(b"5678")),
    ];
    let stream = ByteStream::new(stream::iter(chunks));
    let mut async_read = stream.into_blocking_read();

    let mut buf = [0u8; 3];
    assert_eq!(async_read.read(&mut buf).unwrap(), 3);
    assert_eq!(&buf[..3], b"123");
    assert_eq!(async_read.read(&mut buf).unwrap(), 1);
    assert_eq!(&buf[..1], b"4");
    assert_eq!(async_read.read(&mut buf).unwrap(), 3);
    assert_eq!(&buf[..3], b"567");
    assert_eq!(async_read.read(&mut buf).unwrap(), 1);
    assert_eq!(&buf[..1], b"8");
    assert_eq!(async_read.read(&mut buf).unwrap(), 0);
}

#[tokio::test]
async fn test_new_with_size_read() {
    use bytes::Bytes;
    use tokio::io::AsyncReadExt;

    let chunks = vec![
        Ok(Bytes::from_static(b"1234")),
        Ok(Bytes::from_static(b"5678")),
    ];
    let stream = ByteStream::new_with_size(stream::iter(chunks), 8);

    assert_eq!(stream.size_hint, Some(8));

    let mut async_read = stream.into_async_read();

    let mut buf = [0u8; 3];
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"123");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"4");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 3);
    assert_eq!(&buf[..3], b"567");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 1);
    assert_eq!(&buf[..1], b"8");
    assert_eq!(async_read.read(&mut buf).await.unwrap(), 0);
}
<|endoftext|>


<commit_before>//! Module for handling interaction content (bodies)

use std::fmt::{Display, Formatter};
use std::str::from_utf8;

use base64::encode;
use bytes::{Bytes, BytesMut};
use log::*;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use crate::content_types::{ContentType, ContentTypeHint};

/// Enum that defines the four main states that a body of a request and response can be in a pact
/// file.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
#[serde(untagged)]
pub enum OptionalBody {
  /// A body is missing if it is not present in the pact file
  Missing,
  /// An empty body that is present in the pact file.
  Empty,
  /// A JSON body that is the null value. This state is to protect other language implementations
  /// from null values. It is treated as `Empty`.
  Null,
  /// A non-empty body that is present in the pact file.
  Present(Bytes, Option<ContentType>, Option<ContentTypeHint>)
}

impl OptionalBody {

  /// If the body is present in the pact file and not empty or null.
  pub fn is_present(&self) -> bool {
    match *self {
      OptionalBody::Present(_, _, _) => true,
      _ => false
    }
  }

  /// Returns the body if present, otherwise returns the empty buffer.
  pub fn value(&self) -> Option<Bytes> {
    match self {
      OptionalBody::Present(s, _, _) => Some(s.clone()),
      _ => None
    }
  }

  /// Returns the body if present as a UTF-8 string, otherwise returns the empty string.
  pub fn str_value(&self) -> &str {
    match self {
      OptionalBody::Present(s, _, _) => from_utf8(s).unwrap_or(""),
      _ => ""
    }
  }

  /// If the body has a content type associated to it
  pub fn has_content_type(&self) -> bool {
    match self {
      OptionalBody::Present(_, content_type, _) => content_type.is_some(),
      _ => false
    }
  }

  /// Parsed content type of the body
  pub fn content_type(&self) -> Option<ContentType> {
    match self {
      OptionalBody::Present(_, content_type, _) =>
        content_type.clone(),
      _ => None
    }
  }

  /// Converts this body into a V4 Pact file JSON format
  pub fn to_v4_json(&self) -> Value {
    match self {
      OptionalBody::Present(bytes, content_type, ct_override) => {
        let content_type = content_type.as_ref().cloned().unwrap_or_default();
        let content_type_override = ct_override.unwrap_or_default();
        let (contents, encoded) = if content_type.is_json() {
          match serde_json::from_slice(bytes) {
            Ok(json_body) => (json_body, Value::Bool(false)),
            Err(err) => {
              warn!("Failed to parse json body: {}", err);
              (Value::String(encode(bytes)), Value::String("base64".to_string()))
            }
          }
        } else if content_type_override == ContentTypeHint::BINARY || content_type.is_binary() {
          (Value::String(encode(bytes)), Value::String("base64".to_string()))
        } else {
          match from_utf8(bytes) {
            Ok(s) => (Value::String(s.to_string()), Value::Bool(false)),
            Err(_) => (Value::String(encode(bytes)), Value::String("base64".to_string()))
          }
        };

        if let Some(ct_override) = ct_override {
          json!({
            "content": contents,
            "contentType": content_type.to_string(),
            "contentTypeHint": ct_override.to_string(),
            "encoded": encoded
          })
        } else {
          json!({
            "content": contents,
            "contentType": content_type.to_string(),
            "encoded": encoded
          })
        }
      },
      OptionalBody::Empty => json!({"content": ""}),
      _ => Value::Null
    }
  }
}

impl From<String> for OptionalBody {
  fn from(s: String) -> Self {
    if s.is_empty() {
      OptionalBody::Empty
    } else {
      OptionalBody::Present(Bytes::from(s), None, None)
    }
  }
}

impl <'a> From<&'a str> for OptionalBody {
  fn from(s: &'a str) -> Self {
    if s.is_empty() {
      OptionalBody::Empty
    } else {
      let mut buf = BytesMut::with_capacity(0);
      buf.extend_from_slice(s.as_bytes());
      OptionalBody::Present(buf.freeze(), None, None)
    }
  }
}

impl From<Value> for OptionalBody {
  fn from(json: Value) -> Self {
    OptionalBody::Present(Bytes::from(json.to_string()),
                          Some(ContentType::from("application/json;charset=UTF-8")),
                          None)
  }
}

impl Display for OptionalBody {
  fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
    match *self {
      OptionalBody::Missing => write!(f, "Missing"),
      OptionalBody::Empty => write!(f, "Empty"),
      OptionalBody::Null => write!(f, "Null"),
      OptionalBody::Present(ref s, ref content_type, _) => {
        if let Some(content_type) = content_type {
          write!(f, "Present({} bytes, {})", s.len(), content_type)
        } else {
          write!(f, "Present({} bytes)", s.len())
        }
      }
    }
  }
}

impl Default for OptionalBody {
  fn default() -> Self {
    OptionalBody::Missing
  }
}

#[cfg(test)]
mod tests {
  use expectest::prelude::*;

  use crate::content_types::JSON;

  use super::OptionalBody;

  #[test]
  fn display_tests() {
    expect!(format!("{}", OptionalBody::Missing)).to(be_equal_to("Missing"));
    expect!(format!("{}", OptionalBody::Empty)).to(be_equal_to("Empty"));
    expect!(format!("{}", OptionalBody::Null)).to(be_equal_to("Null"));
    expect!(format!("{}", OptionalBody::Present("hello".into(), None, None))).to(be_equal_to("Present(5 bytes)"));
    expect!(format!("{}", OptionalBody::Present("\"hello\"".into(), Some(JSON.clone()), None))).to(be_equal_to("Present(7 bytes, application/json)"));
  }
}
<commit_msg>refactor: add method to set content type of a body<commit_after>//! Module for handling interaction content (bodies)

use std::fmt::{Display, Formatter};
use std::str::from_utf8;

use base64::encode;
use bytes::{Bytes, BytesMut};
use log::*;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use crate::content_types::{ContentType, ContentTypeHint};

/// Enum that defines the four main states that a body of a request and response can be in a pact
/// file.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
#[serde(untagged)]
pub enum OptionalBody {
  /// A body is missing if it is not present in the pact file
  Missing,
  /// An empty body that is present in the pact file.
  Empty,
  /// A JSON body that is the null value. This state is to protect other language implementations
  /// from null values. It is treated as `Empty`.
  Null,
  /// A non-empty body that is present in the pact file.
  Present(Bytes, Option<ContentType>, Option<ContentTypeHint>)
}

impl OptionalBody {

  /// If the body is present in the pact file and not empty or null.
  pub fn is_present(&self) -> bool {
    match *self {
      OptionalBody::Present(_, _, _) => true,
      _ => false
    }
  }

  /// Returns the body if present, otherwise returns the empty buffer.
  pub fn value(&self) -> Option<Bytes> {
    match self {
      OptionalBody::Present(s, _, _) => Some(s.clone()),
      _ => None
    }
  }

  /// Returns the body if present as a UTF-8 string, otherwise returns the empty string.
  pub fn str_value(&self) -> &str {
    match self {
      OptionalBody::Present(s, _, _) => from_utf8(s).unwrap_or(""),
      _ => ""
    }
  }

  /// If the body has a content type associated to it
  pub fn has_content_type(&self) -> bool {
    match self {
      OptionalBody::Present(_, content_type, _) => content_type.is_some(),
      _ => false
    }
  }

  /// Parsed content type of the body
  pub fn content_type(&self) -> Option<ContentType> {
    match self {
      OptionalBody::Present(_, content_type, _) =>
        content_type.clone(),
      _ => None
    }
  }

  /// Converts this body into a V4 Pact file JSON format
  pub fn to_v4_json(&self) -> Value {
    match self {
      OptionalBody::Present(bytes, content_type, ct_override) => {
        let content_type = content_type.as_ref().cloned().unwrap_or_default();
        let content_type_override = ct_override.unwrap_or_default();
        let (contents, encoded) = if content_type.is_json() {
          match serde_json::from_slice(bytes) {
            Ok(json_body) => (json_body, Value::Bool(false)),
            Err(err) => {
              warn!("Failed to parse json body: {}", err);
              (Value::String(encode(bytes)), Value::String("base64".to_string()))
            }
          }
        } else if content_type_override == ContentTypeHint::BINARY || content_type.is_binary() {
          (Value::String(encode(bytes)), Value::String("base64".to_string()))
        } else {
          match from_utf8(bytes) {
            Ok(s) => (Value::String(s.to_string()), Value::Bool(false)),
            Err(_) => (Value::String(encode(bytes)), Value::String("base64".to_string()))
          }
        };

        if let Some(ct_override) = ct_override {
          json!({
            "content": contents,
            "contentType": content_type.to_string(),
            "contentTypeHint": ct_override.to_string(),
            "encoded": encoded
          })
        } else {
          json!({
            "content": contents,
            "contentType": content_type.to_string(),
            "encoded": encoded
          })
        }
      },
      OptionalBody::Empty => json!({"content": ""}),
      _ => Value::Null
    }
  }

  /// Set the content type of the body. If the body is missing or empty, this is a no-op.
  pub fn set_content_type(&mut self, content_type: &ContentType) {
    match self {
      OptionalBody::Present(_, ct, _) => *ct = Some(content_type.clone()),
      _ => {}
    }
  }
}

impl From<String> for OptionalBody {
  fn from(s: String) -> Self {
    if s.is_empty() {
      OptionalBody::Empty
    } else {
      OptionalBody::Present(Bytes::from(s), None, None)
    }
  }
}

impl <'a> From<&'a str> for OptionalBody {
  fn from(s: &'a str) -> Self {
    if s.is_empty() {
      OptionalBody::Empty
    } else {
      let mut buf = BytesMut::with_capacity(0);
      buf.extend_from_slice(s.as_bytes());
      OptionalBody::Present(buf.freeze(), None, None)
    }
  }
}

impl From<Value> for OptionalBody {
  fn from(json: Value) -> Self {
    OptionalBody::from(&json)
  }
}

impl From<&Value> for OptionalBody {
  fn from(json: &Value) -> Self {
    OptionalBody::Present(Bytes::from(json.to_string()),
                          Some(ContentType::from("application/json;charset=UTF-8")),
                          None)
  }
}

impl Display for OptionalBody {
  fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
    match *self {
      OptionalBody::Missing => write!(f, "Missing"),
      OptionalBody::Empty => write!(f, "Empty"),
      OptionalBody::Null => write!(f, "Null"),
      OptionalBody::Present(ref s, ref content_type, _) => {
        if let Some(content_type) = content_type {
          write!(f, "Present({} bytes, {})", s.len(), content_type)
        } else {
          write!(f, "Present({} bytes)", s.len())
        }
      }
    }
  }
}

impl Default for OptionalBody {
  fn default() -> Self {
    OptionalBody::Missing
  }
}

#[cfg(test)]
mod tests {
  use expectest::prelude::*;

  use crate::content_types::JSON;

  use super::OptionalBody;

  #[test]
  fn display_tests() {
    expect!(format!("{}", OptionalBody::Missing)).to(be_equal_to("Missing"));
    expect!(format!("{}", OptionalBody::Empty)).to(be_equal_to("Empty"));
    expect!(format!("{}", OptionalBody::Null)).to(be_equal_to("Null"));
    expect!(format!("{}", OptionalBody::Present("hello".into(), None, None))).to(be_equal_to("Present(5 bytes)"));
    expect!(format!("{}", OptionalBody::Present("\"hello\"".into(), Some(JSON.clone()), None))).to(be_equal_to("Present(7 bytes, application/json)"));
  }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Macro and helper trait for handling interrupted routines.

use std::io;

use libc::EINTR;

/// Trait for determining if a result indicates the operation was interrupted.
pub trait InterruptibleResult {
    /// Returns `true` if this result indicates the operation was interrupted and should be retried,
    /// and `false` in all other cases.
    fn is_interrupted(&self) -> bool;
}

impl InterruptibleResult for i32 {
    fn is_interrupted(&self) -> bool {
        *self == -EINTR
    }
}

impl<T> InterruptibleResult for ::Result<T> {
    fn is_interrupted(&self) -> bool {
        match self {
            &Err(e) if e.errno() == -EINTR => true,
            _ => false,
        }
    }
}

impl<T> InterruptibleResult for io::Result<T> {
    fn is_interrupted(&self) -> bool {
        match self {
            &Err(ref e) if e.kind() == io::ErrorKind::Interrupted => true,
            _ => false,
        }
    }
}

/// Macro that retries the given expression every time its result indicates it was interrupted (i.e.
/// returned `-EINTR`). This is useful for operations that are prone to being interrupted by
/// signals, such as blocking syscalls.
///
/// The given expression `$x` can return
///
/// * `i32` in which case the expression is retried if equal to `-EINTR`.
/// * `sys_util::Result` in which case the expression is retried if the `Error::errno()` is `-EINTR`.
/// * `std::io::Result` in which case the expression is retried if the `ErrorKind` is `ErrorKind::Interrupted`.
///
/// In all cases where the result does not indicate that the expression was interrupted, the result
/// is returned verbatim to the caller of this macro.
///
/// See the section titled _Interruption of system calls and library functions by signal handlers_
/// on the man page for `signal(7)` to see more information about interruptible syscalls.
///
/// To summarize, routines that use one of these syscalls _might_ need to handle `EINTR`:
///
/// * `accept(2)`
/// * `clock_nanosleep(2)`
/// * `connect(2)`
/// * `epoll_pwait(2)`
/// * `epoll_wait(2)`
/// * `fcntl(2)`
/// * `fifo(7)`
/// * `flock(2)`
/// * `futex(2)`
/// * `getrandom(2)`
/// * `inotify(7)`
/// * `io_getevents(2)`
/// * `ioctl(2)`
/// * `mq_receive(3)`
/// * `mq_send(3)`
/// * `mq_timedreceive(3)`
/// * `mq_timedsend(3)`
/// * `msgrcv(2)`
/// * `msgsnd(2)`
/// * `nanosleep(2)`
/// * `open(2)`
/// * `pause(2)`
/// * `poll(2)`
/// * `ppoll(2)`
/// * `pselect(2)`
/// * `pthread_cond_wait(3)`
/// * `pthread_mutex_lock(3)`
/// * `read(2)`
/// * `readv(2)`
/// * `recv(2)`
/// * `recvfrom(2)`
/// * `recvmmsg(2)`
/// * `recvmsg(2)`
/// * `select(2)`
/// * `sem_timedwait(3)`
/// * `sem_wait(3)`
/// * `semop(2)`
/// * `semtimedop(2)`
/// * `send(2)`
/// * `sendmsg(2)`
/// * `sendto(2)`
/// * `setsockopt(2)`
/// * `sigsuspend(2)`
/// * `sigtimedwait(2)`
/// * `sigwaitinfo(2)`
/// * `sleep(3)`
/// * `usleep(3)`
/// * `wait(2)`
/// * `wait3(2)`
/// * `wait4(2)`
/// * `waitid(2)`
/// * `waitpid(2)`
/// * `write(2)`
/// * `writev(2)`
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate sys_util;
/// # use std::io::stdin;
/// # fn main() {
/// let mut line = String::new();
/// let res = handle_eintr!(stdin().read_line(&mut line));
/// # }
/// ```
#[macro_export]
macro_rules! handle_eintr {
    ($x:expr) => (
        {
            use $crate::handle_eintr::InterruptibleResult;
            let res;
            loop {
                match $x {
                    ref v if v.is_interrupted() => continue,
                    v => {
                        res = v;
                        break;
                    }
                }
            }
            res
        }
    )
}

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

    use Error as SysError;

    #[test]
    fn i32_eintr() {
        let mut count = 3;
        {
            let mut dummy = || {
                count -= 1;
                if count > 0 { -EINTR } else { 56 }
            };
            let res = handle_eintr!(dummy());
            assert_eq!(res, 56);
        }
        assert_eq!(count, 0);
    }

    #[test]
    fn sys_eintr() {
        let mut count = 7;
        {
            let mut dummy = || {
                count -= 1;
                if count > 1 {
                    Err(SysError::new(-EINTR))
                } else {
                    Ok(101)
                }
            };
            let res = handle_eintr!(dummy());
            assert_eq!(res, Ok(101));
        }
        assert_eq!(count, 1);
    }

    #[test]
    fn io_eintr() {
        let mut count = 108;
        {
            let mut dummy = || {
                count -= 1;
                if count > 99 {
                    Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted again :("))
                } else {
                    Ok(32)
                }
            };
            let res = handle_eintr!(dummy());
            assert_eq!(res.unwrap(), 32);
        }
        assert_eq!(count, 99);
    }
}
<commit_msg>sys_util: do not treat EINTR as negative in handle_eintr<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Macro and helper trait for handling interrupted routines.

use std::io;

use libc::EINTR;

/// Trait for determining if a result indicates the operation was interrupted.
pub trait InterruptibleResult {
    /// Returns `true` if this result indicates the operation was interrupted and should be retried,
    /// and `false` in all other cases.
    fn is_interrupted(&self) -> bool;
}

impl InterruptibleResult for i32 {
    fn is_interrupted(&self) -> bool {
        *self == EINTR
    }
}

impl<T> InterruptibleResult for ::Result<T> {
    fn is_interrupted(&self) -> bool {
        match self {
            &Err(e) if e.errno() == EINTR => true,
            _ => false,
        }
    }
}

impl<T> InterruptibleResult for io::Result<T> {
    fn is_interrupted(&self) -> bool {
        match self {
            &Err(ref e) if e.kind() == io::ErrorKind::Interrupted => true,
            _ => false,
        }
    }
}

/// Macro that retries the given expression every time its result indicates it was interrupted (i.e.
/// returned `-EINTR`). This is useful for operations that are prone to being interrupted by
/// signals, such as blocking syscalls.
///
/// The given expression `$x` can return
///
/// * `i32` in which case the expression is retried if equal to `EINTR`.
/// * `sys_util::Result` in which case the expression is retried if the `Error::errno()` is `EINTR`.
/// * `std::io::Result` in which case the expression is retried if the `ErrorKind` is `ErrorKind::Interrupted`.
///
/// In all cases where the result does not indicate that the expression was interrupted, the result
/// is returned verbatim to the caller of this macro.
///
/// See the section titled _Interruption of system calls and library functions by signal handlers_
/// on the man page for `signal(7)` to see more information about interruptible syscalls.
///
/// To summarize, routines that use one of these syscalls _might_ need to handle `EINTR`:
///
/// * `accept(2)`
/// * `clock_nanosleep(2)`
/// * `connect(2)`
/// * `epoll_pwait(2)`
/// * `epoll_wait(2)`
/// * `fcntl(2)`
/// * `fifo(7)`
/// * `flock(2)`
/// * `futex(2)`
/// * `getrandom(2)`
/// * `inotify(7)`
/// * `io_getevents(2)`
/// * `ioctl(2)`
/// * `mq_receive(3)`
/// * `mq_send(3)`
/// * `mq_timedreceive(3)`
/// * `mq_timedsend(3)`
/// * `msgrcv(2)`
/// * `msgsnd(2)`
/// * `nanosleep(2)`
/// * `open(2)`
/// * `pause(2)`
/// * `poll(2)`
/// * `ppoll(2)`
/// * `pselect(2)`
/// * `pthread_cond_wait(3)`
/// * `pthread_mutex_lock(3)`
/// * `read(2)`
/// * `readv(2)`
/// * `recv(2)`
/// * `recvfrom(2)`
/// * `recvmmsg(2)`
/// * `recvmsg(2)`
/// * `select(2)`
/// * `sem_timedwait(3)`
/// * `sem_wait(3)`
/// * `semop(2)`
/// * `semtimedop(2)`
/// * `send(2)`
/// * `sendmsg(2)`
/// * `sendto(2)`
/// * `setsockopt(2)`
/// * `sigsuspend(2)`
/// * `sigtimedwait(2)`
/// * `sigwaitinfo(2)`
/// * `sleep(3)`
/// * `usleep(3)`
/// * `wait(2)`
/// * `wait3(2)`
/// * `wait4(2)`
/// * `waitid(2)`
/// * `waitpid(2)`
/// * `write(2)`
/// * `writev(2)`
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate sys_util;
/// # use std::io::stdin;
/// # fn main() {
/// let mut line = String::new();
/// let res = handle_eintr!(stdin().read_line(&mut line));
/// # }
/// ```
#[macro_export]
macro_rules! handle_eintr {
    ($x:expr) => (
        {
            use $crate::handle_eintr::InterruptibleResult;
            let res;
            loop {
                match $x {
                    ref v if v.is_interrupted() => continue,
                    v => {
                        res = v;
                        break;
                    }
                }
            }
            res
        }
    )
}

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

    use Error as SysError;

    #[test]
    fn i32_eintr() {
        let mut count = 3;
        {
            let mut dummy = || {
                count -= 1;
                if count > 0 { EINTR } else { 0 }
            };
            let res = handle_eintr!(dummy());
            assert_eq!(res, 0);
        }
        assert_eq!(count, 0);
    }

    #[test]
    fn sys_eintr() {
        let mut count = 7;
        {
            let mut dummy = || {
                count -= 1;
                if count > 1 {
                    Err(SysError::new(EINTR))
                } else {
                    Ok(101)
                }
            };
            let res = handle_eintr!(dummy());
            assert_eq!(res, Ok(101));
        }
        assert_eq!(count, 1);
    }

    #[test]
    fn io_eintr() {
        let mut count = 108;
        {
            let mut dummy = || {
                count -= 1;
                if count > 99 {
                    Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted again :("))
                } else {
                    Ok(32)
                }
            };
            let res = handle_eintr!(dummy());
            assert_eq!(res.unwrap(), 32);
        }
        assert_eq!(count, 99);
    }
}
<|endoftext|>


<commit_before>//! ping test handler
use iron::{Handler, Request, Response, IronResult};
use iron::status;

pub struct Ping;

impl Handler for Ping {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Ok, format!("Pong!"))))
    }
}
<commit_msg>Refactored ping function.<commit_after>//! ping test handler
use iron::status;
use iron::prelude::*;

use services::storage::DbPooledConnection;

pub fn ping(_: &mut Request, _: DbPooledConnection) -> IronResult<Response> {
    Ok(Response::with((status::Ok, format!("Pong!"))))
}
<|endoftext|>


<commit_before>extern crate futures_await as futures;
#[macro_use]
extern crate reql;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate tokio;

use futures::stream::Stream;
use reql::{Client, Document, Run};
use slog::Drain;

fn main() {
    // Build an output drain
    let plain = slog_term::PlainSyncDecorator::new(std::io::stdout());
    let drain = slog_term::FullFormat::new(plain).build();

    // Setup a logger
    let logger = slog::Logger::root(drain.fuse(), o!());

    // Create a new ReQL client with the logger
    let r = Client::new().with_logger(logger);

    // Create a connection pool
    let conn = r.connect(args!({servers: ["localhost"]}))
        .unwrap();

    // Run the query
    let sequence1 = json!([100, 200, 300, 400]);
    let sequence2 = json!([10, 20, 30, 40]);
    let sequence3 = json!([1, 2, 3, 4]);

    let sum = r.map(args!(sequence1, sequence2, sequence3, |val1, val2, val3| {
        val1.add(val2).add(val3)
    }))
        .run::<[i32; 4]>(conn)
        .unwrap();

    // Process results
    for res in sum.wait() {
        match res {
            Ok(Some(Document::Expected(sum))) => {
                println!("{:?}", sum);
            }
            Ok(res) => {
                println!("unexpected response from DB: {:?}", res);
            }
            Err(error) => {
                println!("{:?}", error);
            }
        }
    }
}
<commit_msg>Update map example<commit_after>extern crate futures_await as futures;
#[macro_use]
extern crate reql;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate slog;
extern crate slog_term;

use futures::executor::block_on;
use futures::StreamExt;
use reql::{Client, Document, Run};
use slog::Drain;

fn main() {
    // Build an output drain
    let plain = slog_term::PlainSyncDecorator::new(std::io::stdout());
    let drain = slog_term::FullFormat::new(plain).build();

    // Setup a logger
    let logger = slog::Logger::root(drain.fuse(), o!());

    // Create a new ReQL client with the logger
    let r = Client::new().with_logger(logger);

    // Create a connection pool
    let conn = r.connect(args!({servers: ["localhost"]}))
        .unwrap();

    // Run the query
    let sequence1 = json!([100, 200, 300, 400]);
    let sequence2 = json!([10, 20, 30, 40]);
    let sequence3 = json!([1, 2, 3, 4]);

    let sum = r.map(args!(sequence1, sequence2, sequence3, |val1, val2, val3| {
        val1.add(val2).add(val3)
    }))
    .run::<[i32; 4]>(conn)
        .unwrap();

    // Process results
    match block_on(sum.into_future()).unwrap().0.unwrap() {
        Some(Document::Expected(sum)) => {
            println!("{:?}", sum);
        }
        res => {
            println!("unexpected response from DB: {:?}", res);
        }
    }
}
<|endoftext|>


<commit_before>
extern crate bincode;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate three;

#[derive(Clone, Debug, Deserialize, Serialize)]
struct Model<'a> {
    positions: Vec<[f32; 3]>,
    normals: Vec<[f32; 3]>,
    tangents: Vec<[f32; 4]>,
    tex_coords: Vec<[f32; 2]>,
    faces: Vec<[u16; 3]>,

    base_color_factor: [f32; 4],
    metallic_roughness: [f32; 2],
    emissive_factor: [f32; 3],
    normal_scale: f32,
    occlusion_strength: f32,
    #[serde(borrow)]
    base_color_map: Option<&'a str>,
    #[serde(borrow)]
    normal_map: Option<&'a str>,
    #[serde(borrow)]
    metallic_roughness_map: Option<&'a str>,
    #[serde(borrow)]
    emissive_map: Option<&'a str>,
    #[serde(borrow)]
    occlusion_map: Option<&'a str>,
}

fn main() {
    let mut win = three::Window::new("Three-rs PBR example", "data/shaders").build();
    let mut cam = win.factory.perspective_camera(75.0, 0.1, 1.0);
    cam.set_position([0.0, 0.0, 0.15]);

    let mut light = win.factory.point_light(0xffffff, 0.5);
    let pos = [0.0, 5.0, 5.0];
    light.set_position(pos);
    win.scene.add(&light);

    let model_data = {
        use std::io::Read;
        let mut buffer = vec![];
        let file = std::fs::File::open("test_data/Avocado.model").unwrap();
        let _ = std::io::BufReader::new(file).read_to_end(&mut buffer).unwrap();
        buffer
    };
    let model: Model = bincode::deserialize(&model_data).unwrap();

    let geometry = three::Geometry {
        base_shape: three::GeometryShape {
            vertices: model.positions.iter().cloned().map(|x| x.into()).collect(),
            normals: model.normals.iter().cloned().map(|x| x.into()).collect(),
            tangents: model.tangents.iter().cloned().map(|x| x.into()).collect(),
            tex_coords: model.tex_coords.iter().cloned().map(|x| [x[0], -x[1]].into()).collect(),
        },
        faces: model.faces.clone(),
        ..three::Geometry::empty()
    };
    let material = three::Material::MeshPbr {
        base_color_factor: model.base_color_factor,
        metallic_roughness: model.metallic_roughness,
        emissive_factor: model.emissive_factor,
        normal_scale: model.normal_scale,
        base_color_map: model.base_color_map.map(|x| win.factory.load_texture(x)),
        normal_map: model.normal_map.map(|x| win.factory.load_texture(x)),
        metallic_roughness_map: model.metallic_roughness_map
            .map(|x| win.factory.load_texture(x)),
        emissive_map: model.emissive_map.map(|x| win.factory.load_texture(x)),
        occlusion_map: model.occlusion_map.map(|x| win.factory.load_texture(x)),
        occlusion_strength: model.occlusion_strength,
    };
    let mesh = win.factory.mesh(geometry, material);
    win.scene.add(&mesh);

    let mut yaw: f32 = 0.0;
    while win.update() && !three::KEY_ESCAPE.is_hit(&win.input) {
        if three::Button::Key(three::Key::Left).is_hit(&win.input) {
            yaw -= 0.1;
        }
        if three::Button::Key(three::Key::Right).is_hit(&win.input) {
            yaw += 0.1;
        }
        let (x, y, z) = (yaw.sin(), 0.0, yaw.cos());
        cam.look_at(
            [0.15 * x, y, 0.15 * z],
            [0.0, 0.0, 0.0],
            Some([0.0, 1.0, 0.0].into()),
        );
        win.render(&cam);
    }
}
<commit_msg>Add lighter background to PBR example<commit_after>
extern crate bincode;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate three;

#[derive(Clone, Debug, Deserialize, Serialize)]
struct Model<'a> {
    positions: Vec<[f32; 3]>,
    normals: Vec<[f32; 3]>,
    tangents: Vec<[f32; 4]>,
    tex_coords: Vec<[f32; 2]>,
    faces: Vec<[u16; 3]>,

    base_color_factor: [f32; 4],
    metallic_roughness: [f32; 2],
    emissive_factor: [f32; 3],
    normal_scale: f32,
    occlusion_strength: f32,
    #[serde(borrow)]
    base_color_map: Option<&'a str>,
    #[serde(borrow)]
    normal_map: Option<&'a str>,
    #[serde(borrow)]
    metallic_roughness_map: Option<&'a str>,
    #[serde(borrow)]
    emissive_map: Option<&'a str>,
    #[serde(borrow)]
    occlusion_map: Option<&'a str>,
}

fn main() {
    let mut win = three::Window::new("Three-rs PBR example", "data/shaders").build();
    let mut cam = win.factory.perspective_camera(75.0, 0.1, 1.0);
    cam.set_position([0.0, 0.0, 0.15]);

    let mut light = win.factory.point_light(0xffffff, 0.5);
    let pos = [0.0, 5.0, 5.0];
    light.set_position(pos);
    win.scene.add(&light);
    win.scene.background = three::Background::Color(0xC6F0FF);

    let model_data = {
        use std::io::Read;
        let mut buffer = vec![];
        let file = std::fs::File::open("test_data/Avocado.model").unwrap();
        let _ = std::io::BufReader::new(file).read_to_end(&mut buffer).unwrap();
        buffer
    };
    let model: Model = bincode::deserialize(&model_data).unwrap();

    let geometry = three::Geometry {
        base_shape: three::GeometryShape {
            vertices: model.positions.iter().cloned().map(|x| x.into()).collect(),
            normals: model.normals.iter().cloned().map(|x| x.into()).collect(),
            tangents: model.tangents.iter().cloned().map(|x| x.into()).collect(),
            tex_coords: model.tex_coords.iter().cloned().map(|x| [x[0], -x[1]].into()).collect(),
        },
        faces: model.faces.clone(),
        ..three::Geometry::empty()
    };
    let material = three::Material::MeshPbr {
        base_color_factor: model.base_color_factor,
        metallic_roughness: model.metallic_roughness,
        emissive_factor: model.emissive_factor,
        normal_scale: model.normal_scale,
        base_color_map: model.base_color_map.map(|x| win.factory.load_texture(x)),
        normal_map: model.normal_map.map(|x| win.factory.load_texture(x)),
        metallic_roughness_map: model.metallic_roughness_map
            .map(|x| win.factory.load_texture(x)),
        emissive_map: model.emissive_map.map(|x| win.factory.load_texture(x)),
        occlusion_map: model.occlusion_map.map(|x| win.factory.load_texture(x)),
        occlusion_strength: model.occlusion_strength,
    };
    let mesh = win.factory.mesh(geometry, material);
    win.scene.add(&mesh);

    let mut yaw: f32 = 0.0;
    while win.update() && !three::KEY_ESCAPE.is_hit(&win.input) {
        if three::Button::Key(three::Key::Left).is_hit(&win.input) {
            yaw -= 0.1;
        }
        if three::Button::Key(three::Key::Right).is_hit(&win.input) {
            yaw += 0.1;
        }
        let (x, y, z) = (yaw.sin(), 0.0, yaw.cos());
        cam.look_at(
            [0.15 * x, y, 0.15 * z],
            [0.0, 0.0, 0.0],
            Some([0.0, 1.0, 0.0].into()),
        );
        win.render(&cam);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::cmp::{max, min};
use world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS};
use super::{AxialType, DefaultFloat, Point2f};
use std::ops::{Add, Div, Index, IndexMut, Mul, Rem, Sub};
use math::cgmath::{Array, EuclideanSpace, MetricSpace};
use super::AxialVector;
/// A 2-dimensional point in axial coordinates. See [here][hex-blog] for more
/// information.
///
/// [hex-blog]: http://www.redblobgames.com/grids/hexagons/#coordinates
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, packed)]
pub struct AxialPoint {
    pub q: AxialType,
    pub r: AxialType,
}
// TODO: implement cgmath::Array
// TODO: implement cgmath::MatricSpace
// TODO: implement cgmath::EuclideanSpace
// TODO: implement ops::{ ... }
// For all of the above, see
// http://bjz.github.io/cgmath/cgmath/struct.Point2.html
//
impl AxialPoint {
    pub fn new(q: AxialType, r: AxialType) -> Self {
        AxialPoint { q: q, r: r }
    }
    /// Returns the position of the hexagons center in the standard coordinate
    /// system using `world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS}`.
    pub fn to_real(&self) -> Point2f {
        Point2f {
            x: ((2 * self.q + self.r) as DefaultFloat) * HEX_INNER_RADIUS,
            y: (self.r as DefaultFloat) * (3.0 / 2.0) * HEX_OUTER_RADIUS,
        }
    }
    /// Returns the `s` component of corresponding cube coordinates. In cube
    /// coordinates 'q + r + s = 0', so saving `s` is redundant and can be
    /// calculated on the fly when needed.
    pub fn s(&self) -> AxialType {
        -self.q - self.r
    }
}
impl fmt::Debug for AxialPoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("")
            .field(&self.q)
            .field(&self.r)
            .finish()
    }
}
/// ********************Basic Arithmetics************
impl Add<AxialVector> for AxialPoint {
    type Output = AxialPoint;
    fn add(self, rhs: AxialVector) -> AxialPoint {
        AxialPoint {
            q: self.q + rhs.q,
            r: self.r + rhs.r,
        }
    }
}
impl Sub<AxialPoint> for AxialPoint {
    type Output = AxialVector;
    fn sub(self, rhs: AxialPoint) -> AxialVector {
        AxialVector {
            q: self.q - rhs.q,
            r: self.r - rhs.r,
        }
    }
}
impl Mul<AxialType> for AxialPoint {
    type Output = AxialPoint;
    fn mul(self, rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q * rhs,
            r: self.r * rhs,
        }
    }
}
impl Div<AxialType> for AxialPoint {
    type Output = AxialPoint;
    fn div(self, rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q / rhs,
            r: self.r / rhs,
        }
    }
}
impl Rem<AxialType> for AxialPoint {
    type Output = AxialPoint;
    fn rem(self, d: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q % d,
            r: self.r % d,
        }
    }
}
/// ********************Index************
impl Index<usize> for AxialPoint {
    type Output = AxialType;
    fn index(&self, index: usize) -> &AxialType {
        match index {
            0 => &self.q,
            1 => &self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}
impl IndexMut<usize> for AxialPoint {
    fn index_mut(&mut self, index: usize) -> &mut AxialType {
        match index {
            0 => &mut self.q,
            1 => &mut self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}
/// ********************Array************
impl Array for AxialPoint {
    type Element = AxialType;
    fn from_value(x: AxialType) -> AxialPoint {
        AxialPoint { q: x, r: x }
    }
    fn sum(self) -> AxialType {
        self.q + self.r
    }
    fn product(self) -> AxialType {
        self.q * self.r
    }
    fn min(self) -> AxialType {
        min(self.q, self.r)
    }
    fn max(self) -> AxialType {
        max(self.q, self.r)
    }
}
/// ******************* Metric-Space************************
impl MetricSpace for AxialPoint {
    type Metric = f32;
    fn distance2(self, other: AxialPoint) -> Self::Metric {
        (((self.q - other.q) * (self.q - other.q)) +
         ((self.r - other.r) * (self.r - other.r))) as f32
    }
}
/// ******************* EuclideanSpace**********************
impl EuclideanSpace for AxialPoint {
    type Scalar = i32;
    type Diff = AxialVector;
    fn origin() -> Self {
        AxialPoint { q: 0, r: 0 }
    }
    fn from_vec(v: Self::Diff) -> Self {
        AxialPoint { q: v.q, r: v.r }
    }
    fn to_vec(self) -> Self::Diff {
        AxialVector {
            q: self.q,
            r: self.r,
        }
    }
    fn dot(self, v: Self::Diff) -> Self::Scalar {
        (self.q * v.q) + (self.r * v.r)
    }
}

#[test]
fn arithmetic_test_point() {
    let a: AxialPoint = AxialPoint { q: 5, r: 7 };
    let b: AxialPoint = AxialPoint { q: -2, r: 0 };
    let v: AxialVector = AxialVector { q: 8, r: 1 };
    assert!(a.add(v) == AxialPoint { q: 13, r: 8 });
    assert!(a.sub(b) == AxialVector { q: 7, r: 7 });
    assert!(b.mul(4) == AxialPoint { q: -8, r: 0 });
    assert!(b.div(2) == AxialPoint { q: -1, r: 0 });
    assert!(a.rem(3) == AxialPoint { q: 2, r: 1 });
}
#[test]
fn index_test_point() {
    let a: AxialPoint = AxialPoint { q: 5, r: 7 };
    let mut b: AxialPoint = AxialPoint { q: -2, r: 0 };
    assert!(a[0] == 5);
    assert!(a[1] == 7);
    b[0] = 5;
    b[1] = 5;
    assert!(b.q == 5 && b.r == 5);
}
#[test]
fn array_test_point() {
    let a = AxialPoint::from_value(7);
    let b: AxialPoint = AxialPoint { q: 5, r: 7 };
    assert!(a.q == 7 && a.r == 7);
    assert!(a.sum() == 14);
    assert!(a.product() == 49);
    assert!(b.min() == 5);
    assert!(b.max() == 7);
}
#[test]
fn meticspace_test_point() {
    let a = AxialPoint { q: 0, r: 0 };
    let b = AxialPoint { q: 1, r: 1 };
    assert!(a.distance2(b) == 2.0);
}
#[test]
fn euclideanspace_test_point() {
    let v: AxialVector = AxialVector { q: 8, r: 1 };
    let a = AxialPoint { q: 1, r: 1 };
    assert!(AxialPoint::from_vec(v) == AxialPoint { q: 8, r: 1 });
    assert!(a.to_vec() == AxialVector { q: 1, r: 1 });
    assert!(a.dot(v) == 9);
}
<commit_msg>Close #68<commit_after>use std::fmt;
use std::cmp::{max, min};
use world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS};
use super::{AxialType, DefaultFloat, Point2f};
use std::ops::{Add, Div, Index, IndexMut, Mul, Rem, Sub};
use math::cgmath::{Array, EuclideanSpace, MetricSpace};
use super::AxialVector;
/// A 2-dimensional point in axial coordinates. See [here][hex-blog] for more
/// information.
///
/// [hex-blog]: http://www.redblobgames.com/grids/hexagons/#coordinates
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, packed)]
pub struct AxialPoint {
    pub q: AxialType,
    pub r: AxialType,
}
// TODO: implement cgmath::Array
// TODO: implement cgmath::MatricSpace
// TODO: implement cgmath::EuclideanSpace
// TODO: implement ops::{ ... }
// For all of the above, see
// http://bjz.github.io/cgmath/cgmath/struct.Point2.html
//
impl AxialPoint {
    pub fn new(q: AxialType, r: AxialType) -> Self {
        AxialPoint { q: q, r: r }
    }
    /// Returns the position of the hexagons center in the standard coordinate
    /// system using `world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS}`.
    pub fn to_real(&self) -> Point2f {
        Point2f {
            x: ((2 * self.q + self.r) as DefaultFloat) * HEX_INNER_RADIUS,
            y: (self.r as DefaultFloat) * (3.0 / 2.0) * HEX_OUTER_RADIUS,
        }
    }
    /// Return the AxailPoint from a Point2f
    pub fn from_real(real: Point2f) -> Self {
        let q: f32 = (real.x * ::math::SQRT_3 / 3.0 - real.y / 3.0) / HEX_OUTER_RADIUS;
        let r: f32 = (real.y * 2.0 / 3.0) / HEX_OUTER_RADIUS;

        let y: f32 = -q - r;

        // Rounding
        let mut rx: i32 = (q + 0.5) as i32;
        let ry: i32 = (y + 0.5) as i32;
        let mut rz: i32 = (r + 0.5) as i32;

        // To test the right rounding
        let x_diff = (rx as f32 - q).abs();
        let y_diff = (ry as f32 - y).abs();
        let z_diff = (rz as f32 - r).abs();
        if x_diff > y_diff && x_diff > z_diff {
            rx = -ry - rz;
        } else if !(y_diff > z_diff) {
            rz = -rx - ry;
        }

        AxialPoint { q: rx, r: rz }
    }
    /// Returns the `s` component of corresponding cube coordinates. In cube
    /// coordinates 'q + r + s = 0', so saving `s` is redundant and can be
    /// calculated on the fly when needed.
    pub fn s(&self) -> AxialType {
        -self.q - self.r
    }
}
impl fmt::Debug for AxialPoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("")
            .field(&self.q)
            .field(&self.r)
            .finish()
    }
}
/// ********************Basic Arithmetics************
impl Add<AxialVector> for AxialPoint {
    type Output = AxialPoint;
    fn add(self, rhs: AxialVector) -> AxialPoint {
        AxialPoint {
            q: self.q + rhs.q,
            r: self.r + rhs.r,
        }
    }
}
impl Sub<AxialPoint> for AxialPoint {
    type Output = AxialVector;
    fn sub(self, rhs: AxialPoint) -> AxialVector {
        AxialVector {
            q: self.q - rhs.q,
            r: self.r - rhs.r,
        }
    }
}
impl Mul<AxialType> for AxialPoint {
    type Output = AxialPoint;
    fn mul(self, rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q * rhs,
            r: self.r * rhs,
        }
    }
}
impl Div<AxialType> for AxialPoint {
    type Output = AxialPoint;
    fn div(self, rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q / rhs,
            r: self.r / rhs,
        }
    }
}
impl Rem<AxialType> for AxialPoint {
    type Output = AxialPoint;
    fn rem(self, d: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q % d,
            r: self.r % d,
        }
    }
}
/// ********************Index************
impl Index<usize> for AxialPoint {
    type Output = AxialType;
    fn index(&self, index: usize) -> &AxialType {
        match index {
            0 => &self.q,
            1 => &self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}
impl IndexMut<usize> for AxialPoint {
    fn index_mut(&mut self, index: usize) -> &mut AxialType {
        match index {
            0 => &mut self.q,
            1 => &mut self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}
/// ********************Array************
impl Array for AxialPoint {
    type Element = AxialType;
    fn from_value(x: AxialType) -> AxialPoint {
        AxialPoint { q: x, r: x }
    }
    fn sum(self) -> AxialType {
        self.q + self.r
    }
    fn product(self) -> AxialType {
        self.q * self.r
    }
    fn min(self) -> AxialType {
        min(self.q, self.r)
    }
    fn max(self) -> AxialType {
        max(self.q, self.r)
    }
}
/// ******************* Metric-Space************************
impl MetricSpace for AxialPoint {
    type Metric = f32;
    fn distance2(self, other: AxialPoint) -> Self::Metric {
        (((self.q - other.q) * (self.q - other.q)) +
         ((self.r - other.r) * (self.r - other.r))) as f32
    }
}
/// ******************* EuclideanSpace**********************
impl EuclideanSpace for AxialPoint {
    type Scalar = i32;
    type Diff = AxialVector;
    fn origin() -> Self {
        AxialPoint { q: 0, r: 0 }
    }
    fn from_vec(v: Self::Diff) -> Self {
        AxialPoint { q: v.q, r: v.r }
    }
    fn to_vec(self) -> Self::Diff {
        AxialVector {
            q: self.q,
            r: self.r,
        }
    }
    fn dot(self, v: Self::Diff) -> Self::Scalar {
        (self.q * v.q) + (self.r * v.r)
    }
}

#[test]
fn arithmetic_test_point() {
    let a: AxialPoint = AxialPoint { q: 5, r: 7 };
    let b: AxialPoint = AxialPoint { q: -2, r: 0 };
    let v: AxialVector = AxialVector { q: 8, r: 1 };
    assert!(a.add(v) == AxialPoint { q: 13, r: 8 });
    assert!(a.sub(b) == AxialVector { q: 7, r: 7 });
    assert!(b.mul(4) == AxialPoint { q: -8, r: 0 });
    assert!(b.div(2) == AxialPoint { q: -1, r: 0 });
    assert!(a.rem(3) == AxialPoint { q: 2, r: 1 });
}
#[test]
fn index_test_point() {
    let a: AxialPoint = AxialPoint { q: 5, r: 7 };
    let mut b: AxialPoint = AxialPoint { q: -2, r: 0 };
    assert!(a[0] == 5);
    assert!(a[1] == 7);
    b[0] = 5;
    b[1] = 5;
    assert!(b.q == 5 && b.r == 5);
}
#[test]
fn array_test_point() {
    let a = AxialPoint::from_value(7);
    let b: AxialPoint = AxialPoint { q: 5, r: 7 };
    assert!(a.q == 7 && a.r == 7);
    assert!(a.sum() == 14);
    assert!(a.product() == 49);
    assert!(b.min() == 5);
    assert!(b.max() == 7);
}
#[test]
fn meticspace_test_point() {
    let a = AxialPoint { q: 0, r: 0 };
    let b = AxialPoint { q: 1, r: 1 };
    assert!(a.distance2(b) == 2.0);
}
#[test]
fn euclideanspace_test_point() {
    let v: AxialVector = AxialVector { q: 8, r: 1 };
    let a = AxialPoint { q: 1, r: 1 };
    assert!(AxialPoint::from_vec(v) == AxialPoint { q: 8, r: 1 });
    assert!(a.to_vec() == AxialVector { q: 1, r: 1 });
    assert!(a.dot(v) == 9);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::callback::ReportExceptions;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived};
use dom::bindings::js::{JSRef, OptionalSettable, OptionalRootable, Root};
use dom::eventtarget::{Capturing, Bubbling, EventTarget};
use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing, EventMethods};
use dom::node::{Node, NodeHelpers};
use dom::virtualmethods::vtable_for;

// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
                              pseudo_target: Option<JSRef<'b, EventTarget>>,
                              event: &mut JSRef<Event>) -> bool {
    assert!(!event.deref().dispatching);

    {
        let event = event.deref_mut();
        event.target.assign(Some(match pseudo_target {
            Some(pseudo_target) => pseudo_target,
            None => target.clone(),
        }));
        event.dispatching = true;
    }

    let type_ = event.deref().type_.clone();

    //TODO: no chain if not participating in a tree
    let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() {
        let target_node: &JSRef<Node> = NodeCast::to_ref(target).unwrap();
        target_node.ancestors().map(|ancestor| {
            let ancestor_target: &JSRef<EventTarget> = EventTargetCast::from_ref(&ancestor);
            ancestor_target.unrooted().root()
        }).collect()
    } else {
        vec!()
    };

    event.deref_mut().phase = PhaseCapturing;

    //FIXME: The "callback this value" should be currentTarget

    /* capturing */
    for cur_target in chain.as_slice().iter().rev() {
        let stopped = match cur_target.get_listeners_for(type_, Capturing) {
            Some(listeners) => {
                event.current_target.assign(Some(cur_target.deref().clone()));
                for listener in listeners.iter() {
                    //FIXME: this should have proper error handling, or explicitly
                    //       drop the exception on the floor
                    assert!(listener.HandleEvent_(&**cur_target, event, ReportExceptions).is_ok());

                    if event.deref().stop_immediate {
                        break;
                    }
                }

                event.deref().stop_propagation
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.deref().stop_propagation {
        {
            let event = event.deref_mut();
            event.phase = PhaseAtTarget;
            event.current_target.assign(Some(target.clone()));
        }

        let opt_listeners = target.deref().get_listeners(type_);
        for listeners in opt_listeners.iter() {
            for listener in listeners.iter() {
                //FIXME: this should have proper error handling, or explicitly drop the
                //       exception on the floor.
                assert!(listener.HandleEvent_(target, event, ReportExceptions).is_ok());
                if event.deref().stop_immediate {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.deref().bubbles && !event.deref().stop_propagation {
        event.deref_mut().phase = PhaseBubbling;

        for cur_target in chain.iter() {
            let stopped = match cur_target.deref().get_listeners_for(type_, Bubbling) {
                Some(listeners) => {
                    event.deref_mut().current_target.assign(Some(cur_target.deref().clone()));
                    for listener in listeners.iter() {
                        //FIXME: this should have proper error handling or explicitly
                        //       drop exceptions on the floor.
                        assert!(listener.HandleEvent_(&**cur_target, event, ReportExceptions).is_ok());

                        if event.deref().stop_immediate {
                            break;
                        }
                    }

                    event.deref().stop_propagation
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }

    /* default action */
    let target = event.GetTarget().root();
    match target {
        Some(mut target) => {
            let node: Option<&mut JSRef<Node>> = NodeCast::to_mut_ref(&mut *target);
            match node {
                Some(node) =>{
                    let vtable = vtable_for(node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    // Root ordering restrictions mean we need to unroot the chain entries
    // in the same order they were rooted.
    while chain.len() > 0 {
        let _ = chain.pop();
    }

    event.dispatching = false;
    event.phase = PhaseNone;
    event.current_target.set(None);

    !event.DefaultPrevented()
}
<commit_msg>Drop event listener exceptions on the floor.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::callback::ReportExceptions;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived};
use dom::bindings::js::{JSRef, OptionalSettable, OptionalRootable, Root};
use dom::eventtarget::{Capturing, Bubbling, EventTarget};
use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing, EventMethods};
use dom::node::{Node, NodeHelpers};
use dom::virtualmethods::vtable_for;

// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
                              pseudo_target: Option<JSRef<'b, EventTarget>>,
                              event: &mut JSRef<Event>) -> bool {
    assert!(!event.deref().dispatching);

    {
        let event = event.deref_mut();
        event.target.assign(Some(match pseudo_target {
            Some(pseudo_target) => pseudo_target,
            None => target.clone(),
        }));
        event.dispatching = true;
    }

    let type_ = event.deref().type_.clone();

    //TODO: no chain if not participating in a tree
    let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() {
        let target_node: &JSRef<Node> = NodeCast::to_ref(target).unwrap();
        target_node.ancestors().map(|ancestor| {
            let ancestor_target: &JSRef<EventTarget> = EventTargetCast::from_ref(&ancestor);
            ancestor_target.unrooted().root()
        }).collect()
    } else {
        vec!()
    };

    event.deref_mut().phase = PhaseCapturing;

    //FIXME: The "callback this value" should be currentTarget

    /* capturing */
    for cur_target in chain.as_slice().iter().rev() {
        let stopped = match cur_target.get_listeners_for(type_, Capturing) {
            Some(listeners) => {
                event.current_target.assign(Some(cur_target.deref().clone()));
                for listener in listeners.iter() {
                    // Explicitly drop any exception on the floor.
                    let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);

                    if event.deref().stop_immediate {
                        break;
                    }
                }

                event.deref().stop_propagation
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.deref().stop_propagation {
        {
            let event = event.deref_mut();
            event.phase = PhaseAtTarget;
            event.current_target.assign(Some(target.clone()));
        }

        let opt_listeners = target.deref().get_listeners(type_);
        for listeners in opt_listeners.iter() {
            for listener in listeners.iter() {
                // Explicitly drop any exception on the floor.
                let _ = listener.HandleEvent_(target, event, ReportExceptions);

                if event.deref().stop_immediate {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.deref().bubbles && !event.deref().stop_propagation {
        event.deref_mut().phase = PhaseBubbling;

        for cur_target in chain.iter() {
            let stopped = match cur_target.deref().get_listeners_for(type_, Bubbling) {
                Some(listeners) => {
                    event.deref_mut().current_target.assign(Some(cur_target.deref().clone()));
                    for listener in listeners.iter() {
                        // Explicitly drop any exception on the floor.
                        let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);

                        if event.deref().stop_immediate {
                            break;
                        }
                    }

                    event.deref().stop_propagation
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }

    /* default action */
    let target = event.GetTarget().root();
    match target {
        Some(mut target) => {
            let node: Option<&mut JSRef<Node>> = NodeCast::to_mut_ref(&mut *target);
            match node {
                Some(node) =>{
                    let vtable = vtable_for(node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    // Root ordering restrictions mean we need to unroot the chain entries
    // in the same order they were rooted.
    while chain.len() > 0 {
        let _ = chain.pop();
    }

    event.dispatching = false;
    event.phase = PhaseNone;
    event.current_target.set(None);

    !event.DefaultPrevented()
}
<|endoftext|>


<commit_before>//! Parse `.proto` files.
//!
//! Files can be parsed using pure Rust parser (mod `pure`)
//! or using the `protoc` command (mod `protoc`).

mod case_convert;
mod linked_hash_map;
mod parse_and_typecheck;
mod parser;
mod path;
mod proto;
mod proto_path;
mod protobuf_abs_path;
mod protobuf_ident;
mod protobuf_path;
mod protobuf_rel_path;
pub mod protoc;
pub mod pure;
mod rel_path;
mod test_against_protobuf_protos;
mod which_parser;

// Public API
// Non-public API used by codegen crate.
pub use case_convert::*;
pub use parse_and_typecheck::*;
pub use proto_path::*;
pub use protobuf_abs_path::*;
pub use protobuf_ident::*;
pub use protobuf_rel_path::*;
pub use which_parser::*;

use crate::pure::model;

#[derive(Clone)]
pub(crate) struct FileDescriptorPair {
    parsed: model::FileDescriptor,
    descriptor: protobuf::descriptor::FileDescriptorProto,
}
<commit_msg>protobuf-parse crate docs<commit_after>//! Parse `.proto` files.
//!
//! Files can be parsed using pure Rust parser (mod `pure`)
//! or using the `protoc` command (mod `protoc`).
//!
//! This crate is not meant to be used directly, but rather through the `protobuf-codegen` crate.
//! If you think this crate might be useful to you,
//! please [consider creating an issue](https://github.com/stepancheg/rust-protobuf/issues/new),
//! until that this crate is considered to have **no stable API**.

mod case_convert;
mod linked_hash_map;
mod parse_and_typecheck;
mod parser;
mod path;
mod proto;
mod proto_path;
mod protobuf_abs_path;
mod protobuf_ident;
mod protobuf_path;
mod protobuf_rel_path;
pub mod protoc;
pub mod pure;
mod rel_path;
mod test_against_protobuf_protos;
mod which_parser;

// Public API
// Non-public API used by codegen crate.
pub use case_convert::*;
pub use parse_and_typecheck::*;
pub use proto_path::*;
pub use protobuf_abs_path::*;
pub use protobuf_ident::*;
pub use protobuf_rel_path::*;
pub use which_parser::*;

use crate::pure::model;

#[derive(Clone)]
pub(crate) struct FileDescriptorPair {
    parsed: model::FileDescriptor,
    descriptor: protobuf::descriptor::FileDescriptorProto,
}
<|endoftext|>