<commit_before>/// 2D grid coordinate
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Coord {
    pub x: usize,
    pub y: usize
}

/// 2D grid dimensions
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Size {
    pub width: usize,
    pub height: usize
}

impl Coord {
    /// Create a grid coordinate at (x, y)
    pub fn new(x: usize, y: usize) -> Coord {
        Coord {
            x: x,
            y: y
        }
    }
}

impl Size {
    /// Create a grid size of (width, height)
    pub fn new(width: usize, height: usize) -> Size {
        Size {
            width: width,
            height: height
        }
    }

    pub fn area(&self) -> usize {
        self.width * self.height
    }

    /// Return true if the coordinate fits within self's width and
    /// height, false otherwise.
    pub fn contains_coord(&self, coord: Coord) -> bool {
        coord.x < self.width && coord.y < self.height
    }
}

/// Rectangle defined by inclusive minimum and maximum coordinates
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Rect {
    /// Minimum coordinate (inclusive)
    min_coord: Coord,

    /// Maximum coordinate (inclusive)
    max_coord: Coord
}

impl Rect {
    fn width(&self) -> usize {
        return self.max_coord.x - self.min_coord.x + 1;
    }
}

pub struct Vec2D<T> {
    elems: Vec<T>,
    size: Size
}

impl<Elem: Copy> Vec2D<Elem> {
    pub fn from_example(size: Size, example: &Elem) -> Vec2D<Elem> {
        Vec2D {
            elems: vec![*example; size.area()],
            size: size
        }
    }

    pub fn from_vec(size: Size, src: Vec<Elem>) -> Option<Vec2D<Elem>> {
        if size.area() == src.len() {
            Some(Vec2D {
                elems: src,
                size: size
            })
        }
        else {
            None
        }
    }

    pub fn rect_iter_mut<'a>(&'a mut self, rect: Rect) -> Option<RectIterMut<'a, Elem>> {
        if self.size.contains_coord(rect.max_coord) {
            Some(RectIterMut {
                stride: (self.size.width - rect.width()) as isize,
                cur_elem: self.elems.as_mut_ptr(),
                grid: self,
                rect: rect,
                cur_coord: rect.min_coord
            })
        }
        else {
            None
        }
    }
}

impl<'a, Elem> Iterator for RectIterMut<'a, Elem> {
    type Item = (Coord, &'a mut Elem);

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur_coord.y <= self.rect.max_coord.y {
            let result = (self.cur_coord, unsafe { &mut *self.cur_elem });

            self.cur_coord.x += 1;
            if self.cur_coord.x <= self.rect.max_coord.x {
                unsafe { self.cur_elem.offset(1); }
            }
            else {
                self.cur_coord.x = self.rect.min_coord.x;
                self.cur_coord.y += 1;
                unsafe { self.cur_elem.offset(self.stride); }
            }
            Some(result)
        }
        else {
            None
        }
    }
}

pub struct RectIterMut<'a, Elem: 'a> {
    grid: &'a mut Vec2D<Elem>,
    rect: Rect,
    cur_elem: *mut Elem,
    cur_coord: Coord,
    stride: isize
}

#[test]
fn test_rect_iter_mut() {
    let mut elems = vec![0, 1, 2, 3];
    let mut grid = Vec2D::from_vec(Size::new(2, 2), elems).unwrap();
    let rect = Rect::new(Coord::new(0, 0), Coord::new(1, 1)).unwrap();

    let mut actual_coords = Vec::new();
    for (coord, elem) in grid.rect_iter_mut(rect).unwrap() {
        *elem = -(*elem);
        actual_coords.push((coord.x, coord.y));
    }
    assert_eq!(actual_coords, [(0, 0), (1, 0), (0, 1), (1, 1)]);
}

impl Rect {
    /// Create a new Rect defined by inclusive minimum and maximum
    /// coordinates. If min_coord is greater than max_coord on either
    /// axis then None is returned.
    pub fn new(min_coord: Coord, max_coord: Coord) -> Option<Rect> {
        if min_coord.x <= max_coord.x && min_coord.y <= max_coord.y {
            Some(Rect {
                min_coord: min_coord,
                max_coord: max_coord
            })
        }
        else {
            None
        }
    }

}

// pub struct RectIter<usize: Copy + Unsigned> {
//     rect: Rect,
//     cur_coord: Coord
// }

// impl<usize: Copy + Ord + Unsigned + Add<Output=usize> + num::One> Iterator for RectIter {
//     type Item = Coord;

//     fn next(&mut self) -> Option<Self::Item> {
//         if self.cur_coord.y <= self.rect.max_coord.y {
//             let result = Some(self.cur_coord);
//             self.cur_coord.x = self.cur_coord.x + usize::one();
//             if self.cur_coord.x > self.rect.max_coord.x {
//                 self.cur_coord.x = self.rect.min_coord.x;
//                 self.cur_coord.y = self.cur_coord.y + usize::one();
//             }
//             result
//         }
//         else {
//             None
//         }
//     }
// }

// #[test]
// fn test_rect_iter() {
//     let rect = Rect::new(Coord::new(1, 2), Coord::new(3, 4)).unwrap();
//     let coords: Vec<Coord<u8>> = rect.iter().collect();
//     assert_eq!(coords, [
//         Coord::new(1, 2), Coord::new(2, 2), Coord::new(3, 2),
//         Coord::new(1, 3), Coord::new(2, 3), Coord::new(3, 3),
//         Coord::new(1, 4), Coord::new(2, 4), Coord::new(3, 4)]);
// }

// pub struct DataRectIter<'s, S: 's, usize: Copy + Unsigned> {
//     data: &'s [S],
//     cur_elem: *const S,
//     cur_coord: Coord,
//     full: Rect,
//     part: Rect
// }

// impl<'s, S: 's, usize: Copy + Unsigned> Iterator for DataRectIter<'s, S, usize> {
//     type Item = (Coord, &'s S);

//     fn next(&mut self) -> Option<Self::Item> {
//         unsafe {
//             self.cur_elem = self.cur_elem.offset(1);
//         }
//         None
//     }
// }

<commit_msg>warning fix<commit_after>/// 2D grid coordinate
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Coord {
    pub x: usize,
    pub y: usize
}

/// 2D grid dimensions
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Size {
    pub width: usize,
    pub height: usize
}

impl Coord {
    /// Create a grid coordinate at (x, y)
    pub fn new(x: usize, y: usize) -> Coord {
        Coord {
            x: x,
            y: y
        }
    }
}

impl Size {
    /// Create a grid size of (width, height)
    pub fn new(width: usize, height: usize) -> Size {
        Size {
            width: width,
            height: height
        }
    }

    pub fn area(&self) -> usize {
        self.width * self.height
    }

    /// Return true if the coordinate fits within self's width and
    /// height, false otherwise.
    pub fn contains_coord(&self, coord: Coord) -> bool {
        coord.x < self.width && coord.y < self.height
    }
}

/// Rectangle defined by inclusive minimum and maximum coordinates
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Rect {
    /// Minimum coordinate (inclusive)
    min_coord: Coord,

    /// Maximum coordinate (inclusive)
    max_coord: Coord
}

impl Rect {
    fn width(&self) -> usize {
        return self.max_coord.x - self.min_coord.x + 1;
    }
}

pub struct Vec2D<T> {
    elems: Vec<T>,
    size: Size
}

impl<Elem: Copy> Vec2D<Elem> {
    pub fn from_example(size: Size, example: &Elem) -> Vec2D<Elem> {
        Vec2D {
            elems: vec![*example; size.area()],
            size: size
        }
    }

    pub fn from_vec(size: Size, src: Vec<Elem>) -> Option<Vec2D<Elem>> {
        if size.area() == src.len() {
            Some(Vec2D {
                elems: src,
                size: size
            })
        }
        else {
            None
        }
    }

    pub fn rect_iter_mut<'a>(&'a mut self, rect: Rect) -> Option<RectIterMut<'a, Elem>> {
        if self.size.contains_coord(rect.max_coord) {
            Some(RectIterMut {
                stride: (self.size.width - rect.width()) as isize,
                cur_elem: self.elems.as_mut_ptr(),
                grid: self,
                rect: rect,
                cur_coord: rect.min_coord
            })
        }
        else {
            None
        }
    }
}

impl<'a, Elem> Iterator for RectIterMut<'a, Elem> {
    type Item = (Coord, &'a mut Elem);

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur_coord.y <= self.rect.max_coord.y {
            let result = (self.cur_coord, unsafe { &mut *self.cur_elem });

            self.cur_coord.x += 1;
            if self.cur_coord.x <= self.rect.max_coord.x {
                unsafe { self.cur_elem.offset(1); }
            }
            else {
                self.cur_coord.x = self.rect.min_coord.x;
                self.cur_coord.y += 1;
                unsafe { self.cur_elem.offset(self.stride); }
            }
            Some(result)
        }
        else {
            None
        }
    }
}

