<commit_before>//! The HTTP module which provides functions for performing requests to
//! endpoints in Discord's API.
//!
//! An important function of the REST API is ratelimiting. Requests to endpoints
//! are ratelimited to prevent spam, and once ratelimited Discord will stop
//! performing requests. The library implements protection to pre-emptively
//! ratelimit, to ensure that no wasted requests are made.
//!
//! The HTTP module comprises of two types of requests:
//!
//! - REST API requests, which require an authorization token;
//! - Other requests, which do not require an authorization token.
//!
//! The former require a [`Client`] to have logged in, while the latter may be
//! made regardless of any other usage of the library.
//!
//! If a request spuriously fails, it will be retried once.
//!
//! Note that you may want to perform requests through a [model]s'
//! instance methods where possible, as they each offer different
//! levels of a high-level interface to the HTTP module.
//!
//! [`Client`]: ../client/struct.Client.html
//! [model]: ../model/index.html

pub mod ratelimiting;
pub mod raw;
pub mod request;
pub mod routing;

mod error;

pub use reqwest::StatusCode;
pub use self::error::Error as HttpError;
pub use self::raw::*;

use reqwest::{
    Method,
};
use crate::model::prelude::*;
use self::{request::Request};
use std::{
    fs::File,
    path::{Path, PathBuf},
};

#[cfg(feature = "cache")]
use crate::cache::CacheRwLock;
#[cfg(feature = "client")]
use crate::client::Context;

/// This trait will be required by functions that need [`Http`] and can
/// optionally use a [`CacheRwLock`] to potentially avoid REST-requests.
///
/// The types [`Context`], [`CacheRwLock`], and [`Http`] implement this trait
/// and thus passing these to functions expecting `impl CacheHttp` is possible.
///
/// In a situation where you have the `cache`-feature enabled but you do not
/// pass a cache, the function will behave as if no `cache`-feature is active.
///
/// If you are calling a function that expects `impl CacheHttp` as argument
/// and you wish to utilise the `cache`-feature but you got no access to a
/// [`Context`], you can pass a tuple of `(CacheRwLock, Http)`.
///
/// [`CacheRwLock`]: ../cache/struct.CacheRwLock.html
/// [`Http`]: raw/struct.Http.html
/// [`Context`]: ../client/struct.Context.html
pub trait CacheHttp {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http;
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { None }
}

#[cfg(feature = "client")]
impl CacheHttp for Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(feature = "client")]
impl CacheHttp for &Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(feature = "client")]
impl CacheHttp for &mut Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(feature = "client")]
impl CacheHttp for &&mut Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(all(feature = "cache", feature = "http"))]
impl CacheHttp for (&CacheRwLock, &Http) {
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.0) }
    fn http(&self) -> &Http { &self.1 }
}

impl CacheHttp for &Http {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { *self }
}

#[cfg(all(feature = "cache", feature = "http"))]
impl AsRef<CacheRwLock> for (&CacheRwLock, &Http) {
    fn as_ref(&self) -> &CacheRwLock {
        self.0
    }
}

#[cfg(feature = "cache")]
impl AsRef<Http> for (&CacheRwLock, &Http) {
    fn as_ref(&self) -> &Http {
        self.1
    }
}

/// An method used for ratelimiting special routes.
///
/// This is needed because `reqwest`'s `Method` enum does not derive Copy.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum LightMethod {
    /// Indicates that a route is for the `DELETE` method only.
    Delete,
    /// Indicates that a route is for the `GET` method only.
    Get,
    /// Indicates that a route is for the `PATCH` method only.
    Patch,
    /// Indicates that a route is for the `POST` method only.
    Post,
    /// Indicates that a route is for the `PUT` method only.
    Put,
}

impl LightMethod {
    pub fn reqwest_method(self) -> Method {
        match self {
            LightMethod::Delete => Method::DELETE,
            LightMethod::Get => Method::GET,
            LightMethod::Patch => Method::PATCH,
            LightMethod::Post => Method::POST,
            LightMethod::Put => Method::PUT,
        }
    }
}

/// Enum that allows a user to pass a `Path` or a `File` type to `send_files`
#[derive(Clone, Debug)]
pub enum AttachmentType<'a> {
    /// Indicates that the `AttachmentType` is a byte slice with a filename.
    Bytes((&'a [u8], &'a str)),
    /// Indicates that the `AttachmentType` is a `File`
    File((&'a File, &'a str)),
    /// Indicates that the `AttachmentType` is a `Path`
    Path(&'a Path),
    #[doc(hidden)]
    __Nonexhaustive,
}

impl<'a> From<(&'a [u8], &'a str)> for AttachmentType<'a> {
    fn from(params: (&'a [u8], &'a str)) -> AttachmentType<'_> { AttachmentType::Bytes(params) }
}

impl<'a> From<&'a str> for AttachmentType<'a> {
    fn from(s: &'a str) -> AttachmentType<'_> { AttachmentType::Path(Path::new(s)) }
}

impl<'a> From<&'a Path> for AttachmentType<'a> {
    fn from(path: &'a Path) -> AttachmentType<'_> {
        AttachmentType::Path(path)
    }
}

impl<'a> From<&'a PathBuf> for AttachmentType<'a> {
    fn from(pathbuf: &'a PathBuf) -> AttachmentType<'_> { AttachmentType::Path(pathbuf.as_path()) }
}

impl<'a> From<(&'a File, &'a str)> for AttachmentType<'a> {
    fn from(f: (&'a File, &'a str)) -> AttachmentType<'a> { AttachmentType::File((f.0, f.1)) }
}

/// Representation of the method of a query to send for the [`get_guilds`]
/// function.
///
/// [`get_guilds`]: fn.get_guilds.html
pub enum GuildPagination {
    /// The Id to get the guilds after.
    After(GuildId),
    /// The Id to get the guilds before.
    Before(GuildId),
    #[doc(hidden)]
    __Nonexhaustive,
}

#[cfg(test)]
mod test {
    use super::AttachmentType;
    use std::path::Path;

    #[test]
    fn test_attachment_type() {
        assert!(match AttachmentType::from(Path::new("./dogs/corgis/kona.png")) {
            AttachmentType::Path(_) => true,
            _ => false,
        });
        assert!(match AttachmentType::from("./cats/copycat.png") {
            AttachmentType::Path(_) => true,
            _ => false,
        });
    }
}
<commit_msg>Implement `CacheHttp` for `Arc<Http>` (#657)<commit_after>//! The HTTP module which provides functions for performing requests to
//! endpoints in Discord's API.
//!
//! An important function of the REST API is ratelimiting. Requests to endpoints
//! are ratelimited to prevent spam, and once ratelimited Discord will stop
//! performing requests. The library implements protection to pre-emptively
//! ratelimit, to ensure that no wasted requests are made.
//!
//! The HTTP module comprises of two types of requests:
//!
//! - REST API requests, which require an authorization token;
//! - Other requests, which do not require an authorization token.
//!
//! The former require a [`Client`] to have logged in, while the latter may be
//! made regardless of any other usage of the library.
//!
//! If a request spuriously fails, it will be retried once.
//!
//! Note that you may want to perform requests through a [model]s'
//! instance methods where possible, as they each offer different
//! levels of a high-level interface to the HTTP module.
//!
//! [`Client`]: ../client/struct.Client.html
//! [model]: ../model/index.html

pub mod ratelimiting;
pub mod raw;
pub mod request;
pub mod routing;

mod error;

pub use reqwest::StatusCode;
pub use self::error::Error as HttpError;
pub use self::raw::*;

use reqwest::{
    Method,
};
use crate::model::prelude::*;
use self::{request::Request};
use std::{
    fs::File,
    sync::Arc,
    path::{Path, PathBuf},
};

#[cfg(feature = "cache")]
use crate::cache::CacheRwLock;
#[cfg(feature = "client")]
use crate::client::Context;

/// This trait will be required by functions that need [`Http`] and can
/// optionally use a [`CacheRwLock`] to potentially avoid REST-requests.
///
/// The types [`Context`], [`CacheRwLock`], and [`Http`] implement this trait
/// and thus passing these to functions expecting `impl CacheHttp` is possible.
///
/// In a situation where you have the `cache`-feature enabled but you do not
/// pass a cache, the function will behave as if no `cache`-feature is active.
///
/// If you are calling a function that expects `impl CacheHttp` as argument
/// and you wish to utilise the `cache`-feature but you got no access to a
/// [`Context`], you can pass a tuple of `(CacheRwLock, Http)`.
///
/// [`CacheRwLock`]: ../cache/struct.CacheRwLock.html
/// [`Http`]: raw/struct.Http.html
/// [`Context`]: ../client/struct.Context.html
pub trait CacheHttp {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http;
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { None }
}

#[cfg(feature = "client")]
impl CacheHttp for Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(feature = "client")]
impl CacheHttp for &Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(feature = "client")]
impl CacheHttp for &mut Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(feature = "client")]
impl CacheHttp for &&mut Context {
    #[cfg(feature = "http")]
    fn http(&self) -> &Http { &self.http }
    #[cfg(feature = "cache")]
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.cache) }
}

