<commit_before>//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces Serde to treat `&[u8]` just like any
//! other slice and `Vec<u8>` just like any other vector. In reality this
//! particular slice and vector can often be serialized and deserialized in a
//! more efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `serde_bytes::Bytes` and `Vec<u8>` by wrapping it
//! in `serde_bytes::ByteBuf`.
//!
//! This crate supports the Serde `with` attribute to enable efficient handling
//! of `&[u8]` and `Vec<u8>` in structs without needing a wrapper type.
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//!
//! extern crate serde;
//! extern crate serde_bytes;
//!
//! #[derive(Serialize)]
//! struct Efficient<'a> {
//!     #[serde(with = "serde_bytes")]
//!     bytes: &'a [u8],
//!
//!     #[serde(with = "serde_bytes")]
//!     byte_buf: Vec<u8>,
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! struct Packet {
//!     #[serde(with = "serde_bytes")]
//!     payload: Vec<u8>,
//! }
//! #
//! # fn main() {}
//! ```

#![doc(html_root_url = "https://docs.rs/serde_bytes/0.10.4")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![deny(missing_docs)]

#[cfg(feature = "std")]
use std::{fmt, ops};

#[cfg(not(feature = "std"))]
use core::{fmt, ops};

use self::fmt::Debug;

#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::Vec;

#[macro_use]
extern crate serde;
use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::bytebuf::ByteBuf;

mod value;

//////////////////////////////////////////////////////////////////////////////

/// Serde `serialize_with` function to serialize bytes efficiently.
///
/// This function can be used with either of the following Serde attributes:
///
/// - `#[serde(with = "serde_bytes")]`
/// - `#[serde(serialize_with = "serde_bytes::serialize")]`
///
/// ```rust
/// #[macro_use]
/// extern crate serde_derive;
///
/// extern crate serde;
/// extern crate serde_bytes;
///
/// #[derive(Serialize)]
/// struct Efficient<'a> {
///     #[serde(with = "serde_bytes")]
///     bytes: &'a [u8],
///
///     #[serde(with = "serde_bytes")]
///     byte_buf: Vec<u8>,
/// }
/// #
/// # fn main() {}
/// ```
pub fn serialize<T, S>(bytes: &T, serializer: S) -> Result<S::Ok, S::Error>
where
    T: ?Sized + AsRef<[u8]>,
    S: Serializer,
{
    serializer.serialize_bytes(bytes.as_ref())
}

/// Serde `deserialize_with` function to deserialize bytes efficiently.
///
/// This function can be used with either of the following Serde attributes:
///
/// - `#[serde(with = "serde_bytes")]`
/// - `#[serde(deserialize_with = "serde_bytes::deserialize")]`
///
/// ```rust
/// #[macro_use]
/// extern crate serde_derive;
///
/// extern crate serde;
/// extern crate serde_bytes;
///
/// #[derive(Deserialize)]
/// struct Packet {
///     #[serde(with = "serde_bytes")]
///     payload: Vec<u8>,
/// }
/// #
/// # fn main() {}
/// ```
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: From<Vec<u8>>,
    D: Deserializer<'de>,
{
    ByteBuf::deserialize(deserializer).map(|buf| Into::<Vec<u8>>::into(buf).into())
}

//////////////////////////////////////////////////////////////////////////////

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```rust
/// extern crate bincode;
/// extern crate serde_bytes;
///
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
    bytes: &'a [u8],
}

impl<'a> Bytes<'a> {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &'a [u8]) -> Self {
        Bytes { bytes: bytes }
    }
}

impl<'a> Debug for Bytes<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.bytes, f)
    }
}

impl<'a> From<&'a [u8]> for Bytes<'a> {
    fn from(bytes: &'a [u8]) -> Self {
        Bytes::new(bytes)
    }
}

impl<'a> From<Bytes<'a>> for &'a [u8] {
    fn from(wrapper: Bytes<'a>) -> &'a [u8] {
        wrapper.bytes
    }
}

impl<'a> ops::Deref for Bytes<'a> {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        self.bytes
    }
}

impl<'a> Serialize for Bytes<'a> {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(self.bytes)
    }
}

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = Bytes<'de>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    #[inline]
    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Bytes<'de>, E>
    where
        E: Error,
    {
        Ok(Bytes::from(v))
    }

    #[inline]
    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Bytes<'de>, E>
    where
        E: Error,
    {
        Ok(Bytes::from(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for Bytes<'a> {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<Bytes<'a>, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(any(feature = "std", feature = "alloc"))]
mod bytebuf {
    #[cfg(feature = "std")]
    use std::{cmp, fmt, ops};

    #[cfg(not(feature = "std"))]
    use core::{cmp, fmt, ops};

    use self::fmt::Debug;

    #[cfg(feature = "alloc")]
    use alloc::{String, Vec};

    use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
    use serde::ser::{Serialize, Serializer};

    /// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
    ///
    /// ```rust
    /// extern crate bincode;
    /// extern crate serde_bytes;
    ///
    /// use std::collections::HashMap;
    /// use std::io;
    ///
    /// use serde_bytes::ByteBuf;
    ///
    /// fn deserialize_bytebufs() -> bincode::Result<()> {
    ///     let example_data = [
    ///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
    ///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101];
    ///
    ///     let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?;
    ///
    ///     println!("{:?}", map);
    ///
    ///     Ok(())
    /// }
    /// #
    /// # fn main() {
    /// #     deserialize_bytebufs().unwrap();
    /// # }
    /// ```
    #[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
    pub struct ByteBuf {
        bytes: Vec<u8>,
    }

    impl ByteBuf {
        /// Construct a new, empty `ByteBuf`.
        pub fn new() -> Self {
            ByteBuf::from(Vec::new())
        }

        /// Construct a new, empty `ByteBuf` with the specified capacity.
        pub fn with_capacity(cap: usize) -> Self {
            ByteBuf::from(Vec::with_capacity(cap))
        }

        /// Wrap existing bytes in a `ByteBuf`.
        pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
            ByteBuf {
                bytes: bytes.into(),
            }
        }
    }

    impl Debug for ByteBuf {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            Debug::fmt(&self.bytes, f)
        }
    }

    impl From<ByteBuf> for Vec<u8> {
        fn from(wrapper: ByteBuf) -> Vec<u8> {
            wrapper.bytes
        }
    }

    impl From<Vec<u8>> for ByteBuf {
        fn from(bytes: Vec<u8>) -> Self {
            ByteBuf::from(bytes)
        }
    }

    impl AsRef<Vec<u8>> for ByteBuf {
        fn as_ref(&self) -> &Vec<u8> {
            &self.bytes
        }
    }

    impl AsRef<[u8]> for ByteBuf {
        fn as_ref(&self) -> &[u8] {
            &self.bytes
        }
    }

    impl AsMut<Vec<u8>> for ByteBuf {
        fn as_mut(&mut self) -> &mut Vec<u8> {
            &mut self.bytes
        }
    }

    impl AsMut<[u8]> for ByteBuf {
        fn as_mut(&mut self) -> &mut [u8] {
            &mut self.bytes
        }
    }

    impl ops::Deref for ByteBuf {
        type Target = [u8];

        fn deref(&self) -> &[u8] {
            &self.bytes[..]
        }
    }

    impl ops::DerefMut for ByteBuf {
        fn deref_mut(&mut self) -> &mut [u8] {
            &mut self.bytes[..]
        }
    }

    impl Serialize for ByteBuf {
        #[inline]
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            serializer.serialize_bytes(&self.bytes)
        }
    }

    struct ByteBufVisitor;

    impl<'de> Visitor<'de> for ByteBufVisitor {
        type Value = ByteBuf;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("byte array")
        }

        #[inline]
        fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
        where
            V: SeqAccess<'de>,
        {
            let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
            let mut values = Vec::with_capacity(len);

            while let Some(value) = try!(visitor.next_element()) {
                values.push(value);
            }

            Ok(ByteBuf::from(values))
        }

        #[inline]
        fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }

        #[inline]
        fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }

        #[inline]
        fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }

        #[inline]
        fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }
    }

    impl<'de> Deserialize<'de> for ByteBuf {
        #[inline]
        fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
        where
            D: Deserializer<'de>,
        {
            deserializer.deserialize_byte_buf(ByteBufVisitor)
        }
    }
}
<commit_msg>Update doc tests to 2018 edition<commit_after>//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces Serde to treat `&[u8]` just like any
//! other slice and `Vec<u8>` just like any other vector. In reality this
//! particular slice and vector can often be serialized and deserialized in a
//! more efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `serde_bytes::Bytes` and `Vec<u8>` by wrapping it
//! in `serde_bytes::ByteBuf`.
//!
//! This crate supports the Serde `with` attribute to enable efficient handling
//! of `&[u8]` and `Vec<u8>` in structs without needing a wrapper type.
//!
//! ```edition2018
//! # use serde_derive::{Serialize, Deserialize};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Serialize)]
//! struct Efficient<'a> {
//!     #[serde(with = "serde_bytes")]
//!     bytes: &'a [u8],
//!
//!     #[serde(with = "serde_bytes")]
//!     byte_buf: Vec<u8>,
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! struct Packet {
//!     #[serde(with = "serde_bytes")]
//!     payload: Vec<u8>,
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_bytes/0.10.4")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![deny(missing_docs)]

#[cfg(feature = "std")]
use std::{fmt, ops};

#[cfg(not(feature = "std"))]
use core::{fmt, ops};

use self::fmt::Debug;

#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::Vec;

#[macro_use]
extern crate serde;
use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::bytebuf::ByteBuf;

mod value;

//////////////////////////////////////////////////////////////////////////////

/// Serde `serialize_with` function to serialize bytes efficiently.
///
/// This function can be used with either of the following Serde attributes:
///
/// - `#[serde(with = "serde_bytes")]`
/// - `#[serde(serialize_with = "serde_bytes::serialize")]`
///
/// ```edition2018
/// # use serde_derive::Serialize;
/// use serde::Serialize;
///
/// #[derive(Serialize)]
/// struct Efficient<'a> {
///     #[serde(with = "serde_bytes")]
///     bytes: &'a [u8],
///
///     #[serde(with = "serde_bytes")]
///     byte_buf: Vec<u8>,
/// }
/// ```
pub fn serialize<T, S>(bytes: &T, serializer: S) -> Result<S::Ok, S::Error>
where
    T: ?Sized + AsRef<[u8]>,
    S: Serializer,
{
    serializer.serialize_bytes(bytes.as_ref())
}

/// Serde `deserialize_with` function to deserialize bytes efficiently.
///
/// This function can be used with either of the following Serde attributes:
///
/// - `#[serde(with = "serde_bytes")]`
/// - `#[serde(deserialize_with = "serde_bytes::deserialize")]`
///
/// ```edition2018
/// # use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
/// struct Packet {
///     #[serde(with = "serde_bytes")]
///     payload: Vec<u8>,
/// }
/// ```
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: From<Vec<u8>>,
    D: Deserializer<'de>,
{
    ByteBuf::deserialize(deserializer).map(|buf| Into::<Vec<u8>>::into(buf).into())
}

//////////////////////////////////////////////////////////////////////////////

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```edition2018
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
    bytes: &'a [u8],
}

impl<'a> Bytes<'a> {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &'a [u8]) -> Self {
        Bytes { bytes: bytes }
    }
}

impl<'a> Debug for Bytes<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.bytes, f)
    }
}

impl<'a> From<&'a [u8]> for Bytes<'a> {
    fn from(bytes: &'a [u8]) -> Self {
        Bytes::new(bytes)
    }
}

impl<'a> From<Bytes<'a>> for &'a [u8] {
    fn from(wrapper: Bytes<'a>) -> &'a [u8] {
        wrapper.bytes
    }
}

impl<'a> ops::Deref for Bytes<'a> {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        self.bytes
    }
}

impl<'a> Serialize for Bytes<'a> {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(self.bytes)
    }
}

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = Bytes<'de>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    #[inline]
    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Bytes<'de>, E>
    where
        E: Error,
    {
        Ok(Bytes::from(v))
    }

    #[inline]
    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Bytes<'de>, E>
    where
        E: Error,
    {
        Ok(Bytes::from(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for Bytes<'a> {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<Bytes<'a>, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(any(feature = "std", feature = "alloc"))]
mod bytebuf {
    #[cfg(feature = "std")]
    use std::{cmp, fmt, ops};

    #[cfg(not(feature = "std"))]
    use core::{cmp, fmt, ops};

    use self::fmt::Debug;

    #[cfg(feature = "alloc")]
    use alloc::{String, Vec};

    use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
    use serde::ser::{Serialize, Serializer};

    /// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
    ///
    /// ```edition2018
    /// use std::collections::HashMap;
    /// use std::io;
    ///
    /// use serde_bytes::ByteBuf;
    ///
    /// fn deserialize_bytebufs() -> bincode::Result<()> {
    ///     let example_data = [
    ///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
    ///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101];
    ///
    ///     let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?;
    ///
    ///     println!("{:?}", map);
    ///
    ///     Ok(())
    /// }
    /// #
    /// # fn main() {
    /// #     deserialize_bytebufs().unwrap();
    /// # }
    /// ```
    #[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
    pub struct ByteBuf {
        bytes: Vec<u8>,
    }

    impl ByteBuf {
        /// Construct a new, empty `ByteBuf`.
        pub fn new() -> Self {
            ByteBuf::from(Vec::new())
        }

        /// Construct a new, empty `ByteBuf` with the specified capacity.
        pub fn with_capacity(cap: usize) -> Self {
            ByteBuf::from(Vec::with_capacity(cap))
        }

        /// Wrap existing bytes in a `ByteBuf`.
        pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
            ByteBuf {
                bytes: bytes.into(),
            }
        }
    }

    impl Debug for ByteBuf {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            Debug::fmt(&self.bytes, f)
        }
    }

    impl From<ByteBuf> for Vec<u8> {
        fn from(wrapper: ByteBuf) -> Vec<u8> {
            wrapper.bytes
        }
    }

    impl From<Vec<u8>> for ByteBuf {
        fn from(bytes: Vec<u8>) -> Self {
            ByteBuf::from(bytes)
        }
    }

    impl AsRef<Vec<u8>> for ByteBuf {
        fn as_ref(&self) -> &Vec<u8> {
            &self.bytes
        }
    }

    impl AsRef<[u8]> for ByteBuf {
        fn as_ref(&self) -> &[u8] {
            &self.bytes
        }
    }

    impl AsMut<Vec<u8>> for ByteBuf {
        fn as_mut(&mut self) -> &mut Vec<u8> {
            &mut self.bytes
        }
    }

    impl AsMut<[u8]> for ByteBuf {
        fn as_mut(&mut self) -> &mut [u8] {
            &mut self.bytes
        }
    }

    impl ops::Deref for ByteBuf {
        type Target = [u8];

        fn deref(&self) -> &[u8] {
            &self.bytes[..]
        }
    }

    impl ops::DerefMut for ByteBuf {
        fn deref_mut(&mut self) -> &mut [u8] {
            &mut self.bytes[..]
        }
    }

    impl Serialize for ByteBuf {
        #[inline]
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            serializer.serialize_bytes(&self.bytes)
        }
    }

    struct ByteBufVisitor;

    impl<'de> Visitor<'de> for ByteBufVisitor {
        type Value = ByteBuf;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("byte array")
        }

        #[inline]
        fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
        where
            V: SeqAccess<'de>,
        {
            let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
            let mut values = Vec::with_capacity(len);

            while let Some(value) = try!(visitor.next_element()) {
                values.push(value);
            }

            Ok(ByteBuf::from(values))
        }

        #[inline]
        fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }

        #[inline]
        fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }

        #[inline]
        fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }

        #[inline]
        fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
        where
            E: Error,
        {
            Ok(ByteBuf::from(v))
        }
    }

    impl<'de> Deserialize<'de> for ByteBuf {
        #[inline]
        fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
        where
            D: Deserializer<'de>,
        {
            deserializer.deserialize_byte_buf(ByteBufVisitor)
        }
    }
}
<|endoftext|>