pub struct RectIterMut<'a, Elem: 'a> {
    grid: &'a mut Vec2D<Elem>,
    rect: Rect,
    cur_elem: *mut Elem,
    cur_coord: Coord,
    stride: isize
}

#[test]
fn test_rect_iter_mut() {
    let elems = vec![0, 1, 2, 3];
    let mut grid = Vec2D::from_vec(Size::new(2, 2), elems).unwrap();
    let rect = Rect::new(Coord::new(0, 0), Coord::new(1, 1)).unwrap();

    let mut actual_coords = Vec::new();
    for (coord, elem) in grid.rect_iter_mut(rect).unwrap() {
        *elem = -(*elem);
        actual_coords.push((coord.x, coord.y));
    }
    assert_eq!(actual_coords, [(0, 0), (1, 0), (0, 1), (1, 1)]);
}

impl Rect {
    /// Create a new Rect defined by inclusive minimum and maximum
    /// coordinates. If min_coord is greater than max_coord on either
    /// axis then None is returned.
    pub fn new(min_coord: Coord, max_coord: Coord) -> Option<Rect> {
        if min_coord.x <= max_coord.x && min_coord.y <= max_coord.y {
            Some(Rect {
                min_coord: min_coord,
                max_coord: max_coord
            })
        }
        else {
            None
        }
    }

}

// pub struct RectIter<usize: Copy + Unsigned> {
//     rect: Rect,
//     cur_coord: Coord
// }

// impl<usize: Copy + Ord + Unsigned + Add<Output=usize> + num::One> Iterator for RectIter {
//     type Item = Coord;

//     fn next(&mut self) -> Option<Self::Item> {
//         if self.cur_coord.y <= self.rect.max_coord.y {
//             let result = Some(self.cur_coord);
//             self.cur_coord.x = self.cur_coord.x + usize::one();
//             if self.cur_coord.x > self.rect.max_coord.x {
//                 self.cur_coord.x = self.rect.min_coord.x;
//                 self.cur_coord.y = self.cur_coord.y + usize::one();
//             }
//             result
//         }
//         else {
//             None
//         }
//     }
// }

// #[test]
// fn test_rect_iter() {
//     let rect = Rect::new(Coord::new(1, 2), Coord::new(3, 4)).unwrap();
//     let coords: Vec<Coord<u8>> = rect.iter().collect();
//     assert_eq!(coords, [
//         Coord::new(1, 2), Coord::new(2, 2), Coord::new(3, 2),
//         Coord::new(1, 3), Coord::new(2, 3), Coord::new(3, 3),
//         Coord::new(1, 4), Coord::new(2, 4), Coord::new(3, 4)]);
// }

// pub struct DataRectIter<'s, S: 's, usize: Copy + Unsigned> {
//     data: &'s [S],
//     cur_elem: *const S,
//     cur_coord: Coord,
//     full: Rect,
//     part: Rect
// }

// impl<'s, S: 's, usize: Copy + Unsigned> Iterator for DataRectIter<'s, S, usize> {
//     type Item = (Coord, &'s S);

//     fn next(&mut self) -> Option<Self::Item> {
//         unsafe {
//             self.cur_elem = self.cur_elem.offset(1);
//         }
//         None
//     }
// }

<|endoftext|>


<commit_before>//! Module to access [the API][apidoc] of [TheTVDB.com][tvdb]
//!
//! [apidoc]: https://api.thetvdb.com/swagger
//! [tvdb]: http://thetvdb.com

extern crate log;

extern crate reqwest;
extern crate url;

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

// Module structure
pub mod raw;
mod data;
mod error;

// Main public API
pub use raw::{RequestClient, Tvdb};

// Expose error types
pub use error::{TvdbError, TvdbResult};

// Expose data types
pub use data::EpisodeId;
<commit_msg>data module needs to be public<commit_after>//! Module to access [the API][apidoc] of [TheTVDB.com][tvdb]
//!
//! [apidoc]: https://api.thetvdb.com/swagger
//! [tvdb]: http://thetvdb.com

extern crate log;

extern crate reqwest;
extern crate url;

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

// Module structure
pub mod raw;
pub mod data;
mod error;

// Main public API
pub use raw::{RequestClient, Tvdb};

// Expose error types
pub use error::{TvdbError, TvdbResult};

// Expose data types
pub use data::EpisodeId;
<|endoftext|>


<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.
//!
//! ```
//! # 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.5")]
#![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::Vec;

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")]`
///
/// ```
/// # 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")]`
///
/// ```
/// # 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.
///
/// ```
/// 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::String;
    #[cfg(feature = "alloc")]
    use alloc::vec::Vec;

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

    /// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
    ///
    /// ```
    /// 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) = 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>Resolve redundant_field_names lint<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.
//!
//! ```
//! # 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.5")]
#![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::Vec;

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")]`
///
/// ```
/// # 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")]`
///
/// ```
/// # 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.
///
/// ```
/// 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 }
    }
}

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::String;
    #[cfg(feature = "alloc")]
    use alloc::vec::Vec;

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

    /// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
    ///
    /// ```
    /// 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) = 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>use {TypedDecider, ImpliedDeciderImpl, MultiDeciderImpl, Decider, MultiDecider, Decision, Result,
     ErrorKind};

use std::sync::atomic::Ordering::{Relaxed, Release};
use std::time::{Instant, Duration};
use std::cmp;
use std::sync::Arc;

use crossbeam::epoch::{self, Atomic, Owned};

impl Decider for LeakyBucket {}

impl MultiDecider for LeakyBucket {}

impl TypedDecider for LeakyBucket {
    /// The leaky bucket can provide an approximation for how long to
    /// sleep until one token is available again. (This does not
    /// account for multiple requests attempting to use the same
    /// token; schedulers relying on this must account for phenomena
    /// like thundering herds.)
    type T = Duration;
}

#[derive(Debug, Clone)]
/// Implements the industry-standard leaky bucket rate-limiting
/// as-a-meter. The bucket keeps a "fill height", pretending to drip
/// steadily (which reduces the fill height), and increases the fill
/// height with every cell that is found conforming. If cells would
/// make the bucket overflow, they count as non-conforming.
///
/// # Drip implementation
///
/// Instead of having a background task update the bucket's fill
/// level, this implementation re-computes the fill level of the
/// bucket on every call to [`check`](#method.check) and related
/// methods.
///
/// # Wait time calculation
///
/// If the cell does not fit, this implementation computes the minimum
/// wait time until the cell can be accommodated. This minimum wait
/// time does not account for thundering herd effects or other
/// problems in concurrent resource acquisition, so users of this
/// library must take care to apply positive jitter to these wait
/// times.
///
/// # Thread safety
///
/// This implementation uses lock-free techniques to safely update the
/// bucket state in-place. This means the
/// [`.threadsafe`](#method.threadsafe) method returns self & will be
/// deprecated in a future release.
///
///
/// # Example
/// ``` rust
/// # use ratelimit_meter::{Decider, LeakyBucket, Decision};
/// let mut lb: LeakyBucket = LeakyBucket::per_second(2).unwrap();
/// assert_eq!(Decision::Yes, lb.check().unwrap());
/// ```
pub struct LeakyBucket {
    state: Arc<Atomic<BucketState>>,
    full: Duration,
    token_interval: Duration,
}

#[derive(Debug, Clone)]
struct BucketState {
    level: Duration,
    last_update: Option<Instant>,
}

impl LeakyBucket {
    /// Constructs and returns a leaky-bucket rate-limiter allowing as
    /// many cells on average as the given capacity per time duration.
    /// ## Example
    /// ``` rust
    /// # use ratelimit_meter::{Decider, LeakyBucket};
    /// # use std::time::{Duration, Instant};
    /// let now = Instant::now();
    /// let day = Duration::from_secs(86400);
    /// let mut lb = LeakyBucket::new(1, day).unwrap(); // 1 per day
    /// assert!(lb.check_at(now).unwrap().is_compliant());
    ///
    /// assert!(!lb.check_at(now + day/2).unwrap().is_compliant()); // Can't do it half a day later
    /// assert!(lb.check_at(now + day).unwrap().is_compliant()); // Have to wait a day
    /// // ...and then, a day after that.
    /// assert!(lb.check_at(now + day * 2).unwrap().is_compliant());
    /// ```
    pub fn new(capacity: u32, per_duration: Duration) -> Result<LeakyBucket> {
        if capacity == 0 {
            return Err(ErrorKind::InconsistentCapacity(capacity, 0).into());
        }
        let token_interval = per_duration / capacity;
        let state = Atomic::new(BucketState {
            level: Duration::new(0, 0),
            last_update: None,
        });
        Ok(LeakyBucket {
            state: Arc::new(state),
            token_interval: token_interval,
            full: per_duration,
        })
    }