#[cfg(all(feature = "cache", feature = "http"))]
impl CacheHttp for (&CacheRwLock, &Http) {
    fn cache(&self) -> Option<&CacheRwLock> { Some(&self.0) }
    fn http(&self) -> &Http { &self.1 }
}

#[cfg(feature = "http")]
impl CacheHttp for &Http {
    fn http(&self) -> &Http { *self }
}

#[cfg(feature = "http")]
impl CacheHttp for Arc<Http> {
    fn http(&self) -> &Http { &*self }
}

#[cfg(all(feature = "cache", feature = "http"))]
impl AsRef<CacheRwLock> for (&CacheRwLock, &Http) {
    fn as_ref(&self) -> &CacheRwLock {
        self.0
    }
}

#[cfg(feature = "cache")]
impl AsRef<Http> for (&CacheRwLock, &Http) {
    fn as_ref(&self) -> &Http {
        self.1
    }
}

/// An method used for ratelimiting special routes.
///
/// This is needed because `reqwest`'s `Method` enum does not derive Copy.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum LightMethod {
    /// Indicates that a route is for the `DELETE` method only.
    Delete,
    /// Indicates that a route is for the `GET` method only.
    Get,
    /// Indicates that a route is for the `PATCH` method only.
    Patch,
    /// Indicates that a route is for the `POST` method only.
    Post,
    /// Indicates that a route is for the `PUT` method only.
    Put,
}

impl LightMethod {
    pub fn reqwest_method(self) -> Method {
        match self {
            LightMethod::Delete => Method::DELETE,
            LightMethod::Get => Method::GET,
            LightMethod::Patch => Method::PATCH,
            LightMethod::Post => Method::POST,
            LightMethod::Put => Method::PUT,
        }
    }
}

/// Enum that allows a user to pass a `Path` or a `File` type to `send_files`
#[derive(Clone, Debug)]
pub enum AttachmentType<'a> {
    /// Indicates that the `AttachmentType` is a byte slice with a filename.
    Bytes((&'a [u8], &'a str)),
    /// Indicates that the `AttachmentType` is a `File`
    File((&'a File, &'a str)),
    /// Indicates that the `AttachmentType` is a `Path`
    Path(&'a Path),
    #[doc(hidden)]
    __Nonexhaustive,
}

impl<'a> From<(&'a [u8], &'a str)> for AttachmentType<'a> {
    fn from(params: (&'a [u8], &'a str)) -> AttachmentType<'_> { AttachmentType::Bytes(params) }
}

impl<'a> From<&'a str> for AttachmentType<'a> {
    fn from(s: &'a str) -> AttachmentType<'_> { AttachmentType::Path(Path::new(s)) }
}

impl<'a> From<&'a Path> for AttachmentType<'a> {
    fn from(path: &'a Path) -> AttachmentType<'_> {
        AttachmentType::Path(path)
    }
}

impl<'a> From<&'a PathBuf> for AttachmentType<'a> {
    fn from(pathbuf: &'a PathBuf) -> AttachmentType<'_> { AttachmentType::Path(pathbuf.as_path()) }
}

impl<'a> From<(&'a File, &'a str)> for AttachmentType<'a> {
    fn from(f: (&'a File, &'a str)) -> AttachmentType<'a> { AttachmentType::File((f.0, f.1)) }
}

/// Representation of the method of a query to send for the [`get_guilds`]
/// function.
///
/// [`get_guilds`]: fn.get_guilds.html
pub enum GuildPagination {
    /// The Id to get the guilds after.
    After(GuildId),
    /// The Id to get the guilds before.
    Before(GuildId),
    #[doc(hidden)]
    __Nonexhaustive,
}

#[cfg(test)]
mod test {
    use super::AttachmentType;
    use std::path::Path;

    #[test]
    fn test_attachment_type() {
        assert!(match AttachmentType::from(Path::new("./dogs/corgis/kona.png")) {
            AttachmentType::Path(_) => true,
            _ => false,
        });
        assert!(match AttachmentType::from("./cats/copycat.png") {
            AttachmentType::Path(_) => true,
            _ => false,
        });
    }
}
<|endoftext|>


<commit_before>use std::iter::{FromIterator, IntoIterator};
use std::marker::PhantomData;

use super::Bitmap;

#[derive(Clone)]
pub struct BitmapIterator<'a> {
    iterator: ffi::roaring_uint32_iterator_s,
    phantom: PhantomData<&'a Bitmap>,
}

unsafe impl Send for BitmapIterator<'_> {}
unsafe impl Sync for BitmapIterator<'_> {}

impl<'a> BitmapIterator<'a> {
    fn new(bitmap: &'a Bitmap) -> Self {
        let mut iterator = std::mem::MaybeUninit::uninit();
        unsafe {
            ffi::roaring_init_iterator(&bitmap.bitmap, iterator.as_mut_ptr());
        }
        BitmapIterator {
            iterator: unsafe { iterator.assume_init() },
            phantom: PhantomData,
        }
    }

    #[inline]
    fn current_value(&self) -> Option<u32> {
        if self.has_value() {
            Some(self.iterator.current_value)
        } else {
            None
        }
    }

    #[inline]
    fn has_value(&self) -> bool {
        self.iterator.has_value
    }

    #[inline]
    fn advance(&mut self) -> bool {
        unsafe { ffi::roaring_advance_uint32_iterator(&mut self.iterator) }
    }

    /// Attempt to read many values from the iterator into `dst`
    ///
    /// Returns the number of items read from the iterator, may be `< dst.len()` iff
    /// the iterator is exhausted.
    ///
    /// This can be much more efficient than repeated iteration.
    ///
    /// # Examples
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let mut bitmap: Bitmap = Bitmap::create();
    /// bitmap.add_range(0..100);
    /// bitmap.add(222);
    /// bitmap.add(555);
    ///
    /// let mut buf = [0; 100];
    /// let mut iter = bitmap.iter();
    /// assert_eq!(iter.next_many(&mut buf), 100);
    /// // Get the first 100 items, from the original range added
    /// for (i, item) in buf.iter().enumerate() {
    ///     assert_eq!(*item, i as u32);
    /// }
    /// // Calls to next_many() can be interleaved with calls to next()
    /// assert_eq!(iter.next(), Some(222));
    /// assert_eq!(iter.next_many(&mut buf), 1);
    /// assert_eq!(buf[0], 555);
    ///
    /// assert_eq!(iter.next(), None);
    /// assert_eq!(iter.next_many(&mut buf), 0);
    /// ```
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// fn print_by_chunks(bitmap: &Bitmap) {
    ///     let mut buf = [0; 1024];
    ///     let mut iter = bitmap.iter();
    ///     loop {
    ///         let n = iter.next_many(&mut buf);
    ///         if n == 0 {
    ///             break;
    ///         }
    ///         println!("{:?}", &buf[..n]);
    ///     }
    /// }
    ///
    /// # print_by_chunks(&Bitmap::of(&[1, 2, 8, 20, 1000]));
    /// ```
    #[inline]
    pub fn next_many(&mut self, dst: &mut [u32]) -> usize {
        let count: u32 = u32::try_from(dst.len()).unwrap_or(u32::MAX);
        let result = unsafe { ffi::roaring_read_uint32_iterator(&mut self.iterator, dst.as_mut_ptr(), count)};
        debug_assert!(result <= count);
        result as usize
    }
}

impl<'a> Iterator for BitmapIterator<'a> {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        match self.current_value() {
            Some(value) => {
                self.advance();

                Some(value)
            }
            None => None,
        }
    }
}

impl Bitmap {
    /// Returns an iterator over each value stored in the bitmap.
    /// Returned values are ordered in ascending order.
    ///
    /// # Examples
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let mut bitmap = Bitmap::create();
    /// bitmap.add(4);
    /// bitmap.add(3);
    /// bitmap.add(2);
    /// let mut iterator = bitmap.iter();
    ///
    /// assert_eq!(iterator.next(), Some(2));
    /// assert_eq!(iterator.next(), Some(3));
    /// assert_eq!(iterator.next(), Some(4));
    /// assert_eq!(iterator.next(), None);
    /// ```
    pub fn iter(&self) -> BitmapIterator {
        BitmapIterator::new(self)
    }
}