<commit_before>#![feature(associated_consts)]

extern crate uuid;
extern crate jsrs_common;

mod alloc;
mod ast;
mod js_types;
mod utils;

use std::cell::RefCell;
use std::collections::hash_set::HashSet;
use std::mem;
use std::rc::Rc;

use uuid::Uuid;

use alloc::AllocBox;
use alloc::scope::Scope;
use js_types::js_type::{JsPtrEnum, JsVar};

pub struct ScopeManager {
    curr_scope: Scope,
    alloc_box: Rc<RefCell<AllocBox>>
}

impl ScopeManager {
    pub fn new<F>(alloc_box: Rc<RefCell<AllocBox>>, callback: F) -> ScopeManager
        where F: Fn() -> HashSet<Uuid> + 'static {
        ScopeManager {
            curr_scope: Scope::new(&alloc_box, callback),
            alloc_box: alloc_box,
        }
    }

    pub fn push_scope<F>(&mut self, callback: F) where F: Fn() -> HashSet<Uuid> + 'static {
        let parent = mem::replace(&mut self.curr_scope, Scope::new(&self.alloc_box, callback));
        self.curr_scope.set_parent(parent);
    }

    pub fn pop_scope(&mut self) {
        let parent = self.curr_scope.transfer_stack();
        mem::replace(&mut self.curr_scope,
                     *parent.expect("Tried to pop to parent scope, but parent did not exist!"));
    }

    pub fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Uuid {
        self.curr_scope.push(var, ptr)
    }

    pub fn load(&self, uuid: &Uuid) -> Result<(JsVar, Option<JsPtrEnum>), String> {
        if let (Some(v), ptr) = self.curr_scope.get_var_copy(uuid) {
            Ok((v, ptr))
        } else { Err(format!("Lookup of uuid {} failed!", uuid)) }
    }

    pub fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> bool {
        self.curr_scope.update_var(var, ptr)
    }
}