    /// Constructs and returns a leaky-bucket rate-limiter allowing on
    /// average `capacity`/1s cells.
    pub fn per_second(capacity: u32) -> Result<LeakyBucket> {
        LeakyBucket::new(capacity, Duration::from_secs(1))
    }

    /// Returns `self`, as this implementation is threadsafe
    /// already. This method is deprecated and will be removed in a
    /// future release.
    pub fn threadsafe(self) -> LeakyBucket {
        self
    }
}

impl MultiDeciderImpl for LeakyBucket {
    fn test_n_and_update(&mut self, n: u32, t0: Instant) -> Result<Decision<Duration>> {
        let weight = self.token_interval * n;
        if weight > self.full {
            return Err(ErrorKind::InsufficientCapacity(n).into());
        }
        let mut new = Owned::new(BucketState {
            last_update: Some(t0),
            level: Duration::new(0, 0),
        });
        let guard = epoch::pin();

        loop {
            match self.state.load(Relaxed, &guard) {
                Some(state) => {
                    let last = state.last_update.unwrap_or(t0);
                    // Prevent time travel: If any parallel calls get re-ordered,
                    // or any tests attempt silly things, make sure to answer from
                    // the last query onwards instead.
                    let t0 = cmp::max(t0, last);
                    // Decrement the level by however much needed:
                    new.level = state.level - cmp::min(t0 - last, state.level);

                    let mut decision = Decision::Yes;
                    if weight + new.level <= self.full {
                        new.level = new.level + weight;
                    } else {
                        let wait_period = (weight + new.level) - self.full;
                        decision = Decision::No(wait_period);
                    }
                    match self.state.cas_and_ref(Some(state), new, Release, &guard) {
                        Ok(_) => {
                            return Ok(decision);
                        }
                        Err(owned) => {
                            new = owned;
                        }
                    }
                }
                None => {} // retry.
            }
        }
    }
}

impl ImpliedDeciderImpl for LeakyBucket {}
<commit_msg>Only CAS in the positive case<commit_after>use {TypedDecider, ImpliedDeciderImpl, MultiDeciderImpl, Decider, MultiDecider, Decision, Result,
     ErrorKind};

use std::sync::atomic::Ordering::{Relaxed, Release};
use std::time::{Instant, Duration};
use std::cmp;
use std::sync::Arc;

use crossbeam::epoch::{self, Atomic, Owned};

impl Decider for LeakyBucket {}

impl MultiDecider for LeakyBucket {}

impl TypedDecider for LeakyBucket {
    /// The leaky bucket can provide an approximation for how long to
    /// sleep until one token is available again. (This does not
    /// account for multiple requests attempting to use the same
    /// token; schedulers relying on this must account for phenomena
    /// like thundering herds.)
    type T = Duration;
}

#[derive(Debug, Clone)]
/// Implements the industry-standard leaky bucket rate-limiting
/// as-a-meter. The bucket keeps a "fill height", pretending to drip
/// steadily (which reduces the fill height), and increases the fill
/// height with every cell that is found conforming. If cells would
/// make the bucket overflow, they count as non-conforming.
///
/// # Drip implementation
///
/// Instead of having a background task update the bucket's fill
/// level, this implementation re-computes the fill level of the
/// bucket on every call to [`check`](#method.check) and related
/// methods.
///
/// # Wait time calculation
///
/// If the cell does not fit, this implementation computes the minimum
/// wait time until the cell can be accommodated. This minimum wait
/// time does not account for thundering herd effects or other
/// problems in concurrent resource acquisition, so users of this
/// library must take care to apply positive jitter to these wait
/// times.
///
/// # Thread safety
///
/// This implementation uses lock-free techniques to safely update the
/// bucket state in-place. This means the
/// [`.threadsafe`](#method.threadsafe) method returns self & will be
/// deprecated in a future release.
///
///
/// # Example
/// ``` rust
/// # use ratelimit_meter::{Decider, LeakyBucket, Decision};
/// let mut lb: LeakyBucket = LeakyBucket::per_second(2).unwrap();
/// assert_eq!(Decision::Yes, lb.check().unwrap());
/// ```
pub struct LeakyBucket {
    state: Arc<Atomic<BucketState>>,
    full: Duration,
    token_interval: Duration,
}

#[derive(Debug, Clone)]
struct BucketState {
    level: Duration,
    last_update: Option<Instant>,
}

impl LeakyBucket {
    /// Constructs and returns a leaky-bucket rate-limiter allowing as
    /// many cells on average as the given capacity per time duration.
    /// ## Example
    /// ``` rust
    /// # use ratelimit_meter::{Decider, LeakyBucket};
    /// # use std::time::{Duration, Instant};
    /// let now = Instant::now();
    /// let day = Duration::from_secs(86400);
    /// let mut lb = LeakyBucket::new(1, day).unwrap(); // 1 per day
    /// assert!(lb.check_at(now).unwrap().is_compliant());
    ///
    /// assert!(!lb.check_at(now + day/2).unwrap().is_compliant()); // Can't do it half a day later
    /// assert!(lb.check_at(now + day).unwrap().is_compliant()); // Have to wait a day
    /// // ...and then, a day after that.
    /// assert!(lb.check_at(now + day * 2).unwrap().is_compliant());
    /// ```
    pub fn new(capacity: u32, per_duration: Duration) -> Result<LeakyBucket> {
        if capacity == 0 {
            return Err(ErrorKind::InconsistentCapacity(capacity, 0).into());
        }
        let token_interval = per_duration / capacity;
        let state = Atomic::new(BucketState {
            level: Duration::new(0, 0),
            last_update: None,
        });
        Ok(LeakyBucket {
            state: Arc::new(state),
            token_interval: token_interval,
            full: per_duration,
        })
    }

    /// Constructs and returns a leaky-bucket rate-limiter allowing on
    /// average `capacity`/1s cells.
    pub fn per_second(capacity: u32) -> Result<LeakyBucket> {
        LeakyBucket::new(capacity, Duration::from_secs(1))
    }

    /// Returns `self`, as this implementation is threadsafe
    /// already. This method is deprecated and will be removed in a
    /// future release.
    pub fn threadsafe(self) -> LeakyBucket {
        self
    }
}

impl MultiDeciderImpl for LeakyBucket {
    fn test_n_and_update(&mut self, n: u32, t0: Instant) -> Result<Decision<Duration>> {
        let weight = self.token_interval * n;
        if weight > self.full {
            return Err(ErrorKind::InsufficientCapacity(n).into());
        }
        let mut new = Owned::new(BucketState {
            last_update: Some(t0),
            level: Duration::new(0, 0),
        });
        let guard = epoch::pin();

        loop {
            match self.state.load(Relaxed, &guard) {
                Some(state) => {
                    let last = state.last_update.unwrap_or(t0);
                    // Prevent time travel: If any parallel calls get re-ordered,
                    // or any tests attempt silly things, make sure to answer from
                    // the last query onwards instead.
                    let t0 = cmp::max(t0, last);
                    // Decrement the level by the amount the bucket
                    // has dripped in the meantime:
                    new.level = state.level - cmp::min(t0 - last, state.level);

                    // Determine if the cell fits & ensure it is recorded:
                    if weight + new.level <= self.full {
                        new.level = new.level + weight;
                        match self.state.cas_and_ref(Some(state), new, Release, &guard) {
                            Ok(_) => {
                                return Ok(Decision::Yes);
                            }
                            Err(owned) => {
                                new = owned;
                            }
                        }
                    } else {
                        let wait_period = (weight + new.level) - self.full;
                        return Ok(Decision::No(wait_period));
                    }
                }
                None => {} // retry.
            }
        }
    }
}

impl ImpliedDeciderImpl for LeakyBucket {}
<|endoftext|>