impl FromIterator<u32> for Bitmap {
    /// Convenience method for creating bitmap from iterator.
    ///
    /// # Examples
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let bitmap: Bitmap = (1..3).collect();
    ///
    /// assert!(!bitmap.is_empty());
    /// assert!(bitmap.contains(1));
    /// assert!(bitmap.contains(2));
    /// assert_eq!(bitmap.cardinality(), 2);
    /// ```
    fn from_iter<I: IntoIterator<Item = u32>>(iter: I) -> Self {
        Bitmap::of(&Vec::from_iter(iter))
    }
}

impl Extend<u32> for Bitmap {
    fn extend<T: IntoIterator<Item=u32>>(&mut self, iter: T) {
        for item in iter {
            self.add(item);
        }
    }
}
<commit_msg>Add `reset_at_or_after` to iterator<commit_after>use std::iter::{FromIterator, IntoIterator};
use std::marker::PhantomData;

use super::Bitmap;

#[derive(Clone)]
pub struct BitmapIterator<'a> {
    iterator: ffi::roaring_uint32_iterator_s,
    phantom: PhantomData<&'a Bitmap>,
}

unsafe impl Send for BitmapIterator<'_> {}
unsafe impl Sync for BitmapIterator<'_> {}

impl<'a> BitmapIterator<'a> {
    fn new(bitmap: &'a Bitmap) -> Self {
        let mut iterator = std::mem::MaybeUninit::uninit();
        unsafe {
            ffi::roaring_init_iterator(&bitmap.bitmap, iterator.as_mut_ptr());
        }
        BitmapIterator {
            iterator: unsafe { iterator.assume_init() },
            phantom: PhantomData,
        }
    }

    #[inline]
    fn current_value(&self) -> Option<u32> {
        if self.has_value() {
            Some(self.iterator.current_value)
        } else {
            None
        }
    }

    #[inline]
    fn has_value(&self) -> bool {
        self.iterator.has_value
    }

    #[inline]
    fn advance(&mut self) -> bool {
        unsafe { ffi::roaring_advance_uint32_iterator(&mut self.iterator) }
    }

    /// Attempt to read many values from the iterator into `dst`
    ///
    /// Returns the number of items read from the iterator, may be `< dst.len()` iff
    /// the iterator is exhausted.
    ///
    /// This can be much more efficient than repeated iteration.
    ///
    /// # Examples
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let mut bitmap: Bitmap = Bitmap::create();
    /// bitmap.add_range(0..100);
    /// bitmap.add(222);
    /// bitmap.add(555);
    ///
    /// let mut buf = [0; 100];
    /// let mut iter = bitmap.iter();
    /// assert_eq!(iter.next_many(&mut buf), 100);
    /// // Get the first 100 items, from the original range added
    /// for (i, item) in buf.iter().enumerate() {
    ///     assert_eq!(*item, i as u32);
    /// }
    /// // Calls to next_many() can be interleaved with calls to next()
    /// assert_eq!(iter.next(), Some(222));
    /// assert_eq!(iter.next_many(&mut buf), 1);
    /// assert_eq!(buf[0], 555);
    ///
    /// assert_eq!(iter.next(), None);
    /// assert_eq!(iter.next_many(&mut buf), 0);
    /// ```
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// fn print_by_chunks(bitmap: &Bitmap) {
    ///     let mut buf = [0; 1024];
    ///     let mut iter = bitmap.iter();
    ///     loop {
    ///         let n = iter.next_many(&mut buf);
    ///         if n == 0 {
    ///             break;
    ///         }
    ///         println!("{:?}", &buf[..n]);
    ///     }
    /// }
    ///
    /// # print_by_chunks(&Bitmap::of(&[1, 2, 8, 20, 1000]));
    /// ```
    #[inline]
    pub fn next_many(&mut self, dst: &mut [u32]) -> usize {
        let count: u32 = u32::try_from(dst.len()).unwrap_or(u32::MAX);
        let result = unsafe {
            ffi::roaring_read_uint32_iterator(&mut self.iterator, dst.as_mut_ptr(), count)
        };
        debug_assert!(result <= count);
        result as usize
    }

    /// Reset the iterator to the first value `>= val`
    ///
    /// This can move the iterator forwards or backwards.
    ///
    /// # Examples
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let mut bitmap = Bitmap::of(&[0, 1, 100, 1000, u32::MAX]);
    /// let mut iter = bitmap.iter();
    /// iter.reset_at_or_after(0);
    /// assert_eq!(iter.next(), Some(0));
    /// iter.reset_at_or_after(0);
    /// assert_eq!(iter.next(), Some(0));
    ///
    /// iter.reset_at_or_after(101);
    /// assert_eq!(iter.next(), Some(1000));
    /// assert_eq!(iter.next(), Some(u32::MAX));
    /// assert_eq!(iter.next(), None);
    /// iter.reset_at_or_after(u32::MAX);
    /// assert_eq!(iter.next(), Some(u32::MAX));
    /// assert_eq!(iter.next(), None);
    /// ```
    #[inline]
    pub fn reset_at_or_after(&mut self, val: u32) {
        unsafe { ffi::roaring_move_uint32_iterator_equalorlarger(&mut self.iterator, val) };
    }
}

impl<'a> Iterator for BitmapIterator<'a> {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        match self.current_value() {
            Some(value) => {
                self.advance();

                Some(value)
            }
            None => None,
        }
    }
}

impl Bitmap {
    /// Returns an iterator over each value stored in the bitmap.
    /// Returned values are ordered in ascending order.
    ///
    /// # Examples
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let mut bitmap = Bitmap::create();
    /// bitmap.add(4);
    /// bitmap.add(3);
    /// bitmap.add(2);
    /// let mut iterator = bitmap.iter();
    ///
    /// assert_eq!(iterator.next(), Some(2));
    /// assert_eq!(iterator.next(), Some(3));
    /// assert_eq!(iterator.next(), Some(4));
    /// assert_eq!(iterator.next(), None);
    /// ```
    pub fn iter(&self) -> BitmapIterator {
        BitmapIterator::new(self)
    }
}

impl FromIterator<u32> for Bitmap {
    /// Convenience method for creating bitmap from iterator.
    ///
    /// # Examples
    ///
    /// ```
    /// use croaring::Bitmap;
    ///
    /// let bitmap: Bitmap = (1..3).collect();
    ///
    /// assert!(!bitmap.is_empty());
    /// assert!(bitmap.contains(1));
    /// assert!(bitmap.contains(2));
    /// assert_eq!(bitmap.cardinality(), 2);
    /// ```
    fn from_iter<I: IntoIterator<Item = u32>>(iter: I) -> Self {
        Bitmap::of(&Vec::from_iter(iter))
    }
}

impl Extend<u32> for Bitmap {
    fn extend<T: IntoIterator<Item=u32>>(&mut self, iter: T) {
        for item in iter {
            self.add(item);
        }
    }
}
<|endoftext|>


<commit_before>use crate::fmt;
use crate::ops::Try;

use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
use super::Map;