pub fn init_gc<F>(callback: F) -> ScopeManager
    where F: Fn() -> HashSet<Uuid> + 'static {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box, callback)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_set::HashSet;
    use std::cell::RefCell;
    use std::rc::Rc;

    use uuid::Uuid;

    use alloc::AllocBox;
    use js_types::js_type::{JsType, JsVar};
    use utils;

    #[test]
    fn test_alloc() {
        let alloc_box = utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box, utils::dummy_callback);
        mgr.alloc(utils::make_num(1.), None);
        mgr.push_scope(utils::dummy_callback);
        mgr.alloc(utils::make_num(2.), None);
        assert_eq!(mgr.alloc_box.borrow().len(), 0);
    }

    #[test]
    fn test_store() {
        let alloc_box = utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box, utils::dummy_callback);
        mgr.push_scope(utils::dummy_callback);
        mgr.alloc(utils::make_num(1.), None);
        let test_id = mgr.alloc(utils::make_num(2.), None);
        mgr.alloc(utils::make_num(3.), None);

        let mut test_num = utils::make_num(4.);
        test_num.uuid = test_id;
        assert!(mgr.store(test_num, None));
    }

    #[test]
    fn test_pop_scope() {
        let alloc_box = utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box, utils::dummy_callback);
        mgr.push_scope(utils::dummy_callback);
        assert!(mgr.curr_scope.parent.is_some());
        mgr.pop_scope();
        assert!(mgr.curr_scope.parent.is_none());
    }
}
<commit_msg>Make js_type and alloc public modules at the top level<commit_after>#![feature(associated_consts)]

extern crate uuid;
extern crate jsrs_common;

pub mod alloc;
mod ast;
pub mod js_types;
mod utils;

use std::cell::RefCell;
use std::collections::hash_set::HashSet;
use std::mem;
use std::rc::Rc;

use uuid::Uuid;

use alloc::AllocBox;
use alloc::scope::Scope;
use js_types::js_type::{JsPtrEnum, JsVar};

pub struct ScopeManager {
    curr_scope: Scope,
    alloc_box: Rc<RefCell<AllocBox>>
}

impl ScopeManager {
    pub fn new<F>(alloc_box: Rc<RefCell<AllocBox>>, callback: F) -> ScopeManager
        where F: Fn() -> HashSet<Uuid> + 'static {
        ScopeManager {
            curr_scope: Scope::new(&alloc_box, callback),
            alloc_box: alloc_box,
        }
    }

    pub fn push_scope<F>(&mut self, callback: F) where F: Fn() -> HashSet<Uuid> + 'static {
        let parent = mem::replace(&mut self.curr_scope, Scope::new(&self.alloc_box, callback));
        self.curr_scope.set_parent(parent);
    }

    pub fn pop_scope(&mut self) {
        let parent = self.curr_scope.transfer_stack();
        mem::replace(&mut self.curr_scope,
                     *parent.expect("Tried to pop to parent scope, but parent did not exist!"));
    }

    pub fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Uuid {
        self.curr_scope.push(var, ptr)
    }

    pub fn load(&self, uuid: &Uuid) -> Result<(JsVar, Option<JsPtrEnum>), String> {
        if let (Some(v), ptr) = self.curr_scope.get_var_copy(uuid) {
            Ok((v, ptr))
        } else { Err(format!("Lookup of uuid {} failed!", uuid)) }
    }

    pub fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> bool {
        self.curr_scope.update_var(var, ptr)
    }
}

pub fn init_gc<F>(callback: F) -> ScopeManager
    where F: Fn() -> HashSet<Uuid> + 'static {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box, callback)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_set::HashSet;
    use std::cell::RefCell;
    use std::rc::Rc;

    use uuid::Uuid;

    use alloc::AllocBox;
    use js_types::js_type::{JsType, JsVar};
    use utils;

    #[test]
    fn test_alloc() {
        let alloc_box = utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box, utils::dummy_callback);
        mgr.alloc(utils::make_num(1.), None);
        mgr.push_scope(utils::dummy_callback);
        mgr.alloc(utils::make_num(2.), None);
        assert_eq!(mgr.alloc_box.borrow().len(), 0);
    }

    #[test]
    fn test_store() {
        let alloc_box = utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box, utils::dummy_callback);
        mgr.push_scope(utils::dummy_callback);
        mgr.alloc(utils::make_num(1.), None);
        let test_id = mgr.alloc(utils::make_num(2.), None);
        mgr.alloc(utils::make_num(3.), None);

        let mut test_num = utils::make_num(4.);
        test_num.uuid = test_id;
        assert!(mgr.store(test_num, None));
    }

    #[test]
    fn test_pop_scope() {
        let alloc_box = utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box, utils::dummy_callback);
        mgr.push_scope(utils::dummy_callback);
        assert!(mgr.curr_scope.parent.is_some());
        mgr.pop_scope();
        assert!(mgr.curr_scope.parent.is_none());
    }
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, rustc_private, convert, slice_patterns)]

extern crate rustc;
extern crate syntax;

use std::rc::Rc;

use syntax::codemap::Span;
use syntax::parse::{PResult, token};
use syntax::ast::{Delimited, Ident, TokenTree, TtDelimited, TtToken};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::quote::rt::ToTokens;
use syntax::util::small_vector::SmallVector;
use rustc::plugin::Registry;

fn tt_vec(tts: &[TokenTree]) -> Vec<TokenTree> {
    tts.iter().map(|tt| tt.clone()).collect()
}

fn ident_of_ctx_and_span(cx: &mut ExtCtxt, span: Span, ident: &str) -> TokenTree {
    TtToken(span, token::Ident(cx.ident_of(ident), token::Plain))
}

fn build_string_from_idents(target: &mut String, tts: &[TokenTree]) -> Result<(), Span> {
    for t in tts {
        match t {
            &TtToken(_, token::Ident(ref i, _)) => {
                target.extend(i.as_str().chars());
            },
            &TtToken(_, token::Comma) => (),
            &TtDelimited(delim_span, ref delim) => {
                if delim.delim != token::DelimToken::Bracket {
                    return Err(delim_span);
                }
                try!(build_string_from_idents(target, &delim.tts[..]));
            }
            ref tt => return Err(tt.get_span()),
        }
    }
    Ok(())
}

fn fnconcat(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
            -> Box<MacResult + 'static> {
    if args.is_empty() {
        cx.span_err(sp, "fnconcat! can't be called with nothing");
        return DummyResult::any(sp);
    }
    let mut fn_tokens = tt_vec(args);
    fn_tokens[0] = if let &TtDelimited(delim_span, ref delim) = &fn_tokens[0] {
        if delim.delim != token::DelimToken::Bracket {
            cx.span_err(delim_span, "use square brackets (i.e. [..]) in place of the function name");
            return DummyResult::any(delim_span);
        }
        let mut concatenated = String::new();
        match build_string_from_idents(&mut concatenated, &delim.tts) {
            Ok(()) => (),
            Err(err_span) => {
                cx.span_err(err_span, "non-ident, non-comma token");
                return DummyResult::any(sp);
            },
        }
        if concatenated.is_empty() {
            cx.span_err(delim_span, "empty identifier");
            return DummyResult::any(sp);
        }
        ident_of_ctx_and_span(cx, delim_span, concatenated.as_str())
    } else {
        cx.span_err(sp, "use square brackets (i.e. [..]) in place of the function name");
        return DummyResult::any(sp);
    };
    fn_tokens.insert(0, ident_of_ctx_and_span(cx, sp, "fn"));
    let mut p = cx.new_parser_from_tts(&fn_tokens[..]);
    if let Some(i) = p.parse_item() {
        return MacEager::items(SmallVector::one(i));
    }
    cx.span_err(sp, "couldn't parse a fn");
    return DummyResult::any(sp);
}