<commit_before>#![deny(
    absolute_paths_not_starting_with_crate,
    ambiguous_associated_items,
    anonymous_parameters,
    arithmetic_overflow,
    array_into_iter,
    bindings_with_variant_name,
    coherence_leak_check,
    conflicting_repr_hints,
    const_err,
    dead_code,
    deprecated,
    deprecated_in_future,
    ellipsis_inclusive_range_patterns,
    explicit_outlives_requirements,
    exported_private_dependencies,
    ill_formed_attribute_input,
    illegal_floating_point_literal_pattern,
    improper_ctypes,
    incomplete_features,
    indirect_structural_match,
    inline_no_sanitize,
    invalid_type_param_default,
    invalid_value,
    irrefutable_let_patterns,
    keyword_idents,
    late_bound_lifetime_arguments,
    macro_expanded_macro_exports_accessed_by_absolute_paths,
    meta_variable_misuse,
    missing_copy_implementations,
    missing_docs,
    missing_fragment_specifier,
    mutable_borrow_reservation_conflict,
    mutable_transmutes,
    no_mangle_const_items,
    no_mangle_generic_items,
    non_ascii_idents,
    non_camel_case_types,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    order_dependent_trait_objects,
    overflowing_literals,
    overlapping_patterns,
    path_statements,
    patterns_in_fns_without_body,
    private_doc_tests,
    private_in_public,
    proc_macro_derive_resolution_fallback,
    pub_use_of_private_extern_crate,
    redundant_semicolons,
    safe_packed_borrows,
    soft_unstable,
    stable_features,
    trivial_bounds,
    trivial_casts,
    trivial_numeric_casts,
    type_alias_bounds,
    tyvar_behind_raw_pointer,
    uncommon_codepoints,
    unconditional_panic,
    unconditional_recursion,
    unknown_crate_types,
    unnameable_test_items,
    unreachable_code,
    unreachable_patterns,
    unreachable_pub,
    unsafe_code,
    unstable_features,
    unstable_name_collisions,
    unused_allocation,
    unused_assignments,
    unused_attributes,
    unused_comparisons,
    unused_doc_comments,
    unused_extern_crates,
    unused_features,
    unused_import_braces,
    unused_imports,
    unused_labels,
    unused_lifetimes,
    unused_macros,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_unsafe,
    unused_variables,
    where_clauses_object_safety,
    while_true
)]
#![warn(macro_use_extern_crate, unknown_lints)]
#![allow(
    bare_trait_objects,
    box_pointers,
    elided_lifetimes_in_paths,
    intra_doc_link_resolution_failure,
    missing_doc_code_examples,
    missing_debug_implementations,
    single_use_lifetimes,
    unused_results,
    variant_size_differences,
    warnings,
    renamed_and_removed_lints
)]

//! # cargo-make
//!
//! Rust task runner and build tool.

//! The cargo-make task runner enables to define and configure sets of tasks and run them as a flow.

//! A task is a command or a script to execute.

//! Tasks can have dependencies which are also tasks that will be executed before the task itself.

//! With a simple toml based configuration file, you can define a multi platform build script that can run build, test,
//! documentation generation, bench tests execution, security validations and more by running a single command.
//!
//! ## Installation
//! In order to install, just run the following command
//!
//! ```sh
//! cargo install cargo-make
//! ```
//!
//! This will install cargo-make in your ~/.cargo/bin.

//! Make sure to add ~/.cargo/bin directory to your PATH variable.
//!
//! # Contributing
//! See [contributing guide](https://github.com/sagiegurari/cargo-make/blob/master/.github/CONTRIBUTING.md)
//!
//! # License
//! Developed by Sagie Gur-Ari and licensed under the
//! [Apache 2](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) open source license.
//!

#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;

#[cfg(test)]
mod test;

// make types public for docs
pub mod types;

mod cache;
mod cli;
mod cli_commands;
mod command;
mod condition;
mod config;
mod descriptor;
mod environment;
mod execution_plan;
mod functions;
mod installer;
mod io;
mod legacy;
mod logger;
mod profile;
mod recursion_level;
mod runner;
mod scriptengine;
mod storage;
mod toolchain;
mod version;

/// Handles the command line arguments and executes the runner.
pub fn run_cli(command_name: String, sub_command: bool) {
    cli::run_cli(command_name, sub_command)
}
<commit_msg>lint updates<commit_after>#![deny(
    absolute_paths_not_starting_with_crate,
    ambiguous_associated_items,
    anonymous_parameters,
    arithmetic_overflow,
    array_into_iter,
    bindings_with_variant_name,
    coherence_leak_check,
    conflicting_repr_hints,
    const_err,
    dead_code,
    deprecated,
    deprecated_in_future,
    ellipsis_inclusive_range_patterns,
    explicit_outlives_requirements,
    exported_private_dependencies,
    ill_formed_attribute_input,
    illegal_floating_point_literal_pattern,
    improper_ctypes,
    incomplete_features,
    indirect_structural_match,
    inline_no_sanitize,
    invalid_codeblock_attribute,
    invalid_type_param_default,
    invalid_value,
    irrefutable_let_patterns,
    keyword_idents,
    late_bound_lifetime_arguments,
    macro_expanded_macro_exports_accessed_by_absolute_paths,
    meta_variable_misuse,
    missing_copy_implementations,
    missing_crate_level_docs,
    missing_docs,
    missing_fragment_specifier,
    mutable_borrow_reservation_conflict,
    mutable_transmutes,
    no_mangle_const_items,
    no_mangle_generic_items,
    non_ascii_idents,
    non_camel_case_types,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    order_dependent_trait_objects,
    overflowing_literals,
    overlapping_patterns,
    path_statements,
    patterns_in_fns_without_body,
    private_doc_tests,
    private_in_public,
    proc_macro_derive_resolution_fallback,
    pub_use_of_private_extern_crate,
    redundant_semicolons,
    safe_packed_borrows,
    soft_unstable,
    stable_features,
    trivial_bounds,
    trivial_casts,
    trivial_numeric_casts,
    type_alias_bounds,
    tyvar_behind_raw_pointer,
    uncommon_codepoints,
    unconditional_panic,
    unconditional_recursion,
    unknown_crate_types,
    unnameable_test_items,
    unreachable_code,
    unreachable_patterns,
    unreachable_pub,
    unsafe_code,
    unstable_features,
    unstable_name_collisions,
    unused_allocation,
    unused_assignments,
    unused_attributes,
    unused_braces,
    unused_comparisons,
    unused_doc_comments,
    unused_extern_crates,
    unused_features,
    unused_import_braces,
    unused_imports,
    unused_labels,
    unused_lifetimes,
    unused_macros,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_unsafe,
    unused_variables,
    where_clauses_object_safety,
    while_true
)]
#![warn(macro_use_extern_crate, unknown_lints)]
#![allow(
    bare_trait_objects,
    box_pointers,
    elided_lifetimes_in_paths,
    intra_doc_link_resolution_failure,
    missing_doc_code_examples,
    missing_debug_implementations,
    single_use_lifetimes,
    unused_results,
    variant_size_differences,
    warnings,
    renamed_and_removed_lints
)]

//! # cargo-make
//!
//! Rust task runner and build tool.

//! The cargo-make task runner enables to define and configure sets of tasks and run them as a flow.

//! A task is a command or a script to execute.

//! Tasks can have dependencies which are also tasks that will be executed before the task itself.

//! With a simple toml based configuration file, you can define a multi platform build script that can run build, test,
//! documentation generation, bench tests execution, security validations and more by running a single command.
//!
//! ## Installation
//! In order to install, just run the following command
//!
//! ```sh
//! cargo install cargo-make
//! ```
//!
//! This will install cargo-make in your ~/.cargo/bin.

//! Make sure to add ~/.cargo/bin directory to your PATH variable.
//!
//! # Contributing
//! See [contributing guide](https://github.com/sagiegurari/cargo-make/blob/master/.github/CONTRIBUTING.md)
//!
//! # License
//! Developed by Sagie Gur-Ari and licensed under the
//! [Apache 2](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) open source license.
//!

#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;

#[cfg(test)]
mod test;

// make types public for docs
pub mod types;

mod cache;
mod cli;
mod cli_commands;
mod command;
mod condition;
mod config;
mod descriptor;
mod environment;
mod execution_plan;
mod functions;
mod installer;
mod io;
mod legacy;
mod logger;
mod profile;
mod recursion_level;
mod runner;
mod scriptengine;
mod storage;
mod toolchain;
mod version;

/// Handles the command line arguments and executes the runner.
pub fn run_cli(command_name: String, sub_command: bool) {
    cli::run_cli(command_name, sub_command)
}
<|endoftext|>