/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by [`Iterator::flat_map`]. See its documentation
/// for more.
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
        FlatMap { inner: FlattenCompat::new(iter.map(f)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
where
    U: Clone + IntoIterator<IntoIter: Clone>,
{
    fn clone(&self) -> Self {
        FlatMap { inner: self.inner.clone() }
    }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
where
    U: IntoIterator<IntoIter: fmt::Debug>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
    U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
where
    I: FusedIterator,
    U: IntoIterator,
    F: FnMut(I::Item) -> U,
{
}

/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
///
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
    pub(in super::super) fn new(iter: I) -> Flatten<I> {
        Flatten { inner: FlattenCompat::new(iter) }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> fmt::Debug for Flatten<I>
where
    I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: fmt::Debug + Iterator,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Flatten").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Clone for Flatten<I>
where
    I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Clone + Iterator,
{
    fn clone(&self) -> Self {
        Flatten { inner: self.inner.clone() }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Iterator for Flatten<I>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> DoubleEndedIterator for Flatten<I>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> FusedIterator for Flatten<I>
where
    I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
}

/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
struct FlattenCompat<I, U> {
    iter: Fuse<I>,
    frontiter: Option<U>,
    backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U>
where
    I: Iterator,
{
    /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
    fn new(iter: I) -> FlattenCompat<I, U> {
        FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
    }
}

impl<I, U> Iterator for FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.frontiter {
                match inner.next() {
                    None => self.frontiter = None,
                    elt @ Some(_) => return elt,
                }
            }
            match self.iter.next() {
                None => return self.backiter.as_mut()?.next(),
                Some(inner) => self.frontiter = Some(inner.into_iter()),
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let lo = flo.saturating_add(blo);
        match (self.iter.size_hint(), fhi, bhi) {
            ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
            _ => (lo, None),
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            frontiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_fold(acc, &mut *fold);
                *frontiter = Some(mid);
                r
            }
        }

        if let Some(ref mut front) = self.frontiter {
            init = front.try_fold(init, &mut fold)?;
        }
        self.frontiter = None;

        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
        self.frontiter = None;

        if let Some(ref mut back) = self.backiter {
            init = back.try_fold(init, &mut fold)?;
        }
        self.backiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: Iterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.fold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .fold(init, flatten(fold))
    }
}

impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.backiter {
                match inner.next_back() {
                    None => self.backiter = None,
                    elt @ Some(_) => return elt,
                }
            }
            match self.iter.next_back() {
                None => return self.frontiter.as_mut()?.next_back(),
                next => self.backiter = next.map(IntoIterator::into_iter),
            }
        }
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            backiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a
        where
            T::IntoIter: DoubleEndedIterator,
        {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_rfold(acc, &mut *fold);
                *backiter = Some(mid);
                r
            }
        }

        if let Some(ref mut back) = self.backiter {
            init = back.try_rfold(init, &mut fold)?;
        }
        self.backiter = None;

        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
        self.backiter = None;

        if let Some(ref mut front) = self.frontiter {
            init = front.try_rfold(init, &mut fold)?;
        }
        self.frontiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: DoubleEndedIterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.rfold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .rfold(init, flatten(fold))
    }
}
<commit_msg>Remove flatten doc intra-doc links<commit_after>use crate::fmt;
use crate::ops::Try;

use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
use super::Map;

/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by [`Iterator::flat_map`]. See its documentation
/// for more.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
        FlatMap { inner: FlattenCompat::new(iter.map(f)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
where
    U: Clone + IntoIterator<IntoIter: Clone>,
{
    fn clone(&self) -> Self {
        FlatMap { inner: self.inner.clone() }
    }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
where
    U: IntoIterator<IntoIter: fmt::Debug>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
    U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
where
    I: FusedIterator,
    U: IntoIterator,
    F: FnMut(I::Item) -> U,
{
}

/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
///
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
    pub(in super::super) fn new(iter: I) -> Flatten<I> {
        Flatten { inner: FlattenCompat::new(iter) }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> fmt::Debug for Flatten<I>
where
    I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: fmt::Debug + Iterator,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Flatten").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Clone for Flatten<I>
where
    I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Clone + Iterator,
{
    fn clone(&self) -> Self {
        Flatten { inner: self.inner.clone() }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Iterator for Flatten<I>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> DoubleEndedIterator for Flatten<I>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> FusedIterator for Flatten<I>
where
    I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
}

/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
struct FlattenCompat<I, U> {
    iter: Fuse<I>,
    frontiter: Option<U>,
    backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U>
where
    I: Iterator,
{
    /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
    fn new(iter: I) -> FlattenCompat<I, U> {
        FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
    }
}

impl<I, U> Iterator for FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.frontiter {
                match inner.next() {
                    None => self.frontiter = None,
                    elt @ Some(_) => return elt,
                }
            }
            match self.iter.next() {
                None => return self.backiter.as_mut()?.next(),
                Some(inner) => self.frontiter = Some(inner.into_iter()),
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let lo = flo.saturating_add(blo);
        match (self.iter.size_hint(), fhi, bhi) {
            ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
            _ => (lo, None),
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            frontiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_fold(acc, &mut *fold);
                *frontiter = Some(mid);
                r
            }
        }

        if let Some(ref mut front) = self.frontiter {
            init = front.try_fold(init, &mut fold)?;
        }
        self.frontiter = None;

        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
        self.frontiter = None;

        if let Some(ref mut back) = self.backiter {
            init = back.try_fold(init, &mut fold)?;
        }
        self.backiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: Iterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.fold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .fold(init, flatten(fold))
    }
}

impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.backiter {
                match inner.next_back() {
                    None => self.backiter = None,
                    elt @ Some(_) => return elt,
                }
            }
            match self.iter.next_back() {
                None => return self.frontiter.as_mut()?.next_back(),
                next => self.backiter = next.map(IntoIterator::into_iter),
            }
        }
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            backiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a
        where
            T::IntoIter: DoubleEndedIterator,
        {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_rfold(acc, &mut *fold);
                *backiter = Some(mid);
                r
            }
        }

        if let Some(ref mut back) = self.backiter {
            init = back.try_rfold(init, &mut fold)?;
        }
        self.backiter = None;

        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
        self.backiter = None;

        if let Some(ref mut front) = self.frontiter {
            init = front.try_rfold(init, &mut fold)?;
        }
        self.frontiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: DoubleEndedIterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.rfold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .rfold(init, flatten(fold))
    }
}
<|endoftext|>


<commit_before>use std::vec::with_capacity;
use std::util::swap;
use compile::Instruction;
use compile::{InstLiteral, InstRange, InstMatch, InstJump,
  InstCaptureStart, InstCaptureEnd, InstSplit, InstNoop};

// object containing implementation
// details for executing compiled
// instructions

struct Prog {
  strat: ~ExecStrategy
}

impl Prog {
  pub fn new(inst: ~[Instruction]) -> Prog {
    Prog::new_with_pike_vm(inst)
  }
  pub fn new_with_pike_vm(inst: ~[Instruction]) -> Prog {
    let strat = ~PikeVM::new(inst) as ~ExecStrategy;
    Prog {
      strat: strat
   }
  }
  pub fn new_with_recursive(inst: ~[Instruction]) -> Prog {
    let strat = ~RecursiveBacktracking::new(inst) as ~ExecStrategy;
    Prog {
      strat: strat
    }
  }
}

impl Prog {
  pub fn run(&self, input: &str) {
    match self.strat.run(input) {
      Some(t) => {
        println(fmt!("[FOUND %u]", t.sp));
        println(input.slice_to(t.sp));
      }
      None => println("[NOT FOUND]")
    }
  }
}

// Prog expects an ExecStrategy to run...
// this should be able to take compiled
// instructions and execute them (see compile.rs)

trait ExecStrategy {
  fn run(&self, input: &str) -> Option<Thread>;
}

// the implementation for both PikeVM
// and RecursiveBacktracking strategies are
// outlined here:
// -> http://swtch.com/~rsc/regexp/regexp2.html

struct Thread {
  pc: uint, // some index of an instruction
  sp: uint  // index of a char in the input
}

impl Thread {
  fn new(pc: uint, sp: uint) -> Thread {
    Thread {
      pc: pc,
      sp: sp
    }
  }
}

impl ToStr for Thread {
  fn to_str(&self) -> ~str {
    fmt!("<Thread pc: %u, sp: %u>", self.pc, self.sp)
  }
}

struct PikeVM {
  priv inst: ~[Instruction],
  priv len: uint
}

impl PikeVM {
  fn new(inst: ~[Instruction]) -> PikeVM {
    let len = inst.len();
    PikeVM {
      inst: inst,
      len: len
    }
  }
}