fn pull_tts_from_paren_groups(tts: &[TokenTree]) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    for t in tts {
        match t {
            &TtDelimited(_, ref delim) if delim.delim == token::DelimToken::Paren => {
                ret.push(tt_vec(&delim.tts[..]));
            },
            _ => {

            },
        }
    }
    Ok(ret)
}

fn parse_pats_and_types(cx: &mut ExtCtxt, span: Span, tts: Vec<TokenTree>) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        let pat = try!(parser.parse_pat_nopanic());
        try!(parser.expect(&token::Colon));
        let ty = try!(parser.parse_ty_nopanic());
        let mut pat = pat.to_tokens(cx);
        pat.push(TtToken(span, token::Colon));
        pat.extend(ty.to_tokens(cx).into_iter());
        ret.push(pat);
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn parse_exprs(cx: &mut ExtCtxt, tts: Vec<TokenTree>) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        ret.push(try!(parser.parse_expr_nopanic()).to_tokens(cx));
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn let_of_pat_and_expr(cx: &mut ExtCtxt, span: Span, pat: Vec<TokenTree>, expr: Vec<TokenTree>) -> Vec<TokenTree> {
    let mut ret = vec![ident_of_ctx_and_span(cx, span, "let")];
    ret.extend(pat.into_iter());
    ret.push(TtToken(span, token::Eq));
    ret.extend(expr.into_iter());
    ret.push(TtToken(span, token::Semi));
    ret
}

fn test_fn_of_ident_and_block(cx: &mut ExtCtxt, span: Span, ident: String, block: Vec<TokenTree>) -> Vec<TokenTree> {
    vec![
        TtToken(span, token::Pound),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Bracket,
            open_span: span,
            tts: vec![ident_of_ctx_and_span(cx, span, "test")],
            close_span: span,
        })),
        ident_of_ctx_and_span(cx, span, "fn"),
        ident_of_ctx_and_span(cx, span, ident.as_str()),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Paren,
            open_span: span,
            tts: Vec::new(),
            close_span: span,
        })),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Brace,
            open_span: span,
            tts: block,
            close_span: span,
        })),
    ]
}

fn do_parametrization(cx: &mut ExtCtxt, span: Span, base_name: Ident, params: &Delimited, block: Vec<TokenTree>)
                      -> PResult<Box<MacResult + 'static>> {
    let mut tokens = Vec::new();
    let mut groups = try!(pull_tts_from_paren_groups(&params.tts[..]));
    let param_types = try!(parse_pats_and_types(cx, span, groups.remove(0)));
    let param_exprs_vec: Vec<Vec<Vec<TokenTree>>> = try!(groups.into_iter().map(|tts| parse_exprs(cx, tts)).collect());
    for (e, exprs) in param_exprs_vec.into_iter().enumerate() {
        let mut fn_block = Vec::new();
        for (pat, expr) in param_types.iter().cloned().zip(exprs.into_iter()) {
            fn_block.extend(let_of_pat_and_expr(cx, span, pat, expr).into_iter());
        }
        fn_block.extend(block.iter().cloned());
        let fn_name = format!("{}_{}", base_name.as_str(), e);
        tokens.extend(test_fn_of_ident_and_block(cx, span, fn_name, fn_block).into_iter());
    }
    let mut parser = cx.new_parser_from_tts(&tokens[..]);
    let mut items = Vec::new();
    loop {
        match parser.parse_item() {
            Some(i) => items.push(i),
            None => break,
        }
    }
    Ok(MacEager::items(SmallVector::many(items)))
}

fn parametrize_test(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
                    -> Box<MacResult + 'static> {
    match args {
        [TtToken(_, token::Ident(ref name, _)),
         TtToken(_, token::Comma),
         TtDelimited(params_span, ref params),
         TtToken(_, token::Comma),
         TtDelimited(block_span, ref block)] => {
            if params.delim != token::DelimToken::Bracket {
                cx.span_err(params_span, "need square brackets around parameters");
                return DummyResult::any(params_span);
            }
            if block.delim != token::DelimToken::Brace {
                cx.span_err(block_span, "need curly braces around block");
                return DummyResult::any(block_span);
            }
            if params.tts.len() < 2 {
                cx.span_err(params_span, "need at least param types and one param");
                return DummyResult::any(params_span);
            }
            match do_parametrization(cx, sp, name.clone(), params, block.tts.clone()) {
                Ok(r) => return r,
                Err(_) => {
                    cx.span_err(sp, "error while parsing");
                    return DummyResult::any(sp);
                }
            }
        },
        _ => {
            cx.span_err(sp, "badly-structured parametrize_test!");
            return DummyResult::any(sp);
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("fnconcat", fnconcat);
    reg.register_macro("parametrize_test", parametrize_test);
}
<commit_msg>Correct some incorrect spans.<commit_after>#![feature(plugin_registrar, rustc_private, convert, slice_patterns)]

extern crate rustc;
extern crate syntax;

use std::rc::Rc;

use syntax::codemap::Span;
use syntax::parse::{PResult, token};
use syntax::ast::{Delimited, Ident, TokenTree, TtDelimited, TtToken};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::quote::rt::ToTokens;
use syntax::util::small_vector::SmallVector;
use rustc::plugin::Registry;

fn tt_vec(tts: &[TokenTree]) -> Vec<TokenTree> {
    tts.iter().map(|tt| tt.clone()).collect()
}

fn ident_of_ctx_and_span(cx: &mut ExtCtxt, span: Span, ident: &str) -> TokenTree {
    TtToken(span, token::Ident(cx.ident_of(ident), token::Plain))
}

fn build_string_from_idents(target: &mut String, tts: &[TokenTree]) -> Result<(), Span> {
    for t in tts {
        match t {
            &TtToken(_, token::Ident(ref i, _)) => {
                target.extend(i.as_str().chars());
            },
            &TtToken(_, token::Comma) => (),
            &TtDelimited(delim_span, ref delim) => {
                if delim.delim != token::DelimToken::Bracket {
                    return Err(delim_span);
                }
                try!(build_string_from_idents(target, &delim.tts[..]));
            }
            ref tt => return Err(tt.get_span()),
        }
    }
    Ok(())
}

fn fnconcat(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
            -> Box<MacResult + 'static> {
    if args.is_empty() {
        cx.span_err(sp, "fnconcat! can't be called with nothing");
        return DummyResult::any(sp);
    }
    let mut fn_tokens = tt_vec(args);
    fn_tokens[0] = if let &TtDelimited(delim_span, ref delim) = &fn_tokens[0] {
        if delim.delim != token::DelimToken::Bracket {
            cx.span_err(delim_span, "use square brackets (i.e. [..]) in place of the function name");
            return DummyResult::any(delim_span);
        }
        let mut concatenated = String::new();
        match build_string_from_idents(&mut concatenated, &delim.tts) {
            Ok(()) => (),
            Err(err_span) => {
                cx.span_err(err_span, "non-ident, non-comma token");
                return DummyResult::any(err_span);
            },
        }
        if concatenated.is_empty() {
            cx.span_err(delim_span, "empty identifier");
            return DummyResult::any(delim_span);
        }
        ident_of_ctx_and_span(cx, delim_span, concatenated.as_str())
    } else {
        cx.span_err(sp, "use square brackets (i.e. [..]) in place of the function name");
        return DummyResult::any(sp);
    };
    fn_tokens.insert(0, ident_of_ctx_and_span(cx, sp, "fn"));
    let mut p = cx.new_parser_from_tts(&fn_tokens[..]);
    if let Some(i) = p.parse_item() {
        return MacEager::items(SmallVector::one(i));
    }
    cx.span_err(sp, "couldn't parse a fn");
    return DummyResult::any(sp);
}

fn pull_tts_from_paren_groups(tts: &[TokenTree]) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    for t in tts {
        match t {
            &TtDelimited(_, ref delim) if delim.delim == token::DelimToken::Paren => {
                ret.push(tt_vec(&delim.tts[..]));
            },
            _ => {

            },
        }
    }
    Ok(ret)
}

fn parse_pats_and_types(cx: &mut ExtCtxt, span: Span, tts: Vec<TokenTree>) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        let pat = try!(parser.parse_pat_nopanic());
        try!(parser.expect(&token::Colon));
        let ty = try!(parser.parse_ty_nopanic());
        let mut pat = pat.to_tokens(cx);
        pat.push(TtToken(span, token::Colon));
        pat.extend(ty.to_tokens(cx).into_iter());
        ret.push(pat);
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn parse_exprs(cx: &mut ExtCtxt, tts: Vec<TokenTree>) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        ret.push(try!(parser.parse_expr_nopanic()).to_tokens(cx));
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn let_of_pat_and_expr(cx: &mut ExtCtxt, span: Span, pat: Vec<TokenTree>, expr: Vec<TokenTree>) -> Vec<TokenTree> {
    let mut ret = vec![ident_of_ctx_and_span(cx, span, "let")];
    ret.extend(pat.into_iter());
    ret.push(TtToken(span, token::Eq));
    ret.extend(expr.into_iter());
    ret.push(TtToken(span, token::Semi));
    ret
}

fn test_fn_of_ident_and_block(cx: &mut ExtCtxt, span: Span, ident: String, block: Vec<TokenTree>) -> Vec<TokenTree> {
    vec![
        TtToken(span, token::Pound),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Bracket,
            open_span: span,
            tts: vec![ident_of_ctx_and_span(cx, span, "test")],
            close_span: span,
        })),
        ident_of_ctx_and_span(cx, span, "fn"),
        ident_of_ctx_and_span(cx, span, ident.as_str()),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Paren,
            open_span: span,
            tts: Vec::new(),
            close_span: span,
        })),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Brace,
            open_span: span,
            tts: block,
            close_span: span,
        })),
    ]
}