<commit_before>/*!

This crate provides the `error_type!` macro, which is designed to produce a fresh, reasonably well-featured error type from a concise definition.

A simple example of the usage is given below:

```rust
#[macro_use] extern crate error_type;

use std::borrow::Cow;
use std::error::Error;
use std::io;

error_type! {
    #[derive(Debug)]
    pub enum LibError {
        Io(std::io::Error) {
            cause;
        },
        Message(Cow<'static, str>) {
            desc (e) &**e;
            from (s: &'static str) s.into();
            from (s: String) s.into();
        },
        Other(Box<Error>) {
            desc (e) e.description();
            cause (e) Some(&**e);
        }
    }
}
# fn main() {}
```

The expansion of the above includes the following:

- The `LibError` enumeration (plus the provided `#[derive(Debug)]` annotation), with `Io`, `Message` and `Other` variants.

- An implicit `impl From<Payload> for LibError` for each variant's payload type.

- An implicit `impl Display for LibError`, using the existing `Display` implementation for each variant's payload type.

- An implicit `impl Error for LibError`.

- For the `Io` variant:

  - An implicit `description`, forwarded to the existing definition for `std::io::Error`.

  - An automatic `cause`, forwarded to the existing definition for `std::io::Error`.

    **Note**: the automatic `cause` returns the result of `std::io::Error::cause`, *not* the payload itself.  This macro considers the payload to *be* the error, not the underlying cause.

- For the `Message` variant:

  - An explicit `description`, which just returns the contents of the `Cow<'static, str>`.

  - An implicit `cause`, which just returns `None`.

  - An explicit `From<&'static str>` conversion.

  - An explicit `From<String>` conversion.

- For the `Other` variant:

  - An explicit `description` which forwards to the existing definition for the boxed `Error`.

  - An explicit `cause` which returns the boxed error *itself* as the cause.  This is distinct from the behaviour of an *automatic* `cause`.

## FAQ

* *Can I use unitary variants; ones without a payload?*

  No, not as yet.  Maybe if there's demand.

* *Can I use tuple variants with more than one element?*

  No.  This would likely be rather inconvenient to implement, due to the way the various parts of the implementation are constructed.  Not impossible, though.

* *Can I use struct variants?*

  No, for much the same reason as tuple variants.

* *Can I have fields common to all variants; i.e. have the enum wrapped in a struct?*

  No.  It would be nice, but I'm not sure how to go about that.  You can always use the expansion of `error_type!` in a custom structure for the added information.

*/

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_as_item {
    ($i:item) => {$i};
}

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_var_body_emit {
    /*
    Nothing left.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident
    ) => {
        // Done.
    };

    /*
    desc () clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        desc ()
        $($tail:tt)*
    ) => {
        impl<'a> $ed_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_desc(&self) -> &'a str {
                std::error::Error::description(self.1)
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    desc ((arg) expr) clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        desc (($desc_arg:ident) $desc_expr:expr)
        $($tail:tt)*
    ) => {
        impl<'a> $ed_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_desc(&self) -> &'a str {
                let $desc_arg = self.1;
                $desc_expr
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    cause () clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        cause ()
        $($tail:tt)*
    ) => {
        impl<'a> $ec_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_cause(&self) -> Option<&'a std::error::Error> {
                None
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    cause ((arg) expr) clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        cause (($cl_arg:ident) $cl_expr:expr)
        $($tail:tt)*
    ) => {
        impl<'a> $ec_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_cause(&self) -> Option<&'a std::error::Error> {
                let $cl_arg = self.1;
                $cl_expr
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    from ((arg: ty) expr) clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        from ($(($cl_arg:ident: $cl_ty:ty) $cl_expr:expr);*)
        $($tail:tt)*
    ) => {
        $(
            impl From<$cl_ty> for $err_name {
                fn from($cl_arg: $cl_ty) -> $err_name {
                    $err_name::$var_name($cl_expr)
                }
            }
        )*

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_var_body {
    /*
    Base case: no more clauses.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {}
    ) => {
        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            desc $desc, cause $cause, from $from
        }
    };

    /*
    desc (arg) expr;
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {
            desc ($cl_arg:ident) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            (($cl_arg) $cl_body), $cause, $from;
            {$($tail)*}
        }
    };

    /*
    cause (arg) expr;
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {
            cause ($cl_arg:ident) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, (($cl_arg) $cl_body), $from;
            {$($tail)*}
        }
    };

    /*
    cause;
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {
            cause;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, ((e) std::error::Error::cause(e)), $from;
            {$($tail)*}
        }
    };

    /*
    from (arg: Ty) expr; (first)
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, (); {
            from ($cl_arg:ident: $cl_ty:ty) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, $cause, (($cl_arg: $cl_ty) $cl_body);
            {$($tail)*}
        }
    };

    /*
    from (arg: Ty) expr; (not first)
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, ($($from:tt)*); {
            from ($cl_arg:ident: $cl_ty:ty) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, $cause, (($cl_arg: $cl_ty) $cl_body; $($from)*);
            {$($tail)*}
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_impl {
    (
        $(#[$($derive_tts:tt)*])*
        enum $err_name:ident {
            $($var_name:ident($var_ty:ty) $var_body:tt),+
            $(,)*
        }
    ) => {
        $(
            impl From<$var_ty> for $err_name {
                fn from(value: $var_ty) -> $err_name {
                    $err_name::$var_name(value)
                }
            }
        )+

        impl std::fmt::Display for $err_name {
            fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
                match *self {
                    $(
                        $err_name::$var_name(ref v) => std::fmt::Display::fmt(v, fmt)
                    ),+
                }
            }
        }

        pub trait ErrorDescription<'a> {
            fn error_desc(&self) -> &'a str;
        }

        pub trait ErrorCause<'a> {
            fn error_cause(&self) -> Option<&'a std::error::Error>;
        }

        impl std::error::Error for $err_name {
            fn description(&self) -> &str {
                use ErrorDescription;
                match *self {
                    $(
                        $err_name::$var_name(ref v) => (self, v).error_desc()
                    ),+
                }
            }

            fn cause(&self) -> Option<&std::error::Error> {
                use ErrorCause;
                match *self {
                    $(
                        $err_name::$var_name(ref v) => (self, v).error_cause()
                    ),+
                }
            }
        }

        $(
            error_type_var_body! {
                $err_name, $var_name, $var_ty,
                ErrorDescription, ErrorCause,
                (), (), ();
                $var_body
            }
        )+
    };
}

/**
Constructs a reasonably well-featured error type from a concise description.

For details, see the crate documentation.
*/
#[macro_export]
macro_rules! error_type {
    (
        $(#[$($derive_tts:tt)*])*
        pub enum $err_name:ident {
            $($var_name:ident($var_ty:ty) $var_body:tt),+
            $(,)*
        }
    ) => {
        error_type_as_item! {
            $(#[$($derive_tts)*])*
            pub enum $err_name {
                $($var_name($var_ty)),+
            }
        }

        error_type_impl! {
            $(#[$($derive_tts)*])*
            enum $err_name {
                $($var_name($var_ty) $var_body),+
            }
        }
    };

    (
        $(#[$($derive_tts:tt)*])*
        enum $err_name:ident {
            $($var_name:ident($var_ty:ty) $var_body:tt),+
            $(,)*
        }
    ) => {
        error_type_as_item! {
            $(#[$($derive_tts)*])*
            enum $err_name {
                $($var_name($var_ty)),+
            }
        }

        error_type_impl! {
            $(#[$($derive_tts)*])*
            enum $err_name {
                $($var_name($var_ty) $var_body),+
            }
        }
    };

    (
        $(#[$($derive_tts:tt)*])*
        pub enum $err_name:ident {
            $($body_tts:tt)*
        }

        $($tail:tt)*
    ) => {
        error_type_impl! {
            $(#[$($derive_tts)*])*
            (pub) enum $err_name {
                $($body_tts)*
            }
        }

        error_type! { $($tail)* }
    };
}
<commit_msg>Removed old "doc-friendly" macro body which... how did it...?<commit_after>/*!

This crate provides the `error_type!` macro, which is designed to produce a fresh, reasonably well-featured error type from a concise definition.

A simple example of the usage is given below:

```rust
#[macro_use] extern crate error_type;

use std::borrow::Cow;
use std::error::Error;
use std::io;

error_type! {
    #[derive(Debug)]
    pub enum LibError {
        Io(std::io::Error) {
            cause;
        },
        Message(Cow<'static, str>) {
            desc (e) &**e;
            from (s: &'static str) s.into();
            from (s: String) s.into();
        },
        Other(Box<Error>) {
            desc (e) e.description();
            cause (e) Some(&**e);
        }
    }
}
# fn main() {}
```

The expansion of the above includes the following:

- The `LibError` enumeration (plus the provided `#[derive(Debug)]` annotation), with `Io`, `Message` and `Other` variants.

- An implicit `impl From<Payload> for LibError` for each variant's payload type.

- An implicit `impl Display for LibError`, using the existing `Display` implementation for each variant's payload type.

- An implicit `impl Error for LibError`.

- For the `Io` variant:

  - An implicit `description`, forwarded to the existing definition for `std::io::Error`.

  - An automatic `cause`, forwarded to the existing definition for `std::io::Error`.

    **Note**: the automatic `cause` returns the result of `std::io::Error::cause`, *not* the payload itself.  This macro considers the payload to *be* the error, not the underlying cause.

- For the `Message` variant:

  - An explicit `description`, which just returns the contents of the `Cow<'static, str>`.

  - An implicit `cause`, which just returns `None`.

  - An explicit `From<&'static str>` conversion.

  - An explicit `From<String>` conversion.

- For the `Other` variant:

  - An explicit `description` which forwards to the existing definition for the boxed `Error`.

  - An explicit `cause` which returns the boxed error *itself* as the cause.  This is distinct from the behaviour of an *automatic* `cause`.

## FAQ

* *Can I use unitary variants; ones without a payload?*

  No, not as yet.  Maybe if there's demand.

* *Can I use tuple variants with more than one element?*

  No.  This would likely be rather inconvenient to implement, due to the way the various parts of the implementation are constructed.  Not impossible, though.

* *Can I use struct variants?*

  No, for much the same reason as tuple variants.

* *Can I have fields common to all variants; i.e. have the enum wrapped in a struct?*

  No.  It would be nice, but I'm not sure how to go about that.  You can always use the expansion of `error_type!` in a custom structure for the added information.

*/

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_as_item {
    ($i:item) => {$i};
}

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_var_body_emit {
    /*
    Nothing left.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident
    ) => {
        // Done.
    };

    /*
    desc () clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        desc ()
        $($tail:tt)*
    ) => {
        impl<'a> $ed_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_desc(&self) -> &'a str {
                std::error::Error::description(self.1)
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    desc ((arg) expr) clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        desc (($desc_arg:ident) $desc_expr:expr)
        $($tail:tt)*
    ) => {
        impl<'a> $ed_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_desc(&self) -> &'a str {
                let $desc_arg = self.1;
                $desc_expr
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    cause () clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        cause ()
        $($tail:tt)*
    ) => {
        impl<'a> $ec_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_cause(&self) -> Option<&'a std::error::Error> {
                None
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    cause ((arg) expr) clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        cause (($cl_arg:ident) $cl_expr:expr)
        $($tail:tt)*
    ) => {
        impl<'a> $ec_tr<'a> for (&'a $err_name, &'a $var_ty) {
            fn error_cause(&self) -> Option<&'a std::error::Error> {
                let $cl_arg = self.1;
                $cl_expr
            }
        }

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };

    /*
    from ((arg: ty) expr) clause.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        from ($(($cl_arg:ident: $cl_ty:ty) $cl_expr:expr);*)
        $($tail:tt)*
    ) => {
        $(
            impl From<$cl_ty> for $err_name {
                fn from($cl_arg: $cl_ty) -> $err_name {
                    $err_name::$var_name($cl_expr)
                }
            }
        )*

        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr $($tail)*
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_var_body {
    /*
    Base case: no more clauses.
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {}
    ) => {
        error_type_var_body_emit! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            desc $desc, cause $cause, from $from
        }
    };

    /*
    desc (arg) expr;
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {
            desc ($cl_arg:ident) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            (($cl_arg) $cl_body), $cause, $from;
            {$($tail)*}
        }
    };

    /*
    cause (arg) expr;
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {
            cause ($cl_arg:ident) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, (($cl_arg) $cl_body), $from;
            {$($tail)*}
        }
    };

    /*
    cause;
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, $from:tt; {
            cause;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, ((e) std::error::Error::cause(e)), $from;
            {$($tail)*}
        }
    };

    /*
    from (arg: Ty) expr; (first)
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, (); {
            from ($cl_arg:ident: $cl_ty:ty) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, $cause, (($cl_arg: $cl_ty) $cl_body);
            {$($tail)*}
        }
    };

    /*
    from (arg: Ty) expr; (not first)
    */
    (
        $err_name:ident, $var_name:ident, $var_ty:ty, $ed_tr:ident, $ec_tr:ident,
        $desc:tt, $cause:tt, ($($from:tt)*); {
            from ($cl_arg:ident: $cl_ty:ty) $cl_body:expr;
            $($tail:tt)*
        }
    ) => {
        error_type_var_body! {
            $err_name, $var_name, $var_ty, $ed_tr, $ec_tr,
            $desc, $cause, (($cl_arg: $cl_ty) $cl_body; $($from)*);
            {$($tail)*}
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! error_type_impl {
    (
        $(#[$($derive_tts:tt)*])*
        enum $err_name:ident {
            $($var_name:ident($var_ty:ty) $var_body:tt),+
            $(,)*
        }
    ) => {
        $(
            impl From<$var_ty> for $err_name {
                fn from(value: $var_ty) -> $err_name {
                    $err_name::$var_name(value)
                }
            }
        )+

        impl std::fmt::Display for $err_name {
            fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
                match *self {
                    $(
                        $err_name::$var_name(ref v) => std::fmt::Display::fmt(v, fmt)
                    ),+
                }
            }
        }

        pub trait ErrorDescription<'a> {
            fn error_desc(&self) -> &'a str;
        }

        pub trait ErrorCause<'a> {
            fn error_cause(&self) -> Option<&'a std::error::Error>;
        }

        impl std::error::Error for $err_name {
            fn description(&self) -> &str {
                use ErrorDescription;
                match *self {
                    $(
                        $err_name::$var_name(ref v) => (self, v).error_desc()
                    ),+
                }
            }

            fn cause(&self) -> Option<&std::error::Error> {
                use ErrorCause;
                match *self {
                    $(
                        $err_name::$var_name(ref v) => (self, v).error_cause()
                    ),+
                }
            }
        }

        $(
            error_type_var_body! {
                $err_name, $var_name, $var_ty,
                ErrorDescription, ErrorCause,
                (), (), ();
                $var_body
            }
        )+
    };
}

/**
Constructs a reasonably well-featured error type from a concise description.

For details, see the crate documentation.
*/
#[macro_export]
macro_rules! error_type {
    (
        $(#[$($derive_tts:tt)*])*
        pub enum $err_name:ident {
            $($var_name:ident($var_ty:ty) $var_body:tt),+
            $(,)*
        }
    ) => {
        error_type_as_item! {
            $(#[$($derive_tts)*])*
            pub enum $err_name {
                $($var_name($var_ty)),+
            }
        }

        error_type_impl! {
            $(#[$($derive_tts)*])*
            enum $err_name {
                $($var_name($var_ty) $var_body),+
            }
        }
    };

    (
        $(#[$($derive_tts:tt)*])*
        enum $err_name:ident {
            $($var_name:ident($var_ty:ty) $var_body:tt),+
            $(,)*
        }
    ) => {
        error_type_as_item! {
            $(#[$($derive_tts)*])*
            enum $err_name {
                $($var_name($var_ty)),+
            }
        }

        error_type_impl! {
            $(#[$($derive_tts)*])*
            enum $err_name {
                $($var_name($var_ty) $var_body),+
            }
        }
    };
}
<|endoftext|>


<commit_before>//! Provides some common lints for syntax extensions.
#![feature(plugin_registrar)]
#![feature(rustc_private)]

extern crate syntax;
#[macro_use]
extern crate rustc;
extern crate rustc_front;

use rustc_front::hir as ast;
use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
use rustc::plugin;
use std::ops::Deref;

declare_lint!(DUMMY_SPAN,
              Warn,
              "detects uses of DUMMY_SP");

struct Pass;

impl Pass {
    fn new() -> Pass {
        Pass
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(DUMMY_SPAN)
    }

    fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) {
        match expr.node {
            ast::ExprPath(None, ref path) => {
                let name = path.segments.last().unwrap().identifier.name.as_str();
                if name.deref() == "DUMMY_SP" {
                    cx.span_lint(DUMMY_SPAN, expr.span,
                                 "usage of 'DUMMY_SP' is discouraged");
                }
            },
            _ => {},
        }
    }
}

#[plugin_registrar]
pub fn register_plugins(reg: &mut plugin::Registry) {
    reg.register_lint_pass(Box::new(Pass::new()) as LintPassObject);
}
<commit_msg>Nightly fallout (76856e1 and a642d85).<commit_after>//! Provides some common lints for syntax extensions.
#![feature(plugin_registrar)]
#![feature(rustc_private)]

extern crate syntax;
#[macro_use]
extern crate rustc;
extern crate rustc_front;

use syntax::ast as ast;
use rustc::lint::{LintContext, EarlyContext, LintPass, EarlyLintPass, LintArray};
use rustc::plugin;
use std::ops::Deref;

declare_lint!(DUMMY_SPAN,
              Warn,
              "detects uses of DUMMY_SP");

struct Pass;

impl Pass {
    fn new() -> Pass {
        Pass
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(DUMMY_SPAN)
    }
}

impl EarlyLintPass for Pass {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
        match expr.node {
            ast::ExprPath(None, ref path) => {
                let name = path.segments.last().unwrap().identifier.name.as_str();
                if name.deref() == "DUMMY_SP" {
                    cx.span_lint(DUMMY_SPAN, expr.span,
                                 "usage of 'DUMMY_SP' is discouraged");
                }
            },
            _ => {},
        }
    }
}

#[plugin_registrar]
pub fn register_plugins(reg: &mut plugin::Registry) {
    reg.register_early_lint_pass(Box::new(Pass::new()));
}
<|endoftext|>


<commit_before>#![feature(scoped)]

use std::collections::HashMap;
use std::sync::{Arc,Mutex};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::mpsc;
use std::ops::Deref;

#[cfg(test)]
mod test;

struct Subscription{
	pubsub: PubSub,
	channel_id: String,
	receiver: Receiver<String>,
	id: u64
}
impl Subscription{
	pub fn cancel(self){}
}
impl Drop for Subscription{
	fn drop(&mut self){
		self.pubsub.unregister(self);
	}
}
impl Deref for Subscription{
	type Target = Receiver<String>;
	fn deref<'a>(&'a self) -> &'a Receiver<String>{
		&self.receiver
	}
}

struct InnerPubSub{
	channels: HashMap<String, HashMap<u64, Sender<String>>>,

	//id will stay unique for hundreds of years, even at ~1 billion/sec
	next_id: u64
}
#[derive(Clone)]
struct PubSub{
	inner: Arc<Mutex<InnerPubSub>>
}
impl PubSub{
	fn new() -> PubSub{
		PubSub{
			inner: Arc::new(Mutex::new(InnerPubSub{
				channels: HashMap::new(),
				next_id: 0
			}))
		}
	}
	fn subscribe(&self, channel: &str) -> Subscription{
		let mut data = self.inner.lock().unwrap();
		//let mut inner: &mut InnerPubSub = &mut *lock_guard;
		if !data.channels.contains_key(channel){
			data.channels.insert(channel.to_string(), HashMap::new());
		}
		let id = data.next_id;
		data.next_id += 1;
		let (sender, receiver) = mpsc::channel();
		data.channels.get_mut(channel).unwrap().insert(id, sender);
		Subscription{
			pubsub: self.clone(),
			channel_id: channel.to_string(),
			receiver: receiver,
			id: id
		}
	}
	fn num_channels(&self) -> usize{
		let data = self.inner.lock().unwrap();
		data.channels.len()
	}
	fn unregister(&self, sub: &Subscription){
		let mut inner = self.inner.lock().unwrap();
		let mut remove_channel = false;
		{
			let sub_list = inner.channels.get_mut(&sub.channel_id).unwrap();
			sub_list.remove(&sub.id);
			if sub_list.len() == 0{
				remove_channel = true;
			}
		}
		if remove_channel{
			inner.channels.remove(&sub.channel_id);
		}
	}
	pub fn notify(&self, channel: &str, msg: &str){
		if let Some(subscriptions) = self.inner.lock().unwrap().channels.get_mut(channel){
			for (_,sender) in subscriptions{
				let _ = sender.send(msg.to_string());
			}
		}
	}
}
<commit_msg>make methods public<commit_after>#![feature(scoped)]

use std::collections::HashMap;
use std::sync::{Arc,Mutex};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::mpsc;
use std::ops::Deref;

#[cfg(test)]
mod test;

pub struct Subscription{
	pubsub: PubSub,
	channel_id: String,
	receiver: Receiver<String>,
	id: u64
}
impl Subscription{
	pub fn cancel(self){}
}
impl Drop for Subscription{
	fn drop(&mut self){
		self.pubsub.unregister(self);
	}
}
impl Deref for Subscription{
	type Target = Receiver<String>;
	fn deref<'a>(&'a self) -> &'a Receiver<String>{
		&self.receiver
	}
}

struct InnerPubSub{
	channels: HashMap<String, HashMap<u64, Sender<String>>>,

	//id will stay unique for hundreds of years, even at ~1 billion/sec
	next_id: u64
}
#[derive(Clone)]
pub struct PubSub{
	inner: Arc<Mutex<InnerPubSub>>
}
impl PubSub{
	pub fn new() -> PubSub{
		PubSub{
			inner: Arc::new(Mutex::new(InnerPubSub{
				channels: HashMap::new(),
				next_id: 0
			}))
		}
	}
	pub fn subscribe(&self, channel: &str) -> Subscription{
		let mut data = self.inner.lock().unwrap();
		//let mut inner: &mut InnerPubSub = &mut *lock_guard;
		if !data.channels.contains_key(channel){
			data.channels.insert(channel.to_string(), HashMap::new());
		}
		let id = data.next_id;
		data.next_id += 1;
		let (sender, receiver) = mpsc::channel();
		data.channels.get_mut(channel).unwrap().insert(id, sender);
		Subscription{
			pubsub: self.clone(),
			channel_id: channel.to_string(),
			receiver: receiver,
			id: id
		}
	}
	pub fn num_channels(&self) -> usize{
		let data = self.inner.lock().unwrap();
		data.channels.len()
	}
	fn unregister(&self, sub: &Subscription){
		let mut inner = self.inner.lock().unwrap();
		let mut remove_channel = false;
		{
			let sub_list = inner.channels.get_mut(&sub.channel_id).unwrap();
			sub_list.remove(&sub.id);
			if sub_list.len() == 0{
				remove_channel = true;
			}
		}
		if remove_channel{
			inner.channels.remove(&sub.channel_id);
		}
	}
	pub fn notify(&self, channel: &str, msg: &str){
		if let Some(subscriptions) = self.inner.lock().unwrap().channels.get_mut(channel){
			for (_,sender) in subscriptions{
				let _ = sender.send(msg.to_string());
			}
		}
	}
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![crate_type = "lib"]
#[allow(dead_code)]

use std::net::IpAddr;

mod ipv4;
mod ipv6;
mod common;

pub use ipv4::{Ipv4Network, ipv4_mask_to_prefix};
pub use ipv6::{Ipv6Network, ipv6_mask_to_prefix};
pub use common::IpNetworkError;

// A network
#[derive(Debug,Clone,Copy,Hash,PartialEq,Eq)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
        match ip {
            IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
            IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

/// Converts a `IpAddr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
    match mask {
        IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
        IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
    }
}<commit_msg>Add some docs for the top level enum<commit_after>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![crate_type = "lib"]
#[allow(dead_code)]

use std::net::IpAddr;

mod ipv4;
mod ipv6;
mod common;

pub use ipv4::{Ipv4Network, ipv4_mask_to_prefix};
pub use ipv6::{Ipv6Network, ipv6_mask_to_prefix};
pub use common::IpNetworkError;

// A network
#[derive(Debug,Clone,Copy,Hash,PartialEq,Eq)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

impl IpNetwork {
    /// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the
    /// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this
    /// will raise an `IpNetworkError::InvalidPrefix` error. Support for IPv6 is not
    /// complete yet.
    pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
        match ip {
            IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
            IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
        }
    }

    /// Returns the IP part of a given `IpNetwork`
    ///
    /// # Example
    /// ```
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    /// use ipnetwork::IpNetwork;
    ///
    /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).ip(), "10.9.0.32".parse().unwrap());
    /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).ip(), "ff01::0".parse().unwrap());
    /// ```
    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    /// Returns the prefix of the given `IpNetwork`
    ///
    /// # Example
    /// ```
    /// use ipnetwork::IpNetwork;
    ///
    /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8);
    /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
    /// ```
    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

/// Converts a `IpAddr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
    match mask {
        IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
        IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
    }
}
<|endoftext|>


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

extern crate rustc;
extern crate syntax;

use rustc::plugin::registry::Registry;
use syntax::ptr::P;
use syntax::ext::base;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::codemap::Span;
use syntax::ast;
use syntax::ast::Visibility;
use syntax::ast::ItemStatic;
use syntax::ast::Sign::Plus;
use syntax::ast::Mutability::MutImmutable;
use syntax::ast::Lit_::{LitChar, LitInt};
use syntax::ast::Ty_::TyFixedLengthVec;
use syntax::ast::LitIntType::UnsuffixedIntLit;
use syntax::parse::token;

/// Construct a `ast::Ty_::TyPath` corresponding to `path`
fn make_ty_path<'cx>(cx: &'cx mut ExtCtxt, sp: Span, path: Vec<&str>) -> P<ast::Ty> {
    let path = path.iter().map(|p| { cx.ident_of(p) }).collect::<Vec<_>>();
    cx.ty_path(cx.path(sp, path))
}

/// Generate an `ast::Expr` for `'a' as libc::c_char`
fn make_char_cast<'cx>(cx: &'cx mut ExtCtxt, sp: Span, c: char) -> P<ast::Expr> {
    let path = make_ty_path(cx, sp, vec!["libc", "c_char"]);
    cx.expr_cast(sp, cx.expr_lit(sp, LitChar(c)), path)
}

/// Ensure `expr` is a string literal, and return either Some(&str) or None.
fn extract_literal<'cx, 'a>(cx: &'cx mut ExtCtxt, expr: &'a P<ast::Expr>) -> Option<&'a str> {
    if let ast::ExprLit(ref lit) = expr.node {
        if let ast::LitStr(ref s, _) = lit.node {
            Some(s.get())
        } else {
            cx.span_err(expr.span, "expected a string literal");
            None
        }
    } else {
        cx.span_err(expr.span, "expected a string literal");
        None
    }
}

/// Expansion for `declare_static_raw_cstr!`
/// `declare_static_raw_cstr!("foo", "hello")` -> `static foo: [libc::c_char; 6] = ['h' as libc::c_char, ..., 0 as libc::c_char];`
fn expand_declare_static_raw_cstr<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                     -> Box<base::MacResult + 'cx> {
    let exprs = match base::get_exprs_from_tts(cx, sp, tts) {
        Some(e) => e,
        None => return base::DummyResult::expr(sp)
    };

    let mut it = exprs.iter();
    let e_name = if let Some(expr) = it.next() {
        extract_literal(cx, expr)
    } else {
        cx.span_err(sp, "expected 2 arguments, found 0");
        None
    };
    let e_lit = if let Some(expr) = it.next() {
        extract_literal(cx, expr)
    } else {
        cx.span_err(sp, "expected 2 arguments, found 1");
        None
    };

    match (e_name, e_lit, it.count()) {
        // name, literal, and no other arguments remaining
        (Some(name), Some(s), 0) => {
            // append null terminator to make it a cstring
            let lit = format!("{}\0", s);

            // build RHS of the statement
            let rhs = lit.as_slice().chars().map(|c| { make_char_cast(cx, sp, c) }).collect::<Vec<_>>();
            let rhs = cx.expr_vec(sp, rhs);

            // the type of the item is a fixed length vector of libc::c_char
            let path = make_ty_path(cx, sp, vec!["libc", "c_char"]);
            let ty = cx.ty(sp, TyFixedLengthVec(path, cx.expr_lit(sp, LitInt(lit.len() as u64, UnsuffixedIntLit(Plus)))));

            // make the actual item
            let attrs = vec![cx.attribute(sp, cx.meta_word(sp, token::intern_and_get_ident("no_mangle")))];

            // XXX: have to manually construct the item here because we can't set the visibility otherwise.
            let item = P(ast::Item {
              ident: cx.ident_of(name),
              attrs: attrs,
              id: ast::DUMMY_NODE_ID,
              node: ast::ItemStatic(ty, MutImmutable, rhs),
              vis: Visibility::Public,
              span: sp
            });
            base::MacItems::new(vec![item].into_iter())
        }
        (_, _, rest) => {
            if rest > 0 {
                cx.span_err(sp, format!("expected 2 arguments, found {}", rest + 2).as_slice());
            }
            base::DummyResult::expr(sp)
        }
    }
}

/// Declare a `pub static [libc::c_char; N]`, where N is the length of the supplied string, plus 1.
/// The resulting item is a raw, null-terminated C string that becomes exported as an unmangled
/// symbol for use in dynamic libraries.
///
/// `export_cstr!(foo, "hello")` expands to `#[no_mangle] pub static foo: [libc::c_char; 6] = ['h' as libc::c_char, ..., 0 as libc::c_char];`
#[macro_export]
macro_rules! export_cstr {
    ($name:ident, $lit:expr) => (
        declare_static_raw_cstr!(stringify!($name), $lit);
    );
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("declare_static_raw_cstr", expand_declare_static_raw_cstr);
}

<commit_msg>Generate #[allow(dead_code, non_upper_case_globals)] attribute<commit_after>#![feature(core, rustc_private, plugin_registrar)]

extern crate rustc;
extern crate syntax;

use rustc::plugin::registry::Registry;
use syntax::ptr::P;
use syntax::ext::base;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::codemap::Span;
use syntax::ast;
use syntax::ast::Visibility;
use syntax::ast::ItemStatic;
use syntax::ast::Sign::Plus;
use syntax::ast::Mutability::MutImmutable;
use syntax::ast::Lit_::{LitChar, LitInt, LitStr};
use syntax::ast::Ty_::TyFixedLengthVec;
use syntax::ast::LitIntType::UnsuffixedIntLit;
use syntax::parse::token;

/// Construct a `ast::Ty_::TyPath` corresponding to `path`
fn make_ty_path<'cx>(cx: &'cx mut ExtCtxt, sp: Span, path: Vec<&str>) -> P<ast::Ty> {
    let path = path.iter().map(|p| { cx.ident_of(p) }).collect::<Vec<_>>();
    cx.ty_path(cx.path(sp, path))
}