impl ExecStrategy for PikeVM {
  fn run(&self, input: &str) -> Option<Thread> {
    // \x03 is an end of string indicator. it resolves issues
    // the program reaches the end of the string, and still
    // needs to perform instructions
    let input = input.to_owned().append("\x03");

    // setup
    let mut sp = 0;
    let mut found = None;

    let mut clist: ~[Thread] = with_capacity(self.len);
    let mut nlist: ~[Thread] = with_capacity(self.len);

    clist.push(Thread::new(0, sp));

    for c in input.iter() {
      //println(c.to_str());

      let mut i = 0;
      let mut num = clist.len();

      while (i < num) {
        //println(fmt!("RUNNING INST %?", clist[i]));

        let pc = clist[i].pc;

        match self.inst[pc].op {
          InstLiteral(m) => {
            if (c == m) {
              //println(fmt!("c: (%c) == m: (%c)", c, m));
              nlist.push(Thread::new(pc + 1, clist[i].sp));
            }
          }
          InstRange(start, end) => {
            if (c >= start && c <= end) {
              //println(fmt!("c: (%c) within (%c-%c)", c, start, end));
              nlist.push(Thread::new(pc + 1, sp));
            }
          }
          InstMatch => {
            clist[i].sp = sp;
            found = Some(clist[i]);
          }
          InstJump(addr) => {
            //println("JMP");
            clist.push(Thread::new(addr, clist[i].sp));
          }
          InstCaptureStart => {
            clist.push(Thread::new(pc + 1, clist[i].sp));
          }
          InstCaptureEnd => {
            clist.push(Thread::new(pc + 1, clist[i].sp));
          }
          InstSplit(laddr, raddr) => {
            clist.push(Thread::new(laddr, clist[i].sp));
            clist.push(Thread::new(raddr, clist[i].sp));
          }
          InstNoop => {
            clist.push(Thread::new(pc + 1, clist[i].sp));
          } // continue
        }

        //println(fmt!("BEFORE %u", i));

        i += 1;
        num = clist.len();

        //println(fmt!("clist: %?", clist));
        //println(fmt!("nlist: %?", nlist));
      }

      swap(&mut clist, &mut nlist);
      /*
      println("SWAPPING");
      println("AFTER");
      println(fmt!("clist: %?", clist));
      println(fmt!("nlist: %?", nlist));
      */
      nlist.clear();

      sp += c.len_utf8_bytes();
    }

    found
  }
}

// ignore this
// for now...
// this implementation is feature complete, but slow.
// we can execute all the instructions we currently support
// in PikeVM

struct RecursiveBacktracking {
  priv inst: ~[Instruction],
  priv len: uint
}

impl RecursiveBacktracking {
  fn new(inst: ~[Instruction]) -> RecursiveBacktracking {
    let len = inst.len();
    RecursiveBacktracking {
      inst: inst,
      len: len
    }
  }
}

impl ExecStrategy for RecursiveBacktracking {
  fn run(&self, input: &str) -> Option<Thread> {
    let input = input.to_owned().append("\x03");

    None
  }
}
<commit_msg>nongreedy matching might be working now<commit_after>use std::vec::with_capacity;
use std::util::swap;
use compile::Instruction;
use compile::{InstLiteral, InstRange, InstMatch, InstJump,
  InstCaptureStart, InstCaptureEnd, InstSplit, InstNoop};

// object containing implementation
// details for executing compiled
// instructions

struct Prog {
  strat: ~ExecStrategy
}

impl Prog {
  pub fn new(inst: ~[Instruction]) -> Prog {
    Prog::new_with_pike_vm(inst)
  }
  pub fn new_with_pike_vm(inst: ~[Instruction]) -> Prog {
    let strat = ~PikeVM::new(inst) as ~ExecStrategy;
    Prog {
      strat: strat
   }
  }
  pub fn new_with_recursive(inst: ~[Instruction]) -> Prog {
    let strat = ~RecursiveBacktracking::new(inst) as ~ExecStrategy;
    Prog {
      strat: strat
    }
  }
}

impl Prog {
  pub fn run(&self, input: &str) {
    match self.strat.run(input) {
      Some(t) => {
        println(fmt!("[FOUND %u]", t.sp));
        println(input.slice_to(t.sp));
      }
      None => println("[NOT FOUND]")
    }
  }
}

// Prog expects an ExecStrategy to run...
// this should be able to take compiled
// instructions and execute them (see compile.rs)

trait ExecStrategy {
  fn run(&self, input: &str) -> Option<Thread>;
}

// the implementation for both PikeVM
// and RecursiveBacktracking strategies are
// outlined here:
// -> http://swtch.com/~rsc/regexp/regexp2.html

struct Thread {
  pc: uint, // some index of an instruction
  sp: uint  // index of a char in the input
}

impl Thread {
  fn new(pc: uint, sp: uint) -> Thread {
    Thread {
      pc: pc,
      sp: sp
    }
  }
}

impl ToStr for Thread {
  fn to_str(&self) -> ~str {
    fmt!("<Thread pc: %u, sp: %u>", self.pc, self.sp)
  }
}

struct PikeVM {
  priv inst: ~[Instruction],
  priv len: uint
}

impl PikeVM {
  fn new(inst: ~[Instruction]) -> PikeVM {
    let len = inst.len();
    PikeVM {
      inst: inst,
      len: len
    }
  }
}

impl ExecStrategy for PikeVM {
  fn run(&self, input: &str) -> Option<Thread> {
    // \x03 is an end of string indicator. it resolves issues
    // the program reaches the end of the string, and still
    // needs to perform instructions
    let input = input.to_owned().append("\x03");

    // setup
    let mut sp = 0;

    let mut clist: ~[Thread] = with_capacity(self.len);
    let mut nlist: ~[Thread] = with_capacity(self.len);

    clist.push(Thread::new(0, sp));

    for c in input.iter() {
      //println(c.to_str());

      let mut i = 0;
      let mut num = clist.len();

      while (i < num) {
        //println(fmt!("RUNNING INST %?", clist[i]));

        let pc = clist[i].pc;

        match self.inst[pc].op {
          InstLiteral(m) => {
            if (c == m) {
              //println(fmt!("c: (%c) == m: (%c)", c, m));
              nlist.push(Thread::new(pc + 1, clist[i].sp));
              break;
            }
          }
          InstRange(start, end) => {
            if (c >= start && c <= end) {
              //println(fmt!("c: (%c) within (%c-%c)", c, start, end));
              nlist.push(Thread::new(pc + 1, sp));
              break;
            }
          }
          InstMatch => {
            clist[i].sp = sp;
            return Some(clist[i])
          }
          InstJump(addr) => {
            //println("JMP");
            clist.push(Thread::new(addr, clist[i].sp));
          }
          InstCaptureStart => {
            clist.push(Thread::new(pc + 1, clist[i].sp));
          }
          InstCaptureEnd => {
            clist.push(Thread::new(pc + 1, clist[i].sp));
          }
          InstSplit(laddr, raddr) => {
            clist.push(Thread::new(laddr, clist[i].sp));
            clist.push(Thread::new(raddr, clist[i].sp));
          }
          InstNoop => {
            clist.push(Thread::new(pc + 1, clist[i].sp));
          } // continue
        }

        //println(fmt!("BEFORE %u", i));

        i += 1;
        num = clist.len();

        //println(fmt!("clist: %?", clist));
        //println(fmt!("nlist: %?", nlist));
      }

      swap(&mut clist, &mut nlist);
      /*
      println("SWAPPING");
      println("AFTER");
      println(fmt!("clist: %?", clist));
      println(fmt!("nlist: %?", nlist));
      */
      nlist.clear();

      // different encodings have different
      // lengths, so we can't just increment
      // by 1
      sp += c.len_utf8_bytes();
    }

    None
  }
}

// ignore this
// for now...
// this implementation is feature complete, but slow.
// we can execute all the instructions we currently support
// in PikeVM

struct RecursiveBacktracking {
  priv inst: ~[Instruction],
  priv len: uint
}

impl RecursiveBacktracking {
  fn new(inst: ~[Instruction]) -> RecursiveBacktracking {
    let len = inst.len();
    RecursiveBacktracking {
      inst: inst,
      len: len
    }
  }
}

impl ExecStrategy for RecursiveBacktracking {
  fn run(&self, input: &str) -> Option<Thread> {
    let input = input.to_owned().append("\x03");

    None
  }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use util::graph::{Nodes,Edges};

use core::{
    Dependency,
    PackageId,
    Registry,
    SourceId,
};

use semver;

use util::{CargoResult, Graph, human, internal};

pub struct Resolve {
    graph: Graph<PackageId>
}

impl Resolve {
    fn new() -> Resolve {
        Resolve { graph: Graph::new() }
    }

    pub fn iter<'a>(&'a self) -> Nodes<'a, PackageId> {
        self.graph.iter()
    }

    pub fn deps<'a>(&'a self, pkg: &PackageId) -> Option<Edges<'a, PackageId>> {
        self.graph.edges(pkg)
    }
}

struct Context<'a, R> {
    registry: &'a mut R,
    resolve: Resolve,

    // Eventually, we will have smarter logic for checking for conflicts in the resolve,
    // but without the registry, conflicts should not exist in practice, so this is just
    // a sanity check.
    seen: HashMap<(String, SourceId), semver::Version>
}