fn do_parametrization(cx: &mut ExtCtxt, span: Span, base_name: Ident, params: &Delimited, block: Vec<TokenTree>)
                      -> PResult<Box<MacResult + 'static>> {
    let mut tokens = Vec::new();
    let mut groups = try!(pull_tts_from_paren_groups(&params.tts[..]));
    let param_types = try!(parse_pats_and_types(cx, span, groups.remove(0)));
    let param_exprs_vec: Vec<Vec<Vec<TokenTree>>> = try!(groups.into_iter().map(|tts| parse_exprs(cx, tts)).collect());
    for (e, exprs) in param_exprs_vec.into_iter().enumerate() {
        let mut fn_block = Vec::new();
        for (pat, expr) in param_types.iter().cloned().zip(exprs.into_iter()) {
            fn_block.extend(let_of_pat_and_expr(cx, span, pat, expr).into_iter());
        }
        fn_block.extend(block.iter().cloned());
        let fn_name = format!("{}_{}", base_name.as_str(), e);
        tokens.extend(test_fn_of_ident_and_block(cx, span, fn_name, fn_block).into_iter());
    }
    let mut parser = cx.new_parser_from_tts(&tokens[..]);
    let mut items = Vec::new();
    loop {
        match parser.parse_item() {
            Some(i) => items.push(i),
            None => break,
        }
    }
    Ok(MacEager::items(SmallVector::many(items)))
}

fn parametrize_test(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
                    -> Box<MacResult + 'static> {
    match args {
        [TtToken(_, token::Ident(ref name, _)),
         TtToken(_, token::Comma),
         TtDelimited(params_span, ref params),
         TtToken(_, token::Comma),
         TtDelimited(block_span, ref block)] => {
            if params.delim != token::DelimToken::Bracket {
                cx.span_err(params_span, "need square brackets around parameters");
                return DummyResult::any(params_span);
            }
            if block.delim != token::DelimToken::Brace {
                cx.span_err(block_span, "need curly braces around block");
                return DummyResult::any(block_span);
            }
            if params.tts.len() < 2 {
                cx.span_err(params_span, "need at least param types and one param");
                return DummyResult::any(params_span);
            }
            match do_parametrization(cx, sp, name.clone(), params, block.tts.clone()) {
                Ok(r) => return r,
                Err(_) => {
                    cx.span_err(sp, "error while parsing");
                    return DummyResult::any(sp);
                }
            }
        },
        _ => {
            cx.span_err(sp, "badly-structured parametrize_test!");
            return DummyResult::any(sp);
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("fnconcat", fnconcat);
    reg.register_macro("parametrize_test", parametrize_test);
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 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.

//! A collection of numeric types and traits for Rust.
//!
//! This includes new types for big integers, rationals, and complex numbers,
//! new traits for generic programming on numeric properties like `Integer`,
//! and generic range iterators.
//!
//! ## Example
//!
//! This example uses the BigRational type and [Newton's method][newt] to
//! approximate a square root to arbitrary precision:
//!
//! ```
//! extern crate num;
//! # #[cfg(all(feature = "bigint", feature="rational"))]
//! # mod test {
//!
//! use num::FromPrimitive;
//! use num::bigint::BigInt;
//! use num::rational::{Ratio, BigRational};
//!
//! # pub
//! fn approx_sqrt(number: u64, iterations: usize) -> BigRational {
//!     let start: Ratio<BigInt> = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap());
//!     let mut approx = start.clone();
//!
//!     for _ in 0..iterations {
//!         approx = (&approx + (&start / &approx)) /
//!             Ratio::from_integer(FromPrimitive::from_u64(2).unwrap());
//!     }
//!
//!     approx
//! }
//! # }
//! # #[cfg(not(all(feature = "bigint", feature="rational")))]
//! # mod test { pub fn approx_sqrt(n: u64, _: usize) -> u64 { n } }
//! # use test::approx_sqrt;
//!
//! fn main() {
//!     println!("{}", approx_sqrt(10, 4)); // prints 4057691201/1283082416
//! }
//!
//! ```
//!
//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
       html_root_url = "https://rust-num.github.io/num/",
       html_playground_url = "http://play.integer32.com/")]

extern crate num_traits;
extern crate num_integer;
extern crate num_iter;
#[cfg(feature = "num-complex")]
extern crate num_complex;
#[cfg(feature = "num-bigint")]
extern crate num_bigint;
#[cfg(feature = "num-rational")]
extern crate num_rational;

#[cfg(feature = "num-bigint")]
pub use num_bigint::{BigInt, BigUint};
#[cfg(feature = "num-rational")]
pub use num_rational::Rational;
#[cfg(all(feature = "num-rational", feature="num-bigint"))]
pub use num_rational::BigRational;
#[cfg(feature = "num-complex")]
pub use num_complex::Complex;
pub use num_integer::Integer;
pub use num_iter::{range, range_inclusive, range_step, range_step_inclusive};
pub use num_traits::{Num, Zero, One, Signed, Unsigned, Bounded,
                     one, zero, abs, abs_sub, signum,
                     Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
                     PrimInt, Float, ToPrimitive, FromPrimitive, NumCast, cast,
                     pow, checked_pow};

#[cfg(feature = "num-bigint")]
pub mod bigint {
    pub use num_bigint::*;
}

#[cfg(feature = "num-complex")]
pub mod complex {
    pub use num_complex::*;
}

pub mod integer {
    pub use num_integer::*;
}

pub mod iter {
    pub use num_iter::*;
}

pub mod traits {
    pub use num_traits::*;
}

#[cfg(feature = "num-rational")]
pub mod rational {
    pub use num_rational::*;
}

pub fn clamp<T: PartialOrd + Copy>(input: T, min: T, max: T) -> T {
    debug_assert!(min < max, "min must be less than max");
    if input < min {min}
    else if input > max {max}
    else {input}
}
<commit_msg>Changing to >= and <= as it's a slight optimization<commit_after>// Copyright 2014-2016 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.

//! A collection of numeric types and traits for Rust.
//!
//! This includes new types for big integers, rationals, and complex numbers,
//! new traits for generic programming on numeric properties like `Integer`,
//! and generic range iterators.
//!
//! ## Example
//!
//! This example uses the BigRational type and [Newton's method][newt] to
//! approximate a square root to arbitrary precision:
//!
//! ```
//! extern crate num;
//! # #[cfg(all(feature = "bigint", feature="rational"))]
//! # mod test {
//!
//! use num::FromPrimitive;
//! use num::bigint::BigInt;
//! use num::rational::{Ratio, BigRational};
//!
//! # pub
//! fn approx_sqrt(number: u64, iterations: usize) -> BigRational {
//!     let start: Ratio<BigInt> = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap());
//!     let mut approx = start.clone();
//!
//!     for _ in 0..iterations {
//!         approx = (&approx + (&start / &approx)) /
//!             Ratio::from_integer(FromPrimitive::from_u64(2).unwrap());
//!     }
//!
//!     approx
//! }
//! # }
//! # #[cfg(not(all(feature = "bigint", feature="rational")))]
//! # mod test { pub fn approx_sqrt(n: u64, _: usize) -> u64 { n } }
//! # use test::approx_sqrt;
//!
//! fn main() {
//!     println!("{}", approx_sqrt(10, 4)); // prints 4057691201/1283082416
//! }
//!
//! ```
//!
//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
       html_root_url = "https://rust-num.github.io/num/",
       html_playground_url = "http://play.integer32.com/")]