/// Generate an `ast::Expr` for `'a' as libc::c_char`
fn make_char_cast<'cx>(cx: &'cx mut ExtCtxt, sp: Span, c: char) -> P<ast::Expr> {
    let path = make_ty_path(cx, sp, vec!["libc", "c_char"]);
    cx.expr_cast(sp, cx.expr_lit(sp, LitChar(c)), path)
}

/// Ensure `expr` is a string literal, and return either Some(&str) or None.
fn extract_literal<'cx, 'a>(cx: &'cx mut ExtCtxt, expr: &'a P<ast::Expr>) -> Option<&'a str> {
    if let ast::ExprLit(ref lit) = expr.node {
        if let ast::LitStr(ref s, _) = lit.node {
            Some(s.get())
        } else {
            cx.span_err(expr.span, "expected a string literal");
            None
        }
    } else {
        cx.span_err(expr.span, "expected a string literal");
        None
    }
}

/// Expansion for `declare_static_raw_cstr!`
/// `declare_static_raw_cstr!("foo", "hello")` -> `static foo: [libc::c_char; 6] = ['h' as libc::c_char, ..., 0 as libc::c_char];`
fn expand_declare_static_raw_cstr<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                     -> Box<base::MacResult + 'cx> {
    let exprs = match base::get_exprs_from_tts(cx, sp, tts) {
        Some(e) => e,
        None => return base::DummyResult::expr(sp)
    };

    let mut it = exprs.iter();
    let e_name = if let Some(expr) = it.next() {
        extract_literal(cx, expr)
    } else {
        cx.span_err(sp, "expected 2 arguments, found 0");
        None
    };
    let e_lit = if let Some(expr) = it.next() {
        extract_literal(cx, expr)
    } else {
        cx.span_err(sp, "expected 2 arguments, found 1");
        None
    };

    match (e_name, e_lit, it.count()) {
        // name, literal, and no other arguments remaining
        (Some(name), Some(s), 0) => {
            // append null terminator to make it a cstring
            let lit = format!("{}\0", s);

            // build RHS of the statement
            let rhs = lit.as_slice().chars().map(|c| { make_char_cast(cx, sp, c) }).collect::<Vec<_>>();
            let rhs = cx.expr_vec(sp, rhs);

            // the type of the item is a fixed length vector of libc::c_char
            let path = make_ty_path(cx, sp, vec!["libc", "c_char"]);
            let ty = cx.ty(sp, TyFixedLengthVec(path, cx.expr_lit(sp, LitInt(lit.len() as u64, UnsuffixedIntLit(Plus)))));

            // #[no_mangle] #[allow(dead_code, non_upper_case_globals)]
            let attrs = vec![
                cx.attribute(sp, cx.meta_word(sp, token::intern_and_get_ident("no_mangle"))),
                cx.attribute(sp,
                    cx.meta_list(sp,
                        token::intern_and_get_ident("allow"),
                        vec![
                            cx.meta_word(sp, token::intern_and_get_ident("dead_code")),
                            cx.meta_word(sp, token::intern_and_get_ident("non_upper_case_globals"))
                        ]))
            ];

            // XXX: have to manually construct the item here because we can't set the visibility otherwise.
            let item = P(ast::Item {
                ident: cx.ident_of(name),
                attrs: attrs,
                id: ast::DUMMY_NODE_ID,
                node: ast::ItemStatic(ty, MutImmutable, rhs),
                vis: Visibility::Public,
                span: sp
            });
            base::MacItems::new(vec![item].into_iter())
        }
        (_, _, rest) => {
            if rest > 0 {
                cx.span_err(sp, format!("expected 2 arguments, found {}", rest + 2).as_slice());
            }
            base::DummyResult::expr(sp)
        }
    }
}

/// Declare a `pub static [libc::c_char; N]`, where N is the length of the supplied string, plus 1.
/// The resulting item is a raw, null-terminated C string that becomes exported as an unmangled
/// symbol for use in dynamic libraries.
///
/// `export_cstr!(foo, "hello")` expands to `#[no_mangle] pub static foo: [libc::c_char; 6] = ['h' as libc::c_char, ..., 0 as libc::c_char];`
#[macro_export]
macro_rules! export_cstr {
    ($name:ident, $lit:expr) => (
        declare_static_raw_cstr!(stringify!($name), $lit);
    );
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("declare_static_raw_cstr", expand_declare_static_raw_cstr);
}

<|endoftext|>