impl<'a, R: Registry> Context<'a, R> {
    fn new(registry: &'a mut R) -> Context<'a, R> {
        Context {
            registry: registry,
            resolve: Resolve::new(),
            seen: HashMap::new()
        }
    }
}

pub fn resolve<R: Registry>(root: &PackageId, deps: &[Dependency], registry: &mut R)
                            -> CargoResult<Resolve>
{
    log!(5, "resolve; deps={}", deps);

    let mut context = Context::new(registry);
    try!(resolve_deps(root, deps, &mut context));
    Ok(context.resolve)
}

fn resolve_deps<'a, R: Registry>(parent: &PackageId,
                                 deps: &[Dependency],
                                 ctx: &mut Context<'a, R>)
                                 -> CargoResult<()>
{
    if deps.is_empty() {
        return Ok(());
    }

    for dep in deps.iter() {
        let pkgs = try!(ctx.registry.query(dep));

        if pkgs.is_empty() {
            return Err(human(format!("No package named {} found", dep)));
        }

        if pkgs.len() > 1 {
            return Err(internal(format!("At the moment, Cargo only supports a \
                single source for a particular package name ({}).", dep)));
        }

        let summary = pkgs.get(0).clone();
        let name = summary.get_name().to_str();
        let source_id = summary.get_source_id().clone();
        let version = summary.get_version().clone();

        ctx.resolve.graph.link(parent.clone(), summary.get_package_id().clone());

        let found = {
            let found = ctx.seen.find(&(name.clone(), source_id.clone()));

            if found.is_some() {
                if found == Some(&version) { continue; }
                return Err(human(format!("Cargo found multiple copies of {} in {}. This \
                                        is not currently supported",
                                        summary.get_name(), summary.get_source_id())));
            } else {
                false
            }
        };

        if !found {
            ctx.seen.insert((name, source_id), version);
        }

        ctx.resolve.graph.add(summary.get_package_id().clone(), []);

        let deps: Vec<Dependency> = summary.get_dependencies().iter()
            .filter(|d| d.is_transitive())
            .map(|d| d.clone())
            .collect();

        try!(resolve_deps(summary.get_package_id(), deps.as_slice(), ctx));
    }

    Ok(())
}

#[cfg(test)]
mod test {
    use hamcrest::{assert_that, equal_to, contains};

    use core::source::{SourceId, RegistryKind, Location, Remote};
    use core::{Dependency, PackageId, Summary, Registry};
    use util::CargoResult;

    fn resolve<R: Registry>(pkg: &PackageId, deps: &[Dependency], registry: &mut R)
                            -> CargoResult<Vec<PackageId>>
    {
        Ok(try!(super::resolve(pkg, deps, registry)).iter().map(|p| p.clone()).collect())
    }

    trait ToDep {
        fn to_dep(self) -> Dependency;
    }

    impl ToDep for &'static str {
        fn to_dep(self) -> Dependency {
            let url = from_str("http://example.com").unwrap();
            let source_id = SourceId::new(RegistryKind, Remote(url));
            Dependency::parse(self, Some("1.0.0"), &source_id).unwrap()
        }
    }

    impl ToDep for Dependency {
        fn to_dep(self) -> Dependency {
            self
        }
    }

    macro_rules! pkg(
        ($name:expr => $($deps:expr),+) => ({
            let d: Vec<Dependency> = vec!($($deps.to_dep()),+);

            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         d.as_slice())
        });

        ($name:expr) => (
            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         [])
        )
    )

    fn registry_loc() -> SourceId {
        let remote = Location::parse("http://example.com").unwrap();
        SourceId::new(RegistryKind, remote)
    }

    fn pkg(name: &str) -> Summary {
        Summary::new(&pkg_id(name), &[])
    }

    fn pkg_id(name: &str) -> PackageId {
        PackageId::new(name, "1.0.0", &registry_loc()).unwrap()
    }

    fn dep(name: &str) -> Dependency {
        let url = from_str("http://example.com").unwrap();
        let source_id = SourceId::new(RegistryKind, Remote(url));
        Dependency::parse(name, Some("1.0.0"), &source_id).unwrap()
    }

    fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
        pkgs
    }

    fn names(names: &[&'static str]) -> Vec<PackageId> {
        names.iter()
            .map(|name| PackageId::new(*name, "1.0.0", &registry_loc()).unwrap())
            .collect()
    }

    #[test]
    pub fn test_resolving_empty_dependency_list() {
        let res = resolve(&pkg_id("root"), [], &mut registry(vec!())).unwrap();

        assert_that(&res, equal_to(&names([])));
    }

    #[test]
    pub fn test_resolving_only_package() {
        let mut reg = registry(vec!(pkg("foo")));
        let res = resolve(&pkg_id("root"), [dep("foo")], &mut reg);

        assert_that(&res.unwrap(), contains(names(["root", "foo"])).exactly());
    }

    #[test]
    pub fn test_resolving_one_dep() {
        let mut reg = registry(vec!(pkg("foo"), pkg("bar")));
        let res = resolve(&pkg_id("root"), [dep("foo")], &mut reg);

        assert_that(&res.unwrap(), contains(names(["root", "foo"])).exactly());
    }

    #[test]
    pub fn test_resolving_multiple_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar"), pkg!("baz")));
        let res = resolve(&pkg_id("root"), [dep("foo"), dep("baz")], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "baz"])).exactly());
    }

    #[test]
    pub fn test_resolving_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar" => "foo")));
        let res = resolve(&pkg_id("root"), [dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_common_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo" => "bar"), pkg!("bar")));
        let res = resolve(&pkg_id("root"), [dep("foo"), dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_with_dev_deps() {
        let mut reg = registry(vec!(
            pkg!("foo" => "bar", dep("baz").as_dev()),
            pkg!("baz" => "bat", dep("bam").as_dev()),
            pkg!("bar"),
            pkg!("bat")
        ));

        let res = resolve(&pkg_id("root"), [dep("foo"), dep("baz").as_dev()], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "bar", "baz"])));
    }
}
<commit_msg>Add some unit tests<commit_after>use std::collections::HashMap;
use util::graph::{Nodes,Edges};

use core::{
    Dependency,
    PackageId,
    Registry,
    SourceId,
};

use semver;

use util::{CargoResult, Graph, human, internal};

pub struct Resolve {
    graph: Graph<PackageId>
}

impl Resolve {
    fn new() -> Resolve {
        Resolve { graph: Graph::new() }
    }

    pub fn iter<'a>(&'a self) -> Nodes<'a, PackageId> {
        self.graph.iter()
    }

    pub fn deps<'a>(&'a self, pkg: &PackageId) -> Option<Edges<'a, PackageId>> {
        self.graph.edges(pkg)
    }
}

struct Context<'a, R> {
    registry: &'a mut R,
    resolve: Resolve,

    // Eventually, we will have smarter logic for checking for conflicts in the resolve,
    // but without the registry, conflicts should not exist in practice, so this is just
    // a sanity check.
    seen: HashMap<(String, SourceId), semver::Version>
}

impl<'a, R: Registry> Context<'a, R> {
    fn new(registry: &'a mut R) -> Context<'a, R> {
        Context {
            registry: registry,
            resolve: Resolve::new(),
            seen: HashMap::new()
        }
    }
}

pub fn resolve<R: Registry>(root: &PackageId, deps: &[Dependency], registry: &mut R)
                            -> CargoResult<Resolve>
{
    log!(5, "resolve; deps={}", deps);

    let mut context = Context::new(registry);
    try!(resolve_deps(root, deps, &mut context));
    Ok(context.resolve)
}

fn resolve_deps<'a, R: Registry>(parent: &PackageId,
                                 deps: &[Dependency],
                                 ctx: &mut Context<'a, R>)
                                 -> CargoResult<()>
{
    if deps.is_empty() {
        return Ok(());
    }

    for dep in deps.iter() {
        let pkgs = try!(ctx.registry.query(dep));

        if pkgs.is_empty() {
            return Err(human(format!("No package named {} found", dep)));
        }

        if pkgs.len() > 1 {
            return Err(internal(format!("At the moment, Cargo only supports a \
                single source for a particular package name ({}).", dep)));
        }

        let summary = pkgs.get(0).clone();
        let name = summary.get_name().to_str();
        let source_id = summary.get_source_id().clone();
        let version = summary.get_version().clone();

        ctx.resolve.graph.link(parent.clone(), summary.get_package_id().clone());

        let found = {
            let found = ctx.seen.find(&(name.clone(), source_id.clone()));

            if found.is_some() {
                if found == Some(&version) { continue; }
                return Err(human(format!("Cargo found multiple copies of {} in {}. This \
                                        is not currently supported",
                                        summary.get_name(), summary.get_source_id())));
            } else {
                false
            }
        };

        if !found {
            ctx.seen.insert((name, source_id), version);
        }

        ctx.resolve.graph.add(summary.get_package_id().clone(), []);

        let deps: Vec<Dependency> = summary.get_dependencies().iter()
            .filter(|d| d.is_transitive())
            .map(|d| d.clone())
            .collect();

        try!(resolve_deps(summary.get_package_id(), deps.as_slice(), ctx));
    }

    Ok(())
}

#[cfg(test)]
mod test {
    use hamcrest::{assert_that, equal_to, contains};