extern crate num_traits;
extern crate num_integer;
extern crate num_iter;
#[cfg(feature = "num-complex")]
extern crate num_complex;
#[cfg(feature = "num-bigint")]
extern crate num_bigint;
#[cfg(feature = "num-rational")]
extern crate num_rational;

#[cfg(feature = "num-bigint")]
pub use num_bigint::{BigInt, BigUint};
#[cfg(feature = "num-rational")]
pub use num_rational::Rational;
#[cfg(all(feature = "num-rational", feature="num-bigint"))]
pub use num_rational::BigRational;
#[cfg(feature = "num-complex")]
pub use num_complex::Complex;
pub use num_integer::Integer;
pub use num_iter::{range, range_inclusive, range_step, range_step_inclusive};
pub use num_traits::{Num, Zero, One, Signed, Unsigned, Bounded,
                     one, zero, abs, abs_sub, signum,
                     Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
                     PrimInt, Float, ToPrimitive, FromPrimitive, NumCast, cast,
                     pow, checked_pow};

#[cfg(feature = "num-bigint")]
pub mod bigint {
    pub use num_bigint::*;
}

#[cfg(feature = "num-complex")]
pub mod complex {
    pub use num_complex::*;
}

pub mod integer {
    pub use num_integer::*;
}

pub mod iter {
    pub use num_iter::*;
}

pub mod traits {
    pub use num_traits::*;
}

#[cfg(feature = "num-rational")]
pub mod rational {
    pub use num_rational::*;
}

pub fn clamp<T: PartialOrd + Copy>(input: T, min: T, max: T) -> T {
    debug_assert!(min < max, "min must be less than max");
    if input <= min {min}
    else if input >= max {max}
    else {input}
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![feature(std_misc)]

//! Interpolation algorithms.
//!
//! Interpolation is used in animation,
//! to describe smooth shapes and to make transitions.
//! Any object that fullfill certain mathematical
//! properties can be interpolated.
//! A common technique is using one ore more 'numbers'
//! controlling the mixture of states.
//! The choice of interpolation algorithm depends often
//! on the circumstances where it used.

pub use ease::{
    Ease,
    EaseFunction,
};
pub use spatial::Spatial;

mod ease;
mod spatial;

/// Performs linear interpolation.
/// A linear interpolation consists of two states 'a' and 'b'.
/// The 't' variable is a factor between 0 and 1 that
/// gives weight to 'a' or 'b'.
/// When 't' is zero then 'a' has full weight.
/// When 't' is one then 'b' has full weight.
#[inline(always)]
pub fn lerp<T: Spatial>(a: &T, b: &T, t: &<T as Spatial>::Scalar) -> T {
    a.add(&b.sub(a).scale(t))
}

/// Performs quadratic beziér interpolation.
/// This is done by nesting linear interpolations.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn quad_bez<T: Spatial>(
    x0: &T,
    x1: &T,
    x2: &T,
    t: &<T as Spatial>::Scalar
) -> T {
    let x_0_1 = lerp(x0, x1, t);
    let x_1_2 = lerp(x1, x2, t);
    lerp(&x_0_1, &x_1_2, t)
}

/// Performs cubic beziér interpolation.
/// This is done by interpolation between two quadratic beziér.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn cub_bez<T: Spatial>(
    x0: &T,
    x1: &T,
    x2: &T,
    x3: &T,
    t: &<T as Spatial>::Scalar
) -> T {
    let x_0_2 = quad_bez(x0, x1, x2, t);
    let x_1_3 = quad_bez(x1, x2, x3, t);
    lerp(&x_0_2, &x_1_3, t)
}
<commit_msg>Fixed warnings.<commit_after>#![deny(missing_docs)]
#![feature(std_misc, core)]

//! Interpolation algorithms.
//!
//! Interpolation is used in animation,
//! to describe smooth shapes and to make transitions.
//! Any object that fullfill certain mathematical
//! properties can be interpolated.
//! A common technique is using one ore more 'numbers'
//! controlling the mixture of states.
//! The choice of interpolation algorithm depends often
//! on the circumstances where it used.

pub use ease::{
    Ease,
    EaseFunction,
};
pub use spatial::Spatial;

mod ease;
mod spatial;

/// Performs linear interpolation.
/// A linear interpolation consists of two states 'a' and 'b'.
/// The 't' variable is a factor between 0 and 1 that
/// gives weight to 'a' or 'b'.
/// When 't' is zero then 'a' has full weight.
/// When 't' is one then 'b' has full weight.
#[inline(always)]
pub fn lerp<T: Spatial>(a: &T, b: &T, t: &<T as Spatial>::Scalar) -> T {
    a.add(&b.sub(a).scale(t))
}

/// Performs quadratic beziér interpolation.
/// This is done by nesting linear interpolations.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn quad_bez<T: Spatial>(
    x0: &T,
    x1: &T,
    x2: &T,
    t: &<T as Spatial>::Scalar
) -> T {
    let x_0_1 = lerp(x0, x1, t);
    let x_1_2 = lerp(x1, x2, t);
    lerp(&x_0_1, &x_1_2, t)
}

/// Performs cubic beziér interpolation.
/// This is done by interpolation between two quadratic beziér.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn cub_bez<T: Spatial>(
    x0: &T,
    x1: &T,
    x2: &T,
    x3: &T,
    t: &<T as Spatial>::Scalar
) -> T {
    let x_0_2 = quad_bez(x0, x1, x2, t);
    let x_1_3 = quad_bez(x1, x2, x3, t);
    lerp(&x_0_2, &x_1_3, t)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins)
//! within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [package]
//!   build = "build.rs"
//!
//!   [build-dependencies]
//!   capnpc = "*"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     ::capnpc::compile("schema", &["schema/foo.capnp", "schema/bar.capnp"]).unwrap();
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
pub mod schema;

use std::path::Path;

fn run_command(mut command: ::std::process::Command) -> ::capnp::Result<()> {
    let mut p = try!(command.spawn());
    try!(::codegen::main(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    let exit_status = try!(p.wait());
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

pub fn compile<P1, P2>(src_prefix: P1, files: &[P2]) -> ::capnp::Result<()>
    where P1: AsRef<Path>, P2: AsRef<Path>
{
    let mut command = ::std::process::Command::new("capnp");
    command.arg("compile").arg("-o").arg("-")
           .arg(&format!("--src-prefix={}", src_prefix.as_ref().display()));

    for file in files {
        command.arg(&format!("{}", file.as_ref().display()));
    }

    command.stdout(::std::process::Stdio::piped());
    command.stderr(::std::process::Stdio::inherit());

    run_command(command).map_err(|error| {
        ::capnp::Error::failed(format!("Error while trying to execute `capnp compile`: {}.  \
                                       Perhaps the capnp executable is not installed \
                                       on your system? See https://capnproto.org/install.html",
                                       error))})
}
<commit_msg>Include required version number in error message.<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins)
//! within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [package]
//!   build = "build.rs"
//!
//!   [build-dependencies]
//!   capnpc = "*"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     ::capnpc::compile("schema", &["schema/foo.capnp", "schema/bar.capnp"]).unwrap();
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
pub mod schema;

use std::path::Path;

fn run_command(mut command: ::std::process::Command) -> ::capnp::Result<()> {
    let mut p = try!(command.spawn());
    try!(::codegen::main(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    let exit_status = try!(p.wait());
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

pub fn compile<P1, P2>(src_prefix: P1, files: &[P2]) -> ::capnp::Result<()>
    where P1: AsRef<Path>, P2: AsRef<Path>
{
    let mut command = ::std::process::Command::new("capnp");
    command.arg("compile").arg("-o").arg("-")
           .arg(&format!("--src-prefix={}", src_prefix.as_ref().display()));

    for file in files {
        command.arg(&format!("{}", file.as_ref().display()));
    }

    command.stdout(::std::process::Stdio::piped());
    command.stderr(::std::process::Stdio::inherit());

    run_command(command).map_err(|error| {
        ::capnp::Error::failed(format!("Error while trying to execute `capnp compile`: {}.  \
                                        Please verify that version 0.5.2 or higher of the capnp executable \
                                        is installed on your system. See https://capnproto.org/install.html",
                                        error))})
}
<|endoftext|>


<commit_before>//! Strava API
//!

extern crate hyper;
extern crate rustc_serialize;

pub mod error;

pub mod api;
mod http;
mod map;
mod split;

pub mod athlete;

mod activity;
// pub use activity::Activity;
pub use activity::ActivityType;

pub mod segment;

<commit_msg>Add a mod comment in lib.rs<commit_after>//! A wrapper for the Strava API
//!
//! # Organization
//!
//! The module layout in this crate mirrors the [Strava API documentation][]. All functions
//! interacting with the strava servers will return a
//! [`strava::error::Result`](error/type.Result.html) for which the `E` parameter is curried to
//! [`strava::error::ApiError`](error/enum.ApiError.html).
//!
//! [Strava API Documentation]: http://strava.github.io/api/

extern crate hyper;
extern crate rustc_serialize;

pub mod error;

pub mod api;
mod http;
mod map;
mod split;

pub mod athlete;

mod activity;
// pub use activity::Activity;
pub use activity::ActivityType;

pub mod segment;

<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<commit_msg>Added search_map utility<commit_after>#![feature(rust_2018_preview, nll)]

use std::collections as col;
use std::cmp;
use std::ops;
use std::rc;

#[derive(Clone, Debug)]
struct LayoutRef(rc::Rc<LayoutContents>);

impl LayoutRef {
    fn contents(&self) -> &LayoutContents {
        &*self.0
    }
}

impl ops::Deref for LayoutRef {
    type Target = LayoutContents;
    fn deref(&self) -> &LayoutContents {
        self.contents()
    }
}

impl AsRef<LayoutContents> for LayoutRef {
    fn as_ref(&self) -> &LayoutContents {
        self.contents()
    }
}

#[derive(Debug)]
enum LayoutContents {
    Text(String),
    Horiz(LayoutRef, LayoutRef),
    Vert(LayoutRef, LayoutRef),
    Choice(LayoutRef, LayoutRef),
}

trait OrdAs {
    type AsType: Eq + PartialEq + Ord + PartialOrd;
    fn ord_as(&self) -> Self::AsType;
}

struct OrdAsKey<T>(T);

impl<T> ops::Deref for OrdAsKey<T> {
    type Target = T;
    fn deref(&self) -> &T { &self.0 }
}

impl<T> ops::DerefMut for OrdAsKey<T> {
    fn deref_mut(&mut self) -> &mut T { &mut self.0 }
}

impl<T: OrdAs> Ord for OrdAsKey<T> {
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.0.ord_as().cmp(&other.0.ord_as())
    }
}

impl<T: OrdAs> PartialOrd for OrdAsKey<T> {
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: OrdAs> Eq for OrdAsKey<T> {

}

impl<T: OrdAs> PartialEq for OrdAsKey<T> {
    fn eq(&self, other: &Self) -> bool {
        self.0.ord_as().eq(&other.0.ord_as())
    }
}

#[derive(Copy, Clone, Debug)]
struct RefMapKey<'a, K: 'a>(&'a K);

impl<'a, K: 'a> OrdAs for RefMapKey<'a, K> {
    type AsType = *const K;
    fn ord_as(&self) -> *const K { self.0 }
}

struct RefMap<'a, K: 'a, V> {
    map: col::BTreeMap<OrdAsKey<RefMapKey<'a, K>>, V>,
}

impl<'a, K: 'a, V> RefMap<'a, K, V> {
    fn insert(&mut self, key: &'a (impl AsRef<K>), value: V) -> Option<V> {
        self.map.insert(OrdAsKey(RefMapKey(key.as_ref())), value)
    }

    fn iter<'b: 'a>(&'b self) -> impl Iterator<Item = (&'a K, &'b V)> {
        self.map.iter().map(|(k, v)| ((k.0).0, v))
    }
}

// ReducedLayout

#[derive(Debug)]
enum ReducedLayout {
    Text(String),
    Horiz(String, ReducedLayoutRef),
    Vert(ReducedLayoutRef, ReducedLayoutRef),
    Choice(ReducedLayoutRef, ReducedLayoutRef),
}

#[derive(Clone, Debug)]
struct ReducedLayoutRef(rc::Rc<ReducedLayout>);

impl ReducedLayoutRef {
    fn new(layout: ReducedLayout) -> Self { ReducedLayoutRef(rc::Rc::new(layout)) }
}

impl ops::Deref for ReducedLayoutRef {
    type Target = ReducedLayout;
    fn deref(&self) -> &ReducedLayout {
        &*self.0
    }
}

mod layout_reducer {

use super::LayoutContents;
use super::ReducedLayout;
use super::ReducedLayoutRef;
use super::LayoutRef;

use std::collections as col;

struct LayoutReducer {
    memo: col::BTreeMap<(*const LayoutContents, Option<*const ReducedLayout>), ReducedLayoutRef>,
}

impl LayoutReducer {
    fn new() -> Self {
        LayoutReducer { memo: col::BTreeMap::new() }
    }

    fn reduce(&mut self, layout: &LayoutRef, trailer: Option<&ReducedLayoutRef>) -> ReducedLayoutRef {
        let layout_ptr = &**layout;
        let trailer_ptr = trailer.map(|t| &**t as *const ReducedLayout);
        match self.memo.get(&(layout_ptr, trailer_ptr)) {
            Some(v) => v.clone(),
            None => {
                let result = self.reduce_real(layout, trailer);
                self.memo.insert((layout_ptr, trailer_ptr), result.clone());
                result
            }
        }
    }

    fn reduce_real(&mut self, layout: &LayoutRef, trailer: Option<&ReducedLayoutRef>) -> ReducedLayoutRef {
        match layout.contents() {
            LayoutContents::Text(text) => match trailer {
                Some(trailer_val) => ReducedLayoutRef::new(ReducedLayout::Horiz(text.clone(), trailer_val.clone())),
                None => ReducedLayoutRef::new(ReducedLayout::Text(text.clone())),
            }
            LayoutContents::Horiz(left, right) => {
                let reduced_right = self.reduce(right, trailer);
                self.reduce(left, Some(&reduced_right))
            }
            LayoutContents::Vert(top, bottom) => {
                let reduced_top = self.reduce(top, None);
                let reduced_bottom = self.reduce(bottom, trailer);
                ReducedLayoutRef::new(ReducedLayout::Vert(reduced_top, reduced_bottom))
            }
            LayoutContents::Choice(left, right) => {
                let reduced_left = self.reduce(left, trailer);
                let reduced_right = self.reduce(right, trailer);
                ReducedLayoutRef::new(ReducedLayout::Choice(reduced_left, reduced_right))
            }
        }
    }
}

pub(super) fn reduce_layout(layout: &LayoutRef) -> ReducedLayoutRef {
    let mut reducer = LayoutReducer::new();
    reducer.reduce(layout, None)
}

}

use layout_reducer::reduce_layout;

#[derive(Clone, Debug)]
enum ResolvedLayout {
    Text(String),
    Horiz(ResolvedLayoutRef, ResolvedLayoutRef),
    Vert(ResolvedLayoutRef, ResolvedLayoutRef),
}

#[derive(Clone, Debug)]
struct ResolvedLayoutRef(std::rc::Rc<ResolvedLayout>);

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
struct KnotColumn(u16);

struct KnotData {
    // The layout as resolved.
    resolved_layout: ResolvedLayoutRef,

    /// The number of characters in the last line
    span: u16,

    /// The cost value at knot start
    intercept: f32,

    /// The cost increment per column after knot start
    rise: f32,
}

#[derive(Copy, Clone, Debug)]
enum SearchDirection {
    Less,
    LessEq,
    Greater,
    GreaterEq,
}

fn search_map<'a, T, K, V>(map: &'a col::BTreeMap<K, V>, search_key: &T, direction: SearchDirection) -> Option<(&'a K, &'a V)>
where K: std::borrow::Borrow<T> + cmp::Ord, T: cmp::Ord {
        match direction {
            SearchDirection::Less => {
                let mut range = map.range((ops::Bound::Unbounded, ops::Bound::Excluded(search_key)));
                range.next_back()
            }
            SearchDirection::LessEq => {
                let mut range = map.range((ops::Bound::Unbounded, ops::Bound::Included(search_key)));
                range.next_back()
            }
            SearchDirection::Greater => {
                let mut range = map.range((ops::Bound::Excluded(search_key), ops::Bound::Unbounded));
                range.next()
            }
            SearchDirection::GreaterEq => {
                let mut range = map.range((ops::Bound::Excluded(search_key), ops::Bound::Unbounded));
                range.next()
            }
        }
}

struct KnotSet {
    knots: col::BTreeMap<KnotColumn, KnotData>
}

impl KnotSet {
    fn cost_at(&self, col: KnotColumn) -> f32 {
        unimplemented!()
    }

    fn left_knot_data(&self, col: KnotColumn) -> Option<(KnotColumn, &KnotData)> {
        let mut range = self.knots.range((ops::Bound::Unbounded, ops::Bound::Excluded(col)));
        range.next_back().map(|(k, v)| (*k, v))
    }

    fn right_knot_data(&self, col: KnotColumn) -> Option<(KnotColumn, &KnotData)> {
        let mut range = self.knots.range((ops::Bound::Included(col), ops::Bound::Unbounded));
        range.next().map(|(k, v)| (*k, v))
    }
}

struct KnotSetBuilder {
    margin: u16,
    overflow_cost: f32,
    newline_cost: f32,
}

impl KnotSetBuilder {
    pub fn new_text(&self, text: impl Into<String>) -> KnotSet {
        let text_str = text.into();
        let text_len = text_str.len() as u16;
        let layout = ResolvedLayoutRef(rc::Rc::new(ResolvedLayout::Text(text_str)));
        let mut knots = col::BTreeMap::new();
        if text_len < self.margin {
            let flat_data = KnotData {
                resolved_layout: layout.clone(),
                span: text_len,
                intercept: 0.0,
                rise: 0.0,
            };
            knots.insert(KnotColumn(0), flat_data);

            let rise_data = KnotData {
                resolved_layout: layout,
                span: text_len,
                intercept: 0.0,
                rise: self.overflow_cost,
            };

            knots.insert(KnotColumn(self.margin - text_len), rise_data);
        } else {
            let rise_data = KnotData {
                resolved_layout: layout,
                span: text_len,
                intercept: self.overflow_cost * ((text_len - self.margin) as f32),
                rise: self.overflow_cost,
            };
            knots.insert(KnotColumn(0), rise_data);
        }
        KnotSet {
            knots: knots,
        }
    }

    pub fn new_vert(&self, top: KnotSet, bottom: KnotSet) -> KnotSet {
        unimplemented!()
    }

    pub fn new_horiz(&self, left: KnotSet, right: KnotSet) -> KnotSet {
        unimplemented!()
    }

    pub fn new_choice(&self, choice1: KnotSet, choice2: KnotSet) -> KnotSet {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::server::{Handler, Request, Response};
use regex::RegexSet;

use error::RouterError;

pub type RouterFn = fn(Request, Response);

pub struct Router {
    not_found: Option<RouterFn>,
    routes: Option<RegexSet>,
    route_list: Vec<String>,
    route_map: HashMap<String, RouterFn>
}

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.clone().unwrap().matches(&uri);
        let route = matches.iter().next();
        match route {
            Some(r) => {
                let key = &self.route_list[r];
                let handler = self.route_map.get(key).unwrap();
                handler(req, res);
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: None,
            route_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against.
    pub fn add_route(&mut self, route: &str, handler: RouterFn) {
        self.route_list.push(route.to_owned());
        self.route_map.insert(route.to_owned(), handler);
    }

    /// This function ensures that a valid RegexSet could be made from the route
    /// vector that was built while using the `add_route` function. It also
    /// requires that there exist two or more routes so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), RouterError> {
        if self.route_list.len() == 0  {
            return Err(RouterError::TooFewRoutes);
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = Some(r);
                Ok(())
            }
            Err(_) => {
                Err(RouterError::BadSet)
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: RouterFn) {
        self.not_found = Some(not_found)
    }
}

fn default_not_found(req: Request, res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    res.send(message.as_bytes()).unwrap();
}

mod error;

#[test]
#[should_panic]
#[allow(dead_code)]
fn less_than_two_routes() {
    fn test_handler(_: Request, _: Response) {}

    let mut router = Router::new();
    router.finalize().unwrap();
}
<commit_msg>remove no longer needed function<commit_after>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::server::{Handler, Request, Response};
use regex::RegexSet;

use error::RouterError;

pub type RouterFn = fn(Request, Response);

pub struct Router {
    not_found: Option<RouterFn>,
    routes: Option<RegexSet>,
    route_list: Vec<String>,
    route_map: HashMap<String, RouterFn>
}

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.clone().unwrap().matches(&uri);
        let route = matches.iter().next();
        match route {
            Some(r) => {
                let key = &self.route_list[r];
                let handler = self.route_map.get(key).unwrap();
                handler(req, res);
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: None,
            route_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against.
    pub fn add_route(&mut self, route: &str, handler: RouterFn) {
        self.route_list.push(route.to_owned());
        self.route_map.insert(route.to_owned(), handler);
    }

    /// This function ensures that a valid RegexSet could be made from the route
    /// vector that was built while using the `add_route` function. It also
    /// requires that there exist two or more routes so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), RouterError> {
        if self.route_list.len() == 0  {
            return Err(RouterError::TooFewRoutes);
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = Some(r);
                Ok(())
            }
            Err(_) => {
                Err(RouterError::BadSet)
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: RouterFn) {
        self.not_found = Some(not_found)
    }
}

fn default_not_found(req: Request, res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    res.send(message.as_bytes()).unwrap();
}

mod error;

#[test]
#[should_panic]
fn less_than_two_routes() {
    let mut router = Router::new();
    router.finalize().unwrap();
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A simple and type agnostic quaternion math designed for reexporting

extern crate vecmath;

use std::num::Float;

/// Quaternion type alias.
pub type Quaternion<T> = [T; 4];

pub use vecmath::vec4_add as add;

/// Multiplies two quaternions.
#[inline(always)]
pub fn mul<T: Float + Copy>(
    a: Quaternion<T>,
    b: Quaternion<T>
) -> Quaternion<T> {
    use vecmath::vec3_cross as cross;
    use vecmath::vec3_add as add;
    use vecmath::vec3_dot as dot;
    use vecmath::vec3_scale as scale;

    let r1 = a[0];
    let r2 = b[0];
    let v1 = [a[1], a[2], a[3]];
    let v2 = [b[1], b[2], b[3]];
    let scalar = r1 * r2 - dot(v1, v2);
    let vector = add(
        add(scale(v2, r1), scale(v1, r2)),
        cross(v1, v2)
    );
    [scalar, vector[0], vector[1], vector[2]]
}

<commit_msg>Added `conj`<commit_after>#![deny(missing_docs)]

//! A simple and type agnostic quaternion math designed for reexporting

extern crate vecmath;

use std::num::Float;

/// Quaternion type alias.
pub type Quaternion<T> = [T; 4];

pub use vecmath::vec4_add as add;

/// Multiplies two quaternions.
#[inline(always)]
pub fn mul<T: Float + Copy>(
    a: Quaternion<T>,
    b: Quaternion<T>
) -> Quaternion<T> {
    use vecmath::vec3_cross as cross;
    use vecmath::vec3_add as add;
    use vecmath::vec3_dot as dot;
    use vecmath::vec3_scale as scale;

    let r1 = a[0];
    let r2 = b[0];
    let v1 = [a[1], a[2], a[3]];
    let v2 = [b[1], b[2], b[3]];
    let scalar = r1 * r2 - dot(v1, v2);
    let vector = add(
        add(scale(v2, r1), scale(v1, r2)),
        cross(v1, v2)
    );
    [scalar, vector[0], vector[1], vector[2]]
}

/// Takes the quaternion conjugate.
#[inline(always)]
pub fn conj<T: Float>(a: Quaternion<T>) -> Quaternion<T> {
    [a[0], -a[1], -a[2], -a[3]]
}

<|endoftext|>