    use core::source::{SourceId, RegistryKind, GitKind, Location, Remote};
    use core::{Dependency, PackageId, Summary, Registry};
    use util::CargoResult;

    fn resolve<R: Registry>(pkg: &PackageId, deps: &[Dependency], registry: &mut R)
                            -> CargoResult<Vec<PackageId>>
    {
        Ok(try!(super::resolve(pkg, deps, registry)).iter().map(|p| p.clone()).collect())
    }

    trait ToDep {
        fn to_dep(self) -> Dependency;
    }

    impl ToDep for &'static str {
        fn to_dep(self) -> Dependency {
            let url = from_str("http://example.com").unwrap();
            let source_id = SourceId::new(RegistryKind, Remote(url));
            Dependency::parse(self, Some("1.0.0"), &source_id).unwrap()
        }
    }

    impl ToDep for Dependency {
        fn to_dep(self) -> Dependency {
            self
        }
    }

    macro_rules! pkg(
        ($name:expr => $($deps:expr),+) => ({
            let d: Vec<Dependency> = vec!($($deps.to_dep()),+);

            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         d.as_slice())
        });

        ($name:expr) => (
            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         [])
        )
    )

    fn registry_loc() -> SourceId {
        let remote = Location::parse("http://example.com").unwrap();
        SourceId::new(RegistryKind, remote)
    }

    fn pkg(name: &str) -> Summary {
        Summary::new(&pkg_id(name), &[])
    }

    fn pkg_id(name: &str) -> PackageId {
        PackageId::new(name, "1.0.0", &registry_loc()).unwrap()
    }

    fn pkg_id_loc(name: &str, loc: &str) -> PackageId {
        let remote = Location::parse(loc);
        let source_id = SourceId::new(GitKind("master".to_str()),
                                      remote.unwrap());

        PackageId::new(name, "1.0.0", &source_id).unwrap()
    }

    fn pkg_loc(name: &str, loc: &str) -> Summary {
        Summary::new(&pkg_id_loc(name, loc), &[])
    }

    fn dep(name: &str) -> Dependency {
        let url = from_str("http://example.com").unwrap();
        let source_id = SourceId::new(RegistryKind, Remote(url));
        Dependency::parse(name, Some("1.0.0"), &source_id).unwrap()
    }

    fn dep_loc(name: &str, location: &str) -> Dependency {
        let url = from_str(location).unwrap();
        let source_id = SourceId::new(GitKind("master".to_str()), Remote(url));
        Dependency::parse(name, Some("1.0.0"), &source_id).unwrap()
    }

    fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
        pkgs
    }

    fn names(names: &[&'static str]) -> Vec<PackageId> {
        names.iter()
            .map(|name| PackageId::new(*name, "1.0.0", &registry_loc()).unwrap())
            .collect()
    }

    fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {
        names.iter()
            .map(|&(name, loc)| pkg_id_loc(name, loc)).collect()
    }

    #[test]
    pub fn test_resolving_empty_dependency_list() {
        let res = resolve(&pkg_id("root"), [], &mut registry(vec!())).unwrap();

        assert_that(&res, equal_to(&names([])));
    }

    #[test]
    pub fn test_resolving_only_package() {
        let mut reg = registry(vec!(pkg("foo")));
        let res = resolve(&pkg_id("root"), [dep("foo")], &mut reg);

        assert_that(&res.unwrap(), contains(names(["root", "foo"])).exactly());
    }

    #[test]
    pub fn test_resolving_one_dep() {
        let mut reg = registry(vec!(pkg("foo"), pkg("bar")));
        let res = resolve(&pkg_id("root"), [dep("foo")], &mut reg);

        assert_that(&res.unwrap(), contains(names(["root", "foo"])).exactly());
    }

    #[test]
    pub fn test_resolving_multiple_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar"), pkg!("baz")));
        let res = resolve(&pkg_id("root"), [dep("foo"), dep("baz")], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "baz"])).exactly());
    }

    #[test]
    pub fn test_resolving_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar" => "foo")));
        let res = resolve(&pkg_id("root"), [dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_common_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo" => "bar"), pkg!("bar")));
        let res = resolve(&pkg_id("root"), [dep("foo"), dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_with_same_name() {
        let list = vec!(pkg_loc("foo", "http://first.example.com"),
                        pkg_loc("foo", "http://second.example.com"));

        let mut reg = registry(list);
        let res = resolve(&pkg_id("root"),
                          [dep_loc("foo", "http://first.example.com"),
                           dep_loc("foo", "http://second.example.com")],
                           &mut reg);

        let mut names = loc_names([("foo", "http://first.example.com"),
                              ("foo", "http://second.example.com")]);

        names.push(pkg_id("root"));

        assert_that(&res.unwrap(), contains(names).exactly());
    }

    #[test]
    pub fn test_resolving_with_dev_deps() {
        let mut reg = registry(vec!(
            pkg!("foo" => "bar", dep("baz").as_dev()),
            pkg!("baz" => "bat", dep("bam").as_dev()),
            pkg!("bar"),
            pkg!("bat")
        ));

        let res = resolve(&pkg_id("root"), [dep("foo"), dep("baz").as_dev()], &mut reg).unwrap();

        assert_that(&res, contains(names(["root", "foo", "bar", "baz"])));
    }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt};
use std::convert::TryFrom;
use std::default::Default;
use std::{error, fmt, mem};
use std::io::{self, Cursor, Read};
use std::marker::PhantomData;

use crate::error::{DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind};
use crate::image::{ImageDecoder, ImageFormat};

use crate::color;

use super::vp8::Frame;
use super::vp8::Vp8Decoder;

/// All errors that can occur when attempting to parse a WEBP container
#[derive(Debug, Clone, Copy)]
enum DecoderError {
    /// RIFF's "RIFF" signature not found or invalid
    RiffSignatureInvalid([u8; 4]),
    /// WebP's "WEBP" signature not found or invalid
    WebpSignatureInvalid([u8; 4]),
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        struct SignatureWriter([u8; 4]);
        impl fmt::Display for SignatureWriter {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(f, "[{:#04X?}, {:#04X?}, {:#04X?}, {:#04X?}]", self.0[0], self.0[1], self.0[2], self.0[3])
            }
        }

        match self {
            DecoderError::RiffSignatureInvalid(riff) =>
                f.write_fmt(format_args!("Invalid RIFF signature: {}", SignatureWriter(*riff))),
            DecoderError::WebpSignatureInvalid(webp) =>
                f.write_fmt(format_args!("Invalid WebP signature: {}", SignatureWriter(*webp))),
        }
    }
}

impl From<DecoderError> for ImageError {
    fn from(e: DecoderError) -> ImageError {
        ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e))
    }
}

impl error::Error for DecoderError {}

/// WebP Image format decoder. Currently only supports lossy RGB images.
pub struct WebPDecoder<R> {
    r: R,
    frame: Frame,
    have_frame: bool,
}

impl<R: Read> WebPDecoder<R> {
    /// Create a new WebPDecoder from the Reader ```r```.
    /// This function takes ownership of the Reader.
    pub fn new(r: R) -> ImageResult<WebPDecoder<R>> {
        let f: Frame = Default::default();

        let mut decoder = WebPDecoder {
            r,
            have_frame: false,
            frame: f,
        };
        decoder.read_metadata()?;
        Ok(decoder)
    }

    fn read_riff_header(&mut self) -> ImageResult<u32> {
        let mut riff = [0; 4];
        self.r.read_exact(&mut riff)?;
        if &riff != b"RIFF" {
            return Err(DecoderError::RiffSignatureInvalid(riff).into());
        }

        let size = self.r.read_u32::<LittleEndian>()?;

        let mut webp = [0; 4];
        self.r.read_exact(&mut webp)?;
        if &webp != b"WEBP" {
            return Err(DecoderError::WebpSignatureInvalid(webp).into());
        }

        Ok(size)
    }

    fn read_vp8_header(&mut self) -> ImageResult<u32> {
        loop {
            let mut chunk = [0; 4];
            self.r.read_exact(&mut chunk)?;

            match &chunk {
                b"VP8 " => {
                    let len = self.r.read_u32::<LittleEndian>()?;
                    return Ok(len);
                }
                b"ALPH" | b"VP8L" | b"ANIM" | b"ANMF" => {
                    // Alpha, Lossless and Animation isn't supported
                    return Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
                        ImageFormat::WebP.into(),
                        UnsupportedErrorKind::GenericFeature(chunk.iter().map(|&b| b as char).collect()),
                    )));
                }
                _ => {
                    let mut len = self.r.read_u32::<LittleEndian>()?;
                    if len % 2 != 0 {
                        // RIFF chunks containing an uneven number of bytes append
                        // an extra 0x00 at the end of the chunk
                        len += 1;
                    }
                    io::copy(&mut self.r.by_ref().take(len as u64), &mut io::sink())?;
                }
            }
        }
    }

    fn read_frame(&mut self, len: u32) -> ImageResult<()> {
        let mut framedata = Vec::new();
        self.r.by_ref().take(len as u64).read_to_end(&mut framedata)?;
        let m = io::Cursor::new(framedata);

        let mut v = Vp8Decoder::new(m);
        let frame = v.decode_frame()?;

        self.frame = frame.clone();

        Ok(())
    }

    fn read_metadata(&mut self) -> ImageResult<()> {
        if !self.have_frame {
            self.read_riff_header()?;
            let len = self.read_vp8_header()?;
            self.read_frame(len)?;

            self.have_frame = true;
        }

        Ok(())
    }
}

/// Wrapper struct around a `Cursor<Vec<u8>>`
pub struct WebpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
impl<R> Read for WebpReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        if self.0.position() == 0 && buf.is_empty() {
            mem::swap(buf, self.0.get_mut());
            Ok(buf.len())
        } else {
            self.0.read_to_end(buf)
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for WebPDecoder<R> {
    type Reader = WebpReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        (u32::from(self.frame.width), u32::from(self.frame.height))
    }

    fn color_type(&self) -> color::ColorType {
        color::ColorType::Rgb8
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        let mut data = vec![0; self.frame.ybuf.len() * 3];
        self.frame.fill_rgb(data.as_mut_slice());
        Ok(WebpReader(Cursor::new(data), PhantomData))
    }

    fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
        self.frame.fill_rgb(buf);
        Ok(())
    }
}
<commit_msg>webp: Do not panic on overflow if size is maximum<commit_after>use byteorder::{LittleEndian, ReadBytesExt};
use std::convert::TryFrom;
use std::default::Default;
use std::{error, fmt, mem};
use std::io::{self, Cursor, Read};
use std::marker::PhantomData;

use crate::error::{DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind};
use crate::image::{ImageDecoder, ImageFormat};

use crate::color;

use super::vp8::Frame;
use super::vp8::Vp8Decoder;

/// All errors that can occur when attempting to parse a WEBP container
#[derive(Debug, Clone, Copy)]
enum DecoderError {
    /// RIFF's "RIFF" signature not found or invalid
    RiffSignatureInvalid([u8; 4]),
    /// WebP's "WEBP" signature not found or invalid
    WebpSignatureInvalid([u8; 4]),
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        struct SignatureWriter([u8; 4]);
        impl fmt::Display for SignatureWriter {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(f, "[{:#04X?}, {:#04X?}, {:#04X?}, {:#04X?}]", self.0[0], self.0[1], self.0[2], self.0[3])
            }
        }

        match self {
            DecoderError::RiffSignatureInvalid(riff) =>
                f.write_fmt(format_args!("Invalid RIFF signature: {}", SignatureWriter(*riff))),
            DecoderError::WebpSignatureInvalid(webp) =>
                f.write_fmt(format_args!("Invalid WebP signature: {}", SignatureWriter(*webp))),
        }
    }
}

impl From<DecoderError> for ImageError {
    fn from(e: DecoderError) -> ImageError {
        ImageError::Decoding(DecodingError::new(ImageFormat::WebP.into(), e))
    }
}

impl error::Error for DecoderError {}

/// WebP Image format decoder. Currently only supports lossy RGB images.
pub struct WebPDecoder<R> {
    r: R,
    frame: Frame,
    have_frame: bool,
}

impl<R: Read> WebPDecoder<R> {
    /// Create a new WebPDecoder from the Reader ```r```.
    /// This function takes ownership of the Reader.
    pub fn new(r: R) -> ImageResult<WebPDecoder<R>> {
        let f: Frame = Default::default();

        let mut decoder = WebPDecoder {
            r,
            have_frame: false,
            frame: f,
        };
        decoder.read_metadata()?;
        Ok(decoder)
    }

    fn read_riff_header(&mut self) -> ImageResult<u32> {
        let mut riff = [0; 4];
        self.r.read_exact(&mut riff)?;
        if &riff != b"RIFF" {
            return Err(DecoderError::RiffSignatureInvalid(riff).into());
        }

        let size = self.r.read_u32::<LittleEndian>()?;

        let mut webp = [0; 4];
        self.r.read_exact(&mut webp)?;
        if &webp != b"WEBP" {
            return Err(DecoderError::WebpSignatureInvalid(webp).into());
        }

        Ok(size)
    }

    fn read_vp8_header(&mut self) -> ImageResult<u32> {
        loop {
            let mut chunk = [0; 4];
            self.r.read_exact(&mut chunk)?;

            match &chunk {
                b"VP8 " => {
                    let len = self.r.read_u32::<LittleEndian>()?;
                    return Ok(len);
                }
                b"ALPH" | b"VP8L" | b"ANIM" | b"ANMF" => {
                    // Alpha, Lossless and Animation isn't supported
                    return Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
                        ImageFormat::WebP.into(),
                        UnsupportedErrorKind::GenericFeature(chunk.iter().map(|&b| b as char).collect()),
                    )));
                }
                _ => {
                    let mut len = u64::from(self.r.read_u32::<LittleEndian>()?);

                    if len % 2 != 0 {
                        // RIFF chunks containing an uneven number of bytes append
                        // an extra 0x00 at the end of the chunk
                        //
                        // The addition cannot overflow since we have a u64 that was created from a u32
                        len += 1;
                    }

                    io::copy(&mut self.r.by_ref().take(len), &mut io::sink())?;
                }
            }
        }
    }

    fn read_frame(&mut self, len: u32) -> ImageResult<()> {
        let mut framedata = Vec::new();
        self.r.by_ref().take(len as u64).read_to_end(&mut framedata)?;
        let m = io::Cursor::new(framedata);

        let mut v = Vp8Decoder::new(m);
        let frame = v.decode_frame()?;

        self.frame = frame.clone();

        Ok(())
    }

    fn read_metadata(&mut self) -> ImageResult<()> {
        if !self.have_frame {
            self.read_riff_header()?;
            let len = self.read_vp8_header()?;
            self.read_frame(len)?;

            self.have_frame = true;
        }

        Ok(())
    }
}

/// Wrapper struct around a `Cursor<Vec<u8>>`
pub struct WebpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
impl<R> Read for WebpReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        if self.0.position() == 0 && buf.is_empty() {
            mem::swap(buf, self.0.get_mut());
            Ok(buf.len())
        } else {
            self.0.read_to_end(buf)
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for WebPDecoder<R> {
    type Reader = WebpReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        (u32::from(self.frame.width), u32::from(self.frame.height))
    }

    fn color_type(&self) -> color::ColorType {
        color::ColorType::Rgb8
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        let mut data = vec![0; self.frame.ybuf.len() * 3];
        self.frame.fill_rgb(data.as_mut_slice());
        Ok(WebpReader(Cursor::new(data), PhantomData))
    }

    fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
        self.frame.fill_rgb(buf);
        Ok(())
    }
}

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

    #[test]
    fn add_with_overflow_size() {
        let bytes = vec![0x52, 0x49, 0x46, 0x46, 0xaf, 0x37, 0x80, 0x47, 0x57, 0x45, 0x42, 0x50,
                        0x6c, 0x64, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x7e, 0x73, 0x00,
                        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
                        0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x40, 0xfb, 0xff, 0xff, 0x65, 0x65,
                        0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00,
                        0x62, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x49, 0x54,
                        0x55, 0x50, 0x4c, 0x54, 0x59, 0x50, 0x45, 0x33, 0x37, 0x44, 0x4d, 0x46];

        let data = std::io::Cursor::new(bytes);

        let _ = WebPDecoder::new(data);
    }
}
<|endoftext|>