<commit_before>//! DNS Resolution used by the `HttpConnector`.
//!
//! This module contains:
//!
//! - A [`GaiResolver`](GaiResolver) that is the default resolver for the
//!   `HttpConnector`.
//! - The `Name` type used as an argument to custom resolvers.
//!
//! # Resolvers are `Service`s
//!
//! A resolver is just a
//! `Service<Name, Response = impl Iterator<Item = IpAddr>>`.
//!
//! A simple resolver that ignores the name and always returns a specific
//! address:
//!
//! ```rust,ignore
//! use std::{convert::Infallible, iter, net::IpAddr};
//!
//! let resolver = tower::service_fn(|_name| async {
//!     Ok::<_, Infallible>(iter::once(IpAddr::from([127, 0, 0, 1])))
//! });
//! ```
use std::error::Error;
use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
use std::pin::Pin;
use std::str::FromStr;
use std::task::{self, Poll};
use std::{fmt, io, vec};

use tokio::task::JoinHandle;
use tower_service::Service;

pub(super) use self::sealed::Resolve;

/// A domain name to resolve into IP addresses.
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct Name {
    host: String,
}

/// A resolver using blocking `getaddrinfo` calls in a threadpool.
#[derive(Clone)]
pub struct GaiResolver {
    _priv: (),
}

/// An iterator of IP addresses returned from `getaddrinfo`.
pub struct GaiAddrs {
    inner: IpAddrs,
}

/// A future to resolve a name returned by `GaiResolver`.
pub struct GaiFuture {
    inner: JoinHandle<Result<IpAddrs, io::Error>>,
}

impl Name {
    pub(super) fn new(host: String) -> Name {
        Name { host }
    }

    /// View the hostname as a string slice.
    pub fn as_str(&self) -> &str {
        &self.host
    }
}

impl fmt::Debug for Name {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.host, f)
    }
}

impl fmt::Display for Name {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.host, f)
    }
}

impl FromStr for Name {
    type Err = InvalidNameError;

    fn from_str(host: &str) -> Result<Self, Self::Err> {
        // Possibly add validation later
        Ok(Name::new(host.to_owned()))
    }
}

/// Error indicating a given string was not a valid domain name.
#[derive(Debug)]
pub struct InvalidNameError(());

impl fmt::Display for InvalidNameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Not a valid domain name")
    }
}

impl Error for InvalidNameError {}

impl GaiResolver {
    /// Construct a new `GaiResolver`.
    pub fn new() -> Self {
        GaiResolver { _priv: () }
    }
}

impl Service<Name> for GaiResolver {
    type Response = GaiAddrs;
    type Error = io::Error;
    type Future = GaiFuture;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, name: Name) -> Self::Future {
        let blocking = tokio::task::spawn_blocking(move || {
            debug!("resolving host={:?}", name.host);
            (&*name.host, 0)
                .to_socket_addrs()
                .map(|i| IpAddrs { iter: i })
        });

        GaiFuture { inner: blocking }
    }
}

impl fmt::Debug for GaiResolver {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("GaiResolver")
    }
}

impl Future for GaiFuture {
    type Output = Result<GaiAddrs, io::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        Pin::new(&mut self.inner).poll(cx).map(|res| match res {
            Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
            Ok(Err(err)) => Err(err),
            Err(join_err) => panic!("gai background task failed: {:?}", join_err),
        })
    }
}

impl fmt::Debug for GaiFuture {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("GaiFuture")
    }
}

impl Iterator for GaiAddrs {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|sa| sa.ip())
    }
}

impl fmt::Debug for GaiAddrs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("GaiAddrs")
    }
}

pub(super) struct IpAddrs {
    iter: vec::IntoIter<SocketAddr>,
}

impl IpAddrs {
    pub(super) fn new(addrs: Vec<SocketAddr>) -> Self {
        IpAddrs {
            iter: addrs.into_iter(),
        }
    }

    pub(super) fn try_parse(host: &str, port: u16) -> Option<IpAddrs> {
        if let Ok(addr) = host.parse::<Ipv4Addr>() {
            let addr = SocketAddrV4::new(addr, port);
            return Some(IpAddrs {
                iter: vec![SocketAddr::V4(addr)].into_iter(),
            });
        }
        let host = host.trim_start_matches('[').trim_end_matches(']');
        if let Ok(addr) = host.parse::<Ipv6Addr>() {
            let addr = SocketAddrV6::new(addr, port, 0, 0);
            return Some(IpAddrs {
                iter: vec![SocketAddr::V6(addr)].into_iter(),
            });
        }
        None
    }

    pub(super) fn split_by_preference(self, local_addr: Option<IpAddr>) -> (IpAddrs, IpAddrs) {
        if let Some(local_addr) = local_addr {
            let preferred = self
                .iter
                .filter(|addr| addr.is_ipv6() == local_addr.is_ipv6())
                .collect();

            (IpAddrs::new(preferred), IpAddrs::new(vec![]))
        } else {
            let preferring_v6 = self
                .iter
                .as_slice()
                .first()
                .map(SocketAddr::is_ipv6)
                .unwrap_or(false);

            let (preferred, fallback) = self
                .iter
                .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);

            (IpAddrs::new(preferred), IpAddrs::new(fallback))
        }
    }

    pub(super) fn is_empty(&self) -> bool {
        self.iter.as_slice().is_empty()
    }

    pub(super) fn len(&self) -> usize {
        self.iter.as_slice().len()
    }
}

impl Iterator for IpAddrs {
    type Item = SocketAddr;
    #[inline]
    fn next(&mut self) -> Option<SocketAddr> {
        self.iter.next()
    }
}

/*
/// A resolver using `getaddrinfo` calls via the `tokio_executor::threadpool::blocking` API.
///
/// Unlike the `GaiResolver` this will not spawn dedicated threads, but only works when running on the
/// multi-threaded Tokio runtime.
#[cfg(feature = "runtime")]
#[derive(Clone, Debug)]
pub struct TokioThreadpoolGaiResolver(());

/// The future returned by `TokioThreadpoolGaiResolver`.
#[cfg(feature = "runtime")]
#[derive(Debug)]
pub struct TokioThreadpoolGaiFuture {
    name: Name,
}

#[cfg(feature = "runtime")]
impl TokioThreadpoolGaiResolver {
    /// Creates a new DNS resolver that will use tokio threadpool's blocking
    /// feature.
    ///
    /// **Requires** its futures to be run on the threadpool runtime.
    pub fn new() -> Self {
        TokioThreadpoolGaiResolver(())
    }
}

#[cfg(feature = "runtime")]
impl Service<Name> for TokioThreadpoolGaiResolver {
    type Response = GaiAddrs;
    type Error = io::Error;
    type Future = TokioThreadpoolGaiFuture;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, name: Name) -> Self::Future {
        TokioThreadpoolGaiFuture { name }
    }
}

#[cfg(feature = "runtime")]
impl Future for TokioThreadpoolGaiFuture {
    type Output = Result<GaiAddrs, io::Error>;

    fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        match ready!(tokio_executor::threadpool::blocking(|| (
            self.name.as_str(),
            0
        )
            .to_socket_addrs()))
        {
            Ok(Ok(iter)) => Poll::Ready(Ok(GaiAddrs {
                inner: IpAddrs { iter },
            })),
            Ok(Err(e)) => Poll::Ready(Err(e)),
            // a BlockingError, meaning not on a tokio_executor::threadpool :(
            Err(e) => Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, e))),
        }
    }
}
*/

mod sealed {
    use super::{IpAddr, Name};
    use crate::common::{task, Future, Poll};
    use tower_service::Service;

    // "Trait alias" for `Service<Name, Response = Addrs>`
    pub trait Resolve {
        type Addrs: Iterator<Item = IpAddr>;
        type Error: Into<Box<dyn std::error::Error + Send + Sync>>;
        type Future: Future<Output = Result<Self::Addrs, Self::Error>>;

        fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
        fn resolve(&mut self, name: Name) -> Self::Future;
    }

    impl<S> Resolve for S
    where
        S: Service<Name>,
        S::Response: Iterator<Item = IpAddr>,
        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
    {
        type Addrs = S::Response;
        type Error = S::Error;
        type Future = S::Future;

        fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
            Service::poll_ready(self, cx)
        }

        fn resolve(&mut self, name: Name) -> Self::Future {
            Service::call(self, name)
        }
    }
}

pub(crate) async fn resolve<R>(resolver: &mut R, name: Name) -> Result<R::Addrs, R::Error>
where
    R: Resolve,
{
    futures_util::future::poll_fn(|cx| resolver.poll_ready(cx)).await?;
    resolver.resolve(name).await
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::{Ipv4Addr, Ipv6Addr};

    #[test]
    fn test_ip_addrs_split_by_preference() {
        let v4_addr = (Ipv4Addr::new(127, 0, 0, 1), 80).into();
        let v6_addr = (Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 80).into();

        let (mut preferred, mut fallback) = IpAddrs {
            iter: vec![v4_addr, v6_addr].into_iter(),
        }
        .split_by_preference(None);
        assert!(preferred.next().unwrap().is_ipv4());
        assert!(fallback.next().unwrap().is_ipv6());

        let (mut preferred, mut fallback) = IpAddrs {
            iter: vec![v6_addr, v4_addr].into_iter(),
        }
        .split_by_preference(None);
        assert!(preferred.next().unwrap().is_ipv6());
        assert!(fallback.next().unwrap().is_ipv4());

        let (mut preferred, fallback) = IpAddrs {
            iter: vec![v4_addr, v6_addr].into_iter(),
        }
        .split_by_preference(Some(v4_addr.ip()));
        assert!(preferred.next().unwrap().is_ipv4());
        assert!(fallback.is_empty());

        let (mut preferred, fallback) = IpAddrs {
            iter: vec![v4_addr, v6_addr].into_iter(),
        }
        .split_by_preference(Some(v6_addr.ip()));
        assert!(preferred.next().unwrap().is_ipv6());
        assert!(fallback.is_empty());
    }

    #[test]
    fn test_name_from_str() {
        const DOMAIN: &str = "test.example.com";
        let name = Name::from_str(DOMAIN).expect("Should be a valid domain");
        assert_eq!(name.as_str(), DOMAIN);
        assert_eq!(name.to_string(), DOMAIN);
    }

    #[test]
    fn ip_addrs_try_parse_v6() {
        let dst = ::http::Uri::from_static("http://[::1]:8080/");

        let mut addrs =
            IpAddrs::try_parse(dst.host().expect("host"), dst.port_u16().expect("port"))
                .expect("try_parse");

        let expected = "[::1]:8080".parse::<SocketAddr>().expect("expected");

        assert_eq!(addrs.next(), Some(expected));
    }
}
<commit_msg>fix(client): don't panic in DNS resolution when task cancelled (#2229)<commit_after>//! DNS Resolution used by the `HttpConnector`.
//!
//! This module contains:
//!
//! - A [`GaiResolver`](GaiResolver) that is the default resolver for the
//!   `HttpConnector`.
//! - The `Name` type used as an argument to custom resolvers.
//!
//! # Resolvers are `Service`s
//!
//! A resolver is just a
//! `Service<Name, Response = impl Iterator<Item = IpAddr>>`.
//!
//! A simple resolver that ignores the name and always returns a specific
//! address:
//!
//! ```rust,ignore
//! use std::{convert::Infallible, iter, net::IpAddr};
//!
//! let resolver = tower::service_fn(|_name| async {
//!     Ok::<_, Infallible>(iter::once(IpAddr::from([127, 0, 0, 1])))
//! });
//! ```
use std::error::Error;
use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
use std::pin::Pin;
use std::str::FromStr;
use std::task::{self, Poll};
use std::{fmt, io, vec};

use tokio::task::JoinHandle;
use tower_service::Service;

pub(super) use self::sealed::Resolve;

/// A domain name to resolve into IP addresses.
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct Name {
    host: String,
}

/// A resolver using blocking `getaddrinfo` calls in a threadpool.
#[derive(Clone)]
pub struct GaiResolver {
    _priv: (),
}

/// An iterator of IP addresses returned from `getaddrinfo`.
pub struct GaiAddrs {
    inner: IpAddrs,
}

/// A future to resolve a name returned by `GaiResolver`.
pub struct GaiFuture {
    inner: JoinHandle<Result<IpAddrs, io::Error>>,
}

impl Name {
    pub(super) fn new(host: String) -> Name {
        Name { host }
    }

    /// View the hostname as a string slice.
    pub fn as_str(&self) -> &str {
        &self.host
    }
}

impl fmt::Debug for Name {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.host, f)
    }
}

impl fmt::Display for Name {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.host, f)
    }
}

impl FromStr for Name {
    type Err = InvalidNameError;

    fn from_str(host: &str) -> Result<Self, Self::Err> {
        // Possibly add validation later
        Ok(Name::new(host.to_owned()))
    }
}

/// Error indicating a given string was not a valid domain name.
#[derive(Debug)]
pub struct InvalidNameError(());

impl fmt::Display for InvalidNameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Not a valid domain name")
    }
}

impl Error for InvalidNameError {}

impl GaiResolver {
    /// Construct a new `GaiResolver`.
    pub fn new() -> Self {
        GaiResolver { _priv: () }
    }
}

impl Service<Name> for GaiResolver {
    type Response = GaiAddrs;
    type Error = io::Error;
    type Future = GaiFuture;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, name: Name) -> Self::Future {
        let blocking = tokio::task::spawn_blocking(move || {
            debug!("resolving host={:?}", name.host);
            (&*name.host, 0)
                .to_socket_addrs()
                .map(|i| IpAddrs { iter: i })
        });

        GaiFuture { inner: blocking }
    }
}

impl fmt::Debug for GaiResolver {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("GaiResolver")
    }
}

impl Future for GaiFuture {
    type Output = Result<GaiAddrs, io::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        Pin::new(&mut self.inner).poll(cx).map(|res| match res {
            Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
            Ok(Err(err)) => Err(err),
            Err(join_err) => {
                if join_err.is_cancelled() {
                    Err(io::Error::new(io::ErrorKind::Interrupted, join_err))
                } else {
                    panic!("gai background task failed: {:?}", join_err)
                }
            }
        })
    }
}

impl fmt::Debug for GaiFuture {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("GaiFuture")
    }
}

impl Iterator for GaiAddrs {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|sa| sa.ip())
    }
}

impl fmt::Debug for GaiAddrs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("GaiAddrs")
    }
}

pub(super) struct IpAddrs {
    iter: vec::IntoIter<SocketAddr>,
}

impl IpAddrs {
    pub(super) fn new(addrs: Vec<SocketAddr>) -> Self {
        IpAddrs {
            iter: addrs.into_iter(),
        }
    }

    pub(super) fn try_parse(host: &str, port: u16) -> Option<IpAddrs> {
        if let Ok(addr) = host.parse::<Ipv4Addr>() {
            let addr = SocketAddrV4::new(addr, port);
            return Some(IpAddrs {
                iter: vec![SocketAddr::V4(addr)].into_iter(),
            });
        }
        let host = host.trim_start_matches('[').trim_end_matches(']');
        if let Ok(addr) = host.parse::<Ipv6Addr>() {
            let addr = SocketAddrV6::new(addr, port, 0, 0);
            return Some(IpAddrs {
                iter: vec![SocketAddr::V6(addr)].into_iter(),
            });
        }
        None
    }

    pub(super) fn split_by_preference(self, local_addr: Option<IpAddr>) -> (IpAddrs, IpAddrs) {
        if let Some(local_addr) = local_addr {
            let preferred = self
                .iter
                .filter(|addr| addr.is_ipv6() == local_addr.is_ipv6())
                .collect();

            (IpAddrs::new(preferred), IpAddrs::new(vec![]))
        } else {
            let preferring_v6 = self
                .iter
                .as_slice()
                .first()
                .map(SocketAddr::is_ipv6)
                .unwrap_or(false);

            let (preferred, fallback) = self
                .iter
                .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);

            (IpAddrs::new(preferred), IpAddrs::new(fallback))
        }
    }

    pub(super) fn is_empty(&self) -> bool {
        self.iter.as_slice().is_empty()
    }

    pub(super) fn len(&self) -> usize {
        self.iter.as_slice().len()
    }
}

impl Iterator for IpAddrs {
    type Item = SocketAddr;
    #[inline]
    fn next(&mut self) -> Option<SocketAddr> {
        self.iter.next()
    }
}

/*
/// A resolver using `getaddrinfo` calls via the `tokio_executor::threadpool::blocking` API.
///
/// Unlike the `GaiResolver` this will not spawn dedicated threads, but only works when running on the
/// multi-threaded Tokio runtime.
#[cfg(feature = "runtime")]
#[derive(Clone, Debug)]
pub struct TokioThreadpoolGaiResolver(());

/// The future returned by `TokioThreadpoolGaiResolver`.
#[cfg(feature = "runtime")]
#[derive(Debug)]
pub struct TokioThreadpoolGaiFuture {
    name: Name,
}

#[cfg(feature = "runtime")]
impl TokioThreadpoolGaiResolver {
    /// Creates a new DNS resolver that will use tokio threadpool's blocking
    /// feature.
    ///
    /// **Requires** its futures to be run on the threadpool runtime.
    pub fn new() -> Self {
        TokioThreadpoolGaiResolver(())
    }
}

#[cfg(feature = "runtime")]
impl Service<Name> for TokioThreadpoolGaiResolver {
    type Response = GaiAddrs;
    type Error = io::Error;
    type Future = TokioThreadpoolGaiFuture;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, name: Name) -> Self::Future {
        TokioThreadpoolGaiFuture { name }
    }
}

#[cfg(feature = "runtime")]
impl Future for TokioThreadpoolGaiFuture {
    type Output = Result<GaiAddrs, io::Error>;

    fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        match ready!(tokio_executor::threadpool::blocking(|| (
            self.name.as_str(),
            0
        )
            .to_socket_addrs()))
        {
            Ok(Ok(iter)) => Poll::Ready(Ok(GaiAddrs {
                inner: IpAddrs { iter },
            })),
            Ok(Err(e)) => Poll::Ready(Err(e)),
            // a BlockingError, meaning not on a tokio_executor::threadpool :(
            Err(e) => Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, e))),
        }
    }
}
*/

mod sealed {
    use super::{IpAddr, Name};
    use crate::common::{task, Future, Poll};
    use tower_service::Service;

    // "Trait alias" for `Service<Name, Response = Addrs>`
    pub trait Resolve {
        type Addrs: Iterator<Item = IpAddr>;
        type Error: Into<Box<dyn std::error::Error + Send + Sync>>;
        type Future: Future<Output = Result<Self::Addrs, Self::Error>>;

        fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
        fn resolve(&mut self, name: Name) -> Self::Future;
    }

    impl<S> Resolve for S
    where
        S: Service<Name>,
        S::Response: Iterator<Item = IpAddr>,
        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
    {
        type Addrs = S::Response;
        type Error = S::Error;
        type Future = S::Future;

        fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
            Service::poll_ready(self, cx)
        }

        fn resolve(&mut self, name: Name) -> Self::Future {
            Service::call(self, name)
        }
    }
}

pub(crate) async fn resolve<R>(resolver: &mut R, name: Name) -> Result<R::Addrs, R::Error>
where
    R: Resolve,
{
    futures_util::future::poll_fn(|cx| resolver.poll_ready(cx)).await?;
    resolver.resolve(name).await
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::{Ipv4Addr, Ipv6Addr};

    #[test]
    fn test_ip_addrs_split_by_preference() {
        let v4_addr = (Ipv4Addr::new(127, 0, 0, 1), 80).into();
        let v6_addr = (Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 80).into();

        let (mut preferred, mut fallback) = IpAddrs {
            iter: vec![v4_addr, v6_addr].into_iter(),
        }
        .split_by_preference(None);
        assert!(preferred.next().unwrap().is_ipv4());
        assert!(fallback.next().unwrap().is_ipv6());

        let (mut preferred, mut fallback) = IpAddrs {
            iter: vec![v6_addr, v4_addr].into_iter(),
        }
        .split_by_preference(None);
        assert!(preferred.next().unwrap().is_ipv6());
        assert!(fallback.next().unwrap().is_ipv4());

        let (mut preferred, fallback) = IpAddrs {
            iter: vec![v4_addr, v6_addr].into_iter(),
        }
        .split_by_preference(Some(v4_addr.ip()));
        assert!(preferred.next().unwrap().is_ipv4());
        assert!(fallback.is_empty());

        let (mut preferred, fallback) = IpAddrs {
            iter: vec![v4_addr, v6_addr].into_iter(),
        }
        .split_by_preference(Some(v6_addr.ip()));
        assert!(preferred.next().unwrap().is_ipv6());
        assert!(fallback.is_empty());
    }

    #[test]
    fn test_name_from_str() {
        const DOMAIN: &str = "test.example.com";
        let name = Name::from_str(DOMAIN).expect("Should be a valid domain");
        assert_eq!(name.as_str(), DOMAIN);
        assert_eq!(name.to_string(), DOMAIN);
    }

    #[test]
    fn ip_addrs_try_parse_v6() {
        let dst = ::http::Uri::from_static("http://[::1]:8080/");

        let mut addrs =
            IpAddrs::try_parse(dst.host().expect("host"), dst.port_u16().expect("port"))
                .expect("try_parse");

        let expected = "[::1]:8080".parse::<SocketAddr>().expect("expected");

        assert_eq!(addrs.next(), Some(expected));
    }
}
<|endoftext|>


<commit_before>use crate::bytes_deque::buf_vec_deque::BufVecDeque;
use crate::solicit::frame::FrameHeaderBuffer;
use bytes::Buf;
use bytes::Bytes;
use std::io::Cursor;
use std::io::IoSlice;
use std::mem;

enum Item {
    Vec(Cursor<Vec<u8>>),
    FrameHeaderBuffer(Cursor<FrameHeaderBuffer>),
}

impl Buf for Item {
    fn remaining(&self) -> usize {
        match self {
            Item::Vec(v) => v.remaining(),
            Item::FrameHeaderBuffer(c) => c.remaining(),
        }
    }

    fn bytes(&self) -> &[u8] {
        match self {
            Item::Vec(v) => v.bytes(),
            Item::FrameHeaderBuffer(c) => c.bytes(),
        }
    }

    fn advance(&mut self, cnt: usize) {
        match self {
            Item::Vec(v) => v.advance(cnt),
            Item::FrameHeaderBuffer(v) => v.advance(cnt),
        }
    }
}

#[derive(Default)]
pub struct WriteBuffer {
    deque: BufVecDeque<Item>,
}

impl Buf for WriteBuffer {
    /// Size of data in the buffer
    fn remaining(&self) -> usize {
        self.deque.remaining()
    }

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

    fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
        self.deque.bytes_vectored(dst)
    }

    fn advance(&mut self, cnt: usize) {
        self.deque.advance(cnt)
    }
}

impl WriteBuffer {
    pub fn new() -> WriteBuffer {
        Default::default()
    }

    pub fn extend_from_slice(&mut self, data: &[u8]) {
        self.tail_vec().extend_from_slice(data);
    }

    pub fn extend_from_vec(&mut self, data: Vec<u8>) {
        self.extend_from_slice(&data);
    }

    pub fn extend_from_bytes(&mut self, data: Bytes) {
        self.extend_from_slice(&data);
    }

    pub fn extend_from_bytes_ref(&mut self, data: &Bytes) {
        self.extend_from_slice(&*data);
    }

    pub fn extend_frame_header_buffer(&mut self, buffer: FrameHeaderBuffer) {
        self.deque
            .push_back(Item::FrameHeaderBuffer(Cursor::new(buffer)));
    }

    pub fn tail_vec(&mut self) -> WriteBufferTailVec {
        match self.deque.pop_back() {
            Some(Item::Vec(cursor)) => WriteBufferTailVec {
                write_buffer: self,
                position: cursor.position() as usize,
                data: cursor.into_inner(),
            },
            o => {
                if let Some(v) = o {
                    self.deque.push_back(v);
                }
                WriteBufferTailVec {
                    write_buffer: self,
                    data: Vec::new(),
                    position: 0,
                }
            }
        }
    }
}

impl Into<Vec<u8>> for WriteBuffer {
    fn into(mut self) -> Vec<u8> {
        let mut v = Vec::with_capacity(self.remaining());
        while self.has_remaining() {
            let bytes = self.bytes();
            v.extend_from_slice(bytes);
            self.advance(bytes.len());
        }
        v
    }
}

impl Into<Bytes> for WriteBuffer {
    fn into(self) -> Bytes {
        Bytes::from(Into::<Vec<u8>>::into(self))
    }
}

pub struct WriteBufferTailVec<'a> {
    write_buffer: &'a mut WriteBuffer,
    data: Vec<u8>,
    position: usize,
}

impl<'a> Drop for WriteBufferTailVec<'a> {
    fn drop(&mut self) {
        let mut cursor = Cursor::new(mem::take(&mut self.data));
        cursor.set_position(self.position as u64);
        self.write_buffer.deque.push_back(Item::Vec(cursor))
    }
}

impl<'a> WriteBufferTailVec<'a> {
    /// Size of data in the buffer
    pub fn remaining(&self) -> usize {
        debug_assert!(self.position <= self.data.len());
        self.data.len() - self.position
    }

    /// Pos is relative to "data"
    pub fn patch_buf(&mut self, pos: usize, data: &[u8]) {
        let patch_pos = self.position + pos;
        (&mut self.data[patch_pos..patch_pos + data.len()]).copy_from_slice(data);
    }

    pub fn extend_from_slice(&mut self, data: &[u8]) {
        // Could do something smarter
        self.reserve(data.len());
        self.data.extend_from_slice(data);
    }

    pub fn reserve(&mut self, additional: usize) {
        if self.remaining() >= additional {
            return;
        }
        self.compact();
        self.data.reserve(additional);
    }

    pub fn compact(&mut self) {
        self.data.drain(..self.position);
        self.position = 0;
    }
}

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

    #[test]
    fn remaining() {
        let mut buf = WriteBuffer::new();
        buf.extend_from_slice(b"abcd");
        assert_eq!(4, buf.remaining());

        assert_eq!(b'a', buf.get_u8());
        assert_eq!(b'b', buf.get_u8());
        assert_eq!(2, buf.remaining());

        buf.extend_from_slice(b"ef");
        assert_eq!(b'c', buf.get_u8());
        assert_eq!(b'd', buf.get_u8());
        assert_eq!(b'e', buf.get_u8());
        assert_eq!(b'f', buf.get_u8());
        assert_eq!(0, buf.remaining());
    }
}
<commit_msg>Write Bytes objects without allocation<commit_after>use crate::bytes_deque::buf_vec_deque::BufVecDeque;
use crate::solicit::frame::FrameHeaderBuffer;
use bytes::Buf;
use bytes::Bytes;
use std::io::Cursor;
use std::io::IoSlice;
use std::mem;

enum Item {
    Vec(Cursor<Vec<u8>>),
    Bytes(Bytes),
    FrameHeaderBuffer(Cursor<FrameHeaderBuffer>),
}

impl Buf for Item {
    fn remaining(&self) -> usize {
        match self {
            Item::Vec(v) => v.remaining(),
            Item::Bytes(b) => b.remaining(),
            Item::FrameHeaderBuffer(c) => c.remaining(),
        }
    }

    fn bytes(&self) -> &[u8] {
        match self {
            Item::Vec(v) => v.bytes(),
            Item::Bytes(b) => b.bytes(),
            Item::FrameHeaderBuffer(c) => c.bytes(),
        }
    }

    fn advance(&mut self, cnt: usize) {
        match self {
            Item::Vec(v) => v.advance(cnt),
            Item::Bytes(b) => b.advance(cnt),
            Item::FrameHeaderBuffer(v) => v.advance(cnt),
        }
    }
}

#[derive(Default)]
pub struct WriteBuffer {
    deque: BufVecDeque<Item>,
}

impl Buf for WriteBuffer {
    /// Size of data in the buffer
    fn remaining(&self) -> usize {
        self.deque.remaining()
    }

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

    fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
        self.deque.bytes_vectored(dst)
    }

    fn advance(&mut self, cnt: usize) {
        self.deque.advance(cnt)
    }
}

impl WriteBuffer {
    pub fn new() -> WriteBuffer {
        Default::default()
    }

    pub fn extend_from_slice(&mut self, data: &[u8]) {
        self.tail_vec().extend_from_slice(data);
    }

    pub fn extend_from_bytes(&mut self, data: Bytes) {
        if data.is_empty() {
            return;
        }
        self.deque.push_back(Item::Bytes(data));
    }

    pub fn extend_frame_header_buffer(&mut self, buffer: FrameHeaderBuffer) {
        self.deque
            .push_back(Item::FrameHeaderBuffer(Cursor::new(buffer)));
    }

    pub fn tail_vec(&mut self) -> WriteBufferTailVec {
        match self.deque.pop_back() {
            Some(Item::Vec(cursor)) => WriteBufferTailVec {
                write_buffer: self,
                position: cursor.position() as usize,
                data: cursor.into_inner(),
            },
            o => {
                if let Some(v) = o {
                    self.deque.push_back(v);
                }
                WriteBufferTailVec {
                    write_buffer: self,
                    data: Vec::new(),
                    position: 0,
                }
            }
        }
    }
}

impl Into<Vec<u8>> for WriteBuffer {
    fn into(mut self) -> Vec<u8> {
        let mut v = Vec::with_capacity(self.remaining());
        while self.has_remaining() {
            let bytes = self.bytes();
            v.extend_from_slice(bytes);
            self.advance(bytes.len());
        }
        v
    }
}

impl Into<Bytes> for WriteBuffer {
    fn into(self) -> Bytes {
        Bytes::from(Into::<Vec<u8>>::into(self))
    }
}

pub struct WriteBufferTailVec<'a> {
    write_buffer: &'a mut WriteBuffer,
    data: Vec<u8>,
    position: usize,
}

impl<'a> Drop for WriteBufferTailVec<'a> {
    fn drop(&mut self) {
        let mut cursor = Cursor::new(mem::take(&mut self.data));
        cursor.set_position(self.position as u64);
        self.write_buffer.deque.push_back(Item::Vec(cursor))
    }
}

impl<'a> WriteBufferTailVec<'a> {
    /// Size of data in the buffer
    pub fn remaining(&self) -> usize {
        debug_assert!(self.position <= self.data.len());
        self.data.len() - self.position
    }

    /// Pos is relative to "data"
    pub fn patch_buf(&mut self, pos: usize, data: &[u8]) {
        let patch_pos = self.position + pos;
        (&mut self.data[patch_pos..patch_pos + data.len()]).copy_from_slice(data);
    }

    pub fn extend_from_slice(&mut self, data: &[u8]) {
        // Could do something smarter
        self.reserve(data.len());
        self.data.extend_from_slice(data);
    }

    pub fn reserve(&mut self, additional: usize) {
        if self.remaining() >= additional {
            return;
        }
        self.compact();
        self.data.reserve(additional);
    }

    pub fn compact(&mut self) {
        self.data.drain(..self.position);
        self.position = 0;
    }
}

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

    #[test]
    fn remaining() {
        let mut buf = WriteBuffer::new();
        buf.extend_from_slice(b"abcd");
        assert_eq!(4, buf.remaining());

        assert_eq!(b'a', buf.get_u8());
        assert_eq!(b'b', buf.get_u8());
        assert_eq!(2, buf.remaining());

        buf.extend_from_slice(b"ef");
        assert_eq!(b'c', buf.get_u8());
        assert_eq!(b'd', buf.get_u8());
        assert_eq!(b'e', buf.get_u8());
        assert_eq!(b'f', buf.get_u8());
        assert_eq!(0, buf.remaining());
    }
}
<|endoftext|>


<commit_before>use regex::{Captures, Regex};
use analysis::namespaces::MAIN;
use env::Env;

const LANGUAGE_SEP_BEGIN : &'static str = "<!-- language=\"";
const LANGUAGE_SEP_END : &'static str = "\" -->";
const LANGUAGE_BLOCK_BEGIN : &'static str = "|[";
const LANGUAGE_BLOCK_END : &'static str = "\n]|";

pub fn reformat_doc(input: &str, env: &Env) -> String {
    code_blocks_transformation(input, env)
}

fn try_split<'a>(src: &'a str, needle: &str) -> (&'a str, Option<&'a str>) {
    match src.find(needle) {
        Some(pos) => (&src[..pos], Some(&src[pos + needle.len()..])),
        None => (src, None),
    }
}

fn code_blocks_transformation(mut input: &str,
                              env: &Env) -> String {
    let mut out = String::new();

    loop {
        input = match try_split(input, LANGUAGE_BLOCK_BEGIN) {
            (before, Some(after)) => {
                out.push_str(&replace_c_types(before, env));
                if let (before, Some(after)) = try_split(get_language(after, &mut out),
                                                         LANGUAGE_BLOCK_END) {
                    out.push_str(before);
                    out.push_str("\n```");
                    after
                } else {
                    after
                }
            }
            (before, None) => {
                out.push_str(&replace_c_types(before, env));
                return out
            }
        };
    }
}

fn get_language<'a>(entry: &'a str, out: &mut String) -> &'a str {
    if let (_, Some(after)) = try_split(entry, LANGUAGE_SEP_BEGIN) {
        if let (before, Some(after)) = try_split(after, LANGUAGE_SEP_END) {
            out.push_str(&format!("\n```{}", before));
            return after
        }
    }
    out.push_str("\n```text");
    entry
}

lazy_static! {
    static ref REG : Regex = Regex::new(r"#?(G[dt]k)([\w]+:?:?\.?[\w-]+)").unwrap();
    static ref REG2 : Regex = Regex::new(r"@(\w*)").unwrap();
}

fn replace_c_types(entry: &str, env: &Env) -> String {
    let out = &REG.replace_all(entry, |caps: &Captures| {
        let pos = env.library.find_namespace(&caps[1]).unwrap();
        if pos == MAIN {
            format!("`{}`", &caps[2])
        } else {
            format!("`{}::{}`", &env.namespaces[pos].crate_name, &caps[2])
        }
    });
    REG2.replace_all(out, "`$1`")
}
<commit_msg>Eat extra spaces to avoid triggering code blocks with four space ident<commit_after>use regex::{Captures, Regex};
use analysis::namespaces::MAIN;
use env::Env;

const LANGUAGE_SEP_BEGIN : &'static str = "<!-- language=\"";
const LANGUAGE_SEP_END : &'static str = "\" -->";
const LANGUAGE_BLOCK_BEGIN : &'static str = "|[";
const LANGUAGE_BLOCK_END : &'static str = "\n]|";

pub fn reformat_doc(input: &str, env: &Env) -> String {
    code_blocks_transformation(input, env)
}

fn try_split<'a>(src: &'a str, needle: &str) -> (&'a str, Option<&'a str>) {
    match src.find(needle) {
        Some(pos) => (&src[..pos], Some(&src[pos + needle.len()..])),
        None => (src, None),
    }
}

fn code_blocks_transformation(mut input: &str,
                              env: &Env) -> String {
    let mut out = String::new();

    loop {
        input = match try_split(input, LANGUAGE_BLOCK_BEGIN) {
            (before, Some(after)) => {
                out.push_str(&replace_c_types(before, env));
                if let (before, Some(after)) = try_split(get_language(after, &mut out),
                                                         LANGUAGE_BLOCK_END) {
                    out.push_str(before);
                    out.push_str("\n```");
                    after
                } else {
                    after
                }
            }
            (before, None) => {
                out.push_str(&replace_c_types(before, env));
                return out
            }
        };
    }
}

fn get_language<'a>(entry: &'a str, out: &mut String) -> &'a str {
    if let (_, Some(after)) = try_split(entry, LANGUAGE_SEP_BEGIN) {
        if let (before, Some(after)) = try_split(after, LANGUAGE_SEP_END) {
            out.push_str(&format!("\n```{}", before));
            return after
        }
    }
    out.push_str("\n```text");
    entry
}

lazy_static! {
    static ref REG : Regex = Regex::new(r"#?(G[dt]k)([\w]+:?:?\.?[\w-]+)").unwrap();
    static ref REG2 : Regex = Regex::new(r"@(\w*)").unwrap();
    static ref SPACES: Regex = Regex::new(r"[ ][ ]+").unwrap();
}

fn replace_c_types(entry: &str, env: &Env) -> String {
    let out = &REG.replace_all(entry, |caps: &Captures| {
        let pos = env.library.find_namespace(&caps[1]).unwrap();
        if pos == MAIN {
            format!("`{}`", &caps[2])
        } else {
            format!("`{}::{}`", &env.namespaces[pos].crate_name, &caps[2])
        }
    });
    let out = REG2.replace_all(&out, "`$1`");
    SPACES.replace_all(&out, " ")
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::sync::Arc;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;

use futures::task;
use futures::task::Task;

use super::atomic_box_option::AtomicBoxOption;

use futures::Async;

use super::waiters::*;

struct ConnOutWindowShared {
    window_size: AtomicIsize,
}

struct StreamWindowShared {
    conn: Arc<ConnOutWindowShared>,
    task: AtomicBoxOption<Task>,
    window_size: AtomicIsize,
}

pub struct ConnOutWindowSender {
    waker: Waker,
    shared: Arc<ConnOutWindowShared>,
}

struct ConnOutWindowReceiver {
    shared: Arc<ConnOutWindowShared>,
}

pub struct StreamOutWindowSender {
    shared: Arc<StreamWindowShared>,
}

pub struct StreamOutWindowReceiver {
    conn_waiter: Waiter,
    shared: Arc<StreamWindowShared>,
}

impl ConnOutWindowSender {
    pub fn new(size: u32) -> ConnOutWindowSender {
        ConnOutWindowSender {
            waker: Waker::new(),
            shared: Arc::new(ConnOutWindowShared {
                window_size: AtomicIsize::new(size as isize),
            }),
        }
    }

    pub fn new_stream(&self, initial: u32) -> (StreamOutWindowSender, StreamOutWindowReceiver) {
        let shared = Arc::new(StreamWindowShared {
            conn: self.shared.clone(),
            window_size: AtomicIsize::new(initial as isize),
            task: AtomicBoxOption::new(),
        });

        let sender = StreamOutWindowSender {
            shared: shared.clone(),
        };
        let receiver = StreamOutWindowReceiver {
            conn_waiter: self.waker.new_waiter(),
            shared: shared,
        };
        (sender, receiver)
    }

    pub fn increase(&self, size: u32) {
        let old_size = self.shared.window_size.fetch_add(size as isize, Ordering::SeqCst) as i32;
        let new_size = old_size + size as i32;

        debug!("poll conn window size {} -> {}", old_size, new_size);

        if new_size >= 0 {
            self.waker.wake_all();
        }
    }
}

impl StreamOutWindowSender {
    pub fn increase(&self, size: i32) {
        let old_size = self.shared.window_size.fetch_add(size as isize, Ordering::SeqCst) as i32;
        let new_size = old_size + size;
        debug!("poll window size {} -> {}", old_size, new_size);
        if new_size >= 0 {
            if let Some(task) = self.shared.task.swap_null(Ordering::SeqCst) {
                warn!("notify");
                task.notify();
            }
        }
    }
}

impl StreamOutWindowReceiver {
    pub fn decrease(&self, size: u32) {
        self.shared.conn.window_size.fetch_sub(size as isize, Ordering::SeqCst);
        self.shared.window_size.fetch_sub(size as isize, Ordering::SeqCst);
    }

    fn poll_conn(&self) -> Async<()> {
        if self.shared.conn.window_size.load(Ordering::SeqCst) >= 0 {
            return Async::Ready(());
        }

        self.conn_waiter.park();

        if self.shared.conn.window_size.load(Ordering::SeqCst) >= 0 {
            Async::Ready(())
        } else {
            Async::NotReady
        }
    }

    pub fn poll(&self) -> Async<()> {
        if self.shared.window_size.load(Ordering::SeqCst) < 0 {

            self.shared.task.store_box(Box::new(task::current()), Ordering::SeqCst);

            if self.shared.window_size.load(Ordering::SeqCst) < 0 {
                return Async::NotReady;
            }
        }

        self.poll_conn()
    }
}
<commit_msg>Accidental noise<commit_after>#![allow(dead_code)]

use std::sync::Arc;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;

use futures::task;
use futures::task::Task;

use super::atomic_box_option::AtomicBoxOption;

use futures::Async;

use super::waiters::*;

struct ConnOutWindowShared {
    window_size: AtomicIsize,
}

struct StreamWindowShared {
    conn: Arc<ConnOutWindowShared>,
    task: AtomicBoxOption<Task>,
    window_size: AtomicIsize,
}

pub struct ConnOutWindowSender {
    waker: Waker,
    shared: Arc<ConnOutWindowShared>,
}

struct ConnOutWindowReceiver {
    shared: Arc<ConnOutWindowShared>,
}

pub struct StreamOutWindowSender {
    shared: Arc<StreamWindowShared>,
}

pub struct StreamOutWindowReceiver {
    conn_waiter: Waiter,
    shared: Arc<StreamWindowShared>,
}

impl ConnOutWindowSender {
    pub fn new(size: u32) -> ConnOutWindowSender {
        ConnOutWindowSender {
            waker: Waker::new(),
            shared: Arc::new(ConnOutWindowShared {
                window_size: AtomicIsize::new(size as isize),
            }),
        }
    }

    pub fn new_stream(&self, initial: u32) -> (StreamOutWindowSender, StreamOutWindowReceiver) {
        let shared = Arc::new(StreamWindowShared {
            conn: self.shared.clone(),
            window_size: AtomicIsize::new(initial as isize),
            task: AtomicBoxOption::new(),
        });

        let sender = StreamOutWindowSender {
            shared: shared.clone(),
        };
        let receiver = StreamOutWindowReceiver {
            conn_waiter: self.waker.new_waiter(),
            shared: shared,
        };
        (sender, receiver)
    }

    pub fn increase(&self, size: u32) {
        let old_size = self.shared.window_size.fetch_add(size as isize, Ordering::SeqCst) as i32;
        let new_size = old_size + size as i32;

        if new_size >= 0 {
            self.waker.wake_all();
        }
    }
}

impl StreamOutWindowSender {
    pub fn increase(&self, size: i32) {
        let old_size = self.shared.window_size.fetch_add(size as isize, Ordering::SeqCst) as i32;
        let new_size = old_size + size;
        if new_size >= 0 {
            if let Some(task) = self.shared.task.swap_null(Ordering::SeqCst) {
                task.notify();
            }
        }
    }
}

impl StreamOutWindowReceiver {
    pub fn decrease(&self, size: u32) {
        self.shared.conn.window_size.fetch_sub(size as isize, Ordering::SeqCst);
        self.shared.window_size.fetch_sub(size as isize, Ordering::SeqCst);
    }

    fn poll_conn(&self) -> Async<()> {
        if self.shared.conn.window_size.load(Ordering::SeqCst) >= 0 {
            return Async::Ready(());
        }

        self.conn_waiter.park();

        if self.shared.conn.window_size.load(Ordering::SeqCst) >= 0 {
            Async::Ready(())
        } else {
            Async::NotReady
        }
    }

    pub fn poll(&self) -> Async<()> {
        if self.shared.window_size.load(Ordering::SeqCst) < 0 {

            self.shared.task.store_box(Box::new(task::current()), Ordering::SeqCst);

            if self.shared.window_size.load(Ordering::SeqCst) < 0 {
                return Async::NotReady;
            }
        }

        self.poll_conn()
    }
}
<|endoftext|>


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

#![feature(issue_5723_bootstrap)]

trait Foo { }

fn foo<'a>(x: ~Foo:'a) {
}

fn bar<'a, T:'a>() {
}

pub fn main() { }
<commit_msg>Skip pretty printing for the regions bound test<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-pretty

#![feature(issue_5723_bootstrap)]

trait Foo { }

fn foo<'a>(x: ~Foo:'a) {
}

fn bar<'a, T:'a>() {
}

pub fn main() { }
<|endoftext|>


<commit_before>fn largest<T>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

struct Point<T> {
    x: T,
    y: T,
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<commit_msg>Define a method on struct that uses generics<commit_after>fn largest<T>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<|endoftext|>


<commit_before>use core::num::{ ToStrRadix };
use core::iterator::{ IteratorUtil };

use common::extiter::{ ExtIteratorUtil, Range };
use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 96,
    answer: "24702",
    solver: solve
};

static WIDTH: uint = 9;
static HEIGHT: uint = 9;

struct SuDoku {
    name: ~str,
    map: [[u16, .. WIDTH], .. HEIGHT]
}

impl TotalEq for SuDoku {
    #[inline(always)]
    fn equals(&self, other: &SuDoku) -> bool {
        self.name == other.name && Range::new(0, HEIGHT).all(|&y| self.map[y] == other.map[y])
    }
}

impl Eq for SuDoku {
    #[inline(always)]
    fn eq(&self, other: &SuDoku) -> bool { self.equals(other) }
    #[inline(always)]
    fn ne(&self, other: &SuDoku) -> bool { !self.equals(other) }
}

impl ToStr for SuDoku {
    fn to_str(&self) -> ~str {
        let rows = do self.map.map |row| {
            let cells = do row.map |&cell| {
                if cell.population_count() == 1 {
                    ~"_"
                } else {
                    (1u << cell.trailing_zeros()).to_str()
                }
            };
            str::concat(cells)
        };
        return self.name + "\n" + str::connect(rows, "\n");
    }
}

impl Clone for SuDoku {
    fn clone(&self) -> SuDoku {
        SuDoku { name: self.name.clone(), map: self.map }
    }
}

static MASK_ALL: u16 = 0x1ff;

impl SuDoku {
    fn get_num(&self, x: uint, y: uint) -> u16 {
        match self.map[y][x].population_count() {
            0 => -1,
            1 => self.map[y][x].trailing_zeros() + 1,
            _ => 0
        }
    }

    fn to_str_debug(&self) -> ~str {
        let row_strs = do vec::build_sized(HEIGHT) |push| {
            for uint::range(0, HEIGHT) |y| {
                let cell_strs = do vec::build_sized(WIDTH) |push| {
                    for uint::range(0, WIDTH) |x| {
                        let s = self.map[y][x].to_str_radix(2);
                        push(str::replace(fmt!("%s:%s",
                                               self.get_num(x, y).to_str(),
                                               str::repeat("0", 9 - s.len()) + s), "0", "_"));
                    }
                };
                push(str::connect(cell_strs, " "));
            }
        };
        return self.name + "\n" + str::connect(row_strs, "\n");
    }
}

fn read_sudoku<T: Reader>(r: T) -> SuDoku {
    let mut sudoku = SuDoku {
        name: r.read_line(),
        map: [[MASK_ALL, .. WIDTH], .. HEIGHT]
    };

    for uint::range(0, HEIGHT) |y| {
        let line = r.read_line();
        for uint::range(0, WIDTH) |x| {
            let n = char::to_digit(line[x] as char, 10).get();
            if n != 0 { sudoku.map[y][x] = 1 << (n - 1); }
        }
    }
    return sudoku;
}

fn solve_sudoku(mut puzzle: SuDoku) -> ~[SuDoku] {
    let mut answers = ~[];

    loop {
        let bkup = puzzle.clone();

        for uint::range(0, HEIGHT) |y| {
            for uint::range(0, WIDTH) |x| {
                if puzzle.map[y][x].population_count() != 1 { loop; }

                let bits = puzzle.map[y][x];
                for uint::range(0, WIDTH) |x2| {
                    if x2 != x { puzzle.map[y][x2] &= (!bits & MASK_ALL); }
                }
                for uint::range(0, HEIGHT) |y2| {
                    if y2 != y { puzzle.map[y2][x] &= (!bits & MASK_ALL); }
                }
                let x0 = x / 3 * 3, y0 = y / 3 * 3;
                for uint::range(x0, x0 + 3) |x2| {
                    for uint::range(y0, y0 + 3) |y2| {
                        if x2 != x && y2 != y { puzzle.map[y2][x2] &= (!bits & MASK_ALL); }
                    }
                }
            }
        }

        for uint::range(0, 9) |n| {
            let bit = 1 << n;

            for uint::range(0, HEIGHT) |y| {
                let it = Range::new(0, WIDTH).filter(|&x| puzzle.map[y][x] & bit != 0);
                if it.count_elem() != 1 { loop; }
                puzzle.map[y][it.first()] = bit;
            }

            for uint::range(0, WIDTH) |x| {
                let it = Range::new(0, HEIGHT).filter(|&y| puzzle.map[y][x] & bit != 0);
                if it.count_elem() != 1 { loop; }
                puzzle.map[it.first()][x] = bit;
            }

            for uint::range_step(0, HEIGHT, 3) |y0| {
                for uint::range_step(0, WIDTH, 3) |x0| {
                    let it = Range::new(0u, 3 * 3)
                        .transform(|i| (x0 + i % 3, y0 + i / 3))
                        .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                    if it.count_elem() != 1 { loop; }
                    let (x, y) = it.first();
                    puzzle.map[y][x] = bit;
                }
            }
        }

        if puzzle == bkup {
            let it = Range::new(0, HEIGHT * WIDTH)
                .transform(|i| (i % WIDTH, i / WIDTH))
                .transform(|(x, y)| (x, y, puzzle.map[y][x].population_count()));

            if it.any(|&(_x, _y, cnt)| cnt == 0) { return ~[]; }
            if it.all(|&(_x, _y, cnt)| cnt == 1) { answers.push(puzzle); break; }

            let (x, y, cnt) = it.filter(|&(_x, _y, cnt)| cnt > 1)
                .min_as(|&(_x, _y, cnt)| cnt);

            for uint::range(0, 9) |n| {
                let bit = 1 << n;
                if puzzle.map[y][x] & bit == 0 { loop; }
                let mut p2 = puzzle.clone();
                p2.map[y][x] = bit;
                answers.push_all(solve_sudoku(p2));
            }
            break;
        }
    }

    return answers;
}

fn solve() -> ~str {
    let result = io::file_reader(&Path("files/sudoku.txt")).map(|&file| {
        let mut puzzles = ~[];
        while !file.eof() { puzzles.push(read_sudoku(file)); }
        puzzles
    }).map(|&puzzles| {
        let mut answers = ~[];
        for puzzles.each |&p| {
            let mut ans = solve_sudoku(p);
            assert_eq!(ans.len(), 1);
            answers.push(ans.pop());
        }
        answers
    }).map(|&answers| {
        let mut sum = 0;
        for answers.each |ans| {
            sum += 100 * ans.get_num(0, 0) + 10 * ans.get_num(1, 0) + ans.get_num(2, 0);
        }
        sum
    });

    match result {
        Err(msg) => fail!(msg),
        Ok(value) => return value.to_str()
    }
}
<commit_msg>Refactor problem #96<commit_after>use core::num::{ ToStrRadix };
use core::iterator::{ IteratorUtil };

use common::extiter::{ ExtIteratorUtil, Range };
use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 96,
    answer: "24702",
    solver: solve
};

static BOARD_WIDTH: uint = 9;
static BOARD_HEIGHT: uint = 9;
static GROUP_WIDTH: uint = 3;
static GROUP_HEIGHT: uint = 3;
static MAX_NUMBER: uint = 9;
type BITS = u16;
static MASK_ALL: BITS = 0x1ff;

struct SuDoku {
    name: ~str,
    map: [[BITS, .. BOARD_WIDTH], .. BOARD_HEIGHT]
}

impl TotalEq for SuDoku {
    #[inline(always)]
    fn equals(&self, other: &SuDoku) -> bool {
        self.name == other.name && Range::new(0, BOARD_HEIGHT).all(|&y| self.map[y] == other.map[y])
    }
}

impl Eq for SuDoku {
    #[inline(always)]
    fn eq(&self, other: &SuDoku) -> bool { self.equals(other) }
    #[inline(always)]
    fn ne(&self, other: &SuDoku) -> bool { !self.equals(other) }
}

impl ToStr for SuDoku {
    fn to_str(&self) -> ~str {
        let rows = do self.map.map |row| {
            let cells = do row.map |&cell| {
                if cell.population_count() == 1 {
                    ~"_"
                } else {
                    (1u << cell.trailing_zeros()).to_str()
                }
            };
            str::concat(cells)
        };
        return self.name + "\n" + str::connect(rows, "\n");
    }
}

impl Clone for SuDoku {
    fn clone(&self) -> SuDoku {
        SuDoku { name: self.name.clone(), map: self.map }
    }
}

impl SuDoku {
    fn get_num(&self, x: uint, y: uint) -> BITS {
        match self.map[y][x].population_count() {
            0 => -1,
            1 => self.map[y][x].trailing_zeros() + 1,
            _ => 0
        }
    }

    fn to_str_debug(&self) -> ~str {
        let row_strs = do vec::build_sized(BOARD_HEIGHT) |push| {
            for uint::range(0, BOARD_HEIGHT) |y| {
                let cell_strs = do vec::build_sized(BOARD_WIDTH) |push| {
                    for uint::range(0, BOARD_WIDTH) |x| {
                        let s = self.map[y][x].to_str_radix(2);
                        push(str::replace(fmt!("%s:%s",
                                               self.get_num(x, y).to_str(),
                                               str::repeat("0", MAX_NUMBER - s.len()) + s), "0", "_"));
                    }
                };
                push(str::connect(cell_strs, " "));
            }
        };
        return self.name + "\n" + str::connect(row_strs, "\n");
    }
}

fn read_sudoku<T: Reader>(r: T) -> SuDoku {
    let mut sudoku = SuDoku {
        name: r.read_line(),
        map: [[MASK_ALL, .. BOARD_WIDTH], .. BOARD_HEIGHT]
    };

    for uint::range(0, BOARD_HEIGHT) |y| {
        let line = r.read_line();
        for uint::range(0, BOARD_WIDTH) |x| {
            let n = char::to_digit(line[x] as char, 10).get();
            if n != 0 { sudoku.map[y][x] = 1 << (n - 1); }
        }
    }
    return sudoku;
}

fn solve_sudoku(mut puzzle: SuDoku) -> ~[SuDoku] {
    let group_it = Range::new(0, GROUP_WIDTH * GROUP_HEIGHT)
        .transform(|i| (i % GROUP_WIDTH, i / GROUP_WIDTH));

    loop {
        let bkup = puzzle.clone();

        for uint::range(0, BOARD_HEIGHT) |y| {
            for uint::range(0, BOARD_WIDTH) |x| {
                if puzzle.map[y][x].population_count() != 1 { loop; }

                let x0 = x / GROUP_WIDTH * GROUP_WIDTH, y0 = y / GROUP_HEIGHT * GROUP_HEIGHT;
                let row = Range::new(0, BOARD_WIDTH).transform(|x| (x, y));
                let col = Range::new(0, BOARD_HEIGHT).transform(|y| (x, y));
                let grp = group_it.transform(|(dx, dy)| (x0 + dx, y0 + dy));

                let mut it = row.chain(col).chain(grp).filter(|&pos: &(uint, uint)| pos != (x, y));
                let mask = !puzzle.map[y][x] & MASK_ALL;
                for it.advance |(x, y)| { puzzle.map[y][x] &= mask; }
            }
        }

        for uint::range(0, MAX_NUMBER) |n| {
            let bit = 1 << n;

            for uint::range(0, BOARD_HEIGHT) |y| {
                let it = Range::new(0, BOARD_WIDTH).filter(|&x| puzzle.map[y][x] & bit != 0);
                if it.count_elem() != 1 { loop; }
                puzzle.map[y][it.first()] = bit;
            }

            for uint::range(0, BOARD_WIDTH) |x| {
                let it = Range::new(0, BOARD_HEIGHT).filter(|&y| puzzle.map[y][x] & bit != 0);
                if it.count_elem() != 1 { loop; }
                puzzle.map[it.first()][x] = bit;
            }

            for uint::range_step(0, BOARD_HEIGHT, GROUP_WIDTH as int) |y0| {
                for uint::range_step(0, BOARD_WIDTH, GROUP_HEIGHT as int) |x0| {
                    let it = group_it
                        .transform(|(dx, dy)| (x0 + dx, y0 + dy))
                        .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                    if it.count_elem() != 1 { loop; }
                    let (x, y) = it.first();
                    puzzle.map[y][x] = bit;
                }
            }
        }

        if puzzle == bkup { break; }
    }

    let it = Range::new(0, BOARD_HEIGHT * BOARD_WIDTH)
        .transform(|i| (i % BOARD_WIDTH, i / BOARD_WIDTH))
        .transform(|(x, y)| (x, y, puzzle.map[y][x].population_count()));

    if it.any(|&(_x, _y, cnt)| cnt == 0) { return ~[]; }
    if it.all(|&(_x, _y, cnt)| cnt == 1) { return ~[puzzle]; }

    let (x, y, _cnt) = it
        .filter(|&(_x, _y, cnt)| cnt > 1)
        .min_as(|&(_x, _y, cnt)| cnt);

    let mut answers = ~[];
    for uint::range(0, MAX_NUMBER) |n| {
        let bit = 1 << n;
        if puzzle.map[y][x] & bit == 0 { loop; }

        let mut p2 = puzzle.clone();
        p2.map[y][x] = bit;
        answers.push_all(solve_sudoku(p2));
    }

    return answers;
}

fn solve() -> ~str {
    let result = io::file_reader(&Path("files/sudoku.txt")).map(|&file| {
        let mut puzzles = ~[];
        while !file.eof() { puzzles.push(read_sudoku(file)); }
        puzzles
    }).map(|&puzzles| {
        let mut answers = ~[];
        for puzzles.each |&p| {
            let mut ans = solve_sudoku(p);
            assert_eq!(ans.len(), 1);
            answers.push(ans.pop());
        }
        answers
    }).map(|&answers| {
        let mut sum = 0;
        for answers.each |ans| {
            sum += 100 * ans.get_num(0, 0) + 10 * ans.get_num(1, 0) + ans.get_num(2, 0);
        }
        sum
    });

    match result {
        Err(msg) => fail!(msg),
        Ok(value) => return value.to_str()
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};
use std::str::FromStr;

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge<T> {
    count: usize,
    states: Vec<State<T>>,
}

impl<T: 'static + FromStr> Merge<T> {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let states = (0..count).map(|i| {
            let collection = Box::new(get_collection(filename, i).unwrap());
            State(collection, None)
        }).collect();
        Merge {
            count: count,
            states: states,
        }
    }
}

impl<T: 'static + PartialOrd + Copy> Iterator for Merge<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let mut min_index: Option<usize> = None;
            for i in 0..count {
                if let Some(val) = states[i].1 {
                    if let Some(m) = min_index {
                        let min = states[m].1.unwrap();
                        if val < min {
                            min_index.replace(i);
                        }
                    } else {
                        min_index.replace(i);
                    }
                }
            }
            if let Some(m) = min_index {
                return states[m].1.take();
            }
            return None;
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<T: FromStr>(filename: &str) -> io::Result<impl Iterator<Item = T>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<T: FromStr>(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = T>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers<T: FromStr>(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = T>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<T> {
        if let Ok(i) = v.parse::<T>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt").unwrap().collect::<Vec<u32>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator<T: PartialOrd>(
        iter1: &mut impl Iterator<Item = T>,
        iter2: &mut impl Iterator<Item = T>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<commit_msg>no loop needed in next<commit_after>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};
use std::str::FromStr;

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge<T> {
    count: usize,
    states: Vec<State<T>>,
}

impl<T: 'static + FromStr> Merge<T> {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let states = (0..count).map(|i| {
            let collection = Box::new(get_collection(filename, i).unwrap());
            State(collection, None)
        }).collect();
        Merge {
            count: count,
            states: states,
        }
    }
}

impl<T: 'static + PartialOrd + Copy> Iterator for Merge<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        for i in 0..count {
            let state = &mut states[i];
            if state.1.is_none() {
                state.1 = state.0.next();
            }
        }
        let mut min_index: Option<usize> = None;
        for i in 0..count {
            if let Some(val) = states[i].1 {
                if let Some(m) = min_index {
                    let min = states[m].1.unwrap();
                    if val < min {
                        min_index.replace(i);
                    }
                } else {
                    min_index.replace(i);
                }
            }
        }
        if let Some(m) = min_index {
            return states[m].1.take();
        }
        return None;
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<T: FromStr>(filename: &str) -> io::Result<impl Iterator<Item = T>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<T: FromStr>(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = T>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers<T: FromStr>(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = T>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<T> {
        if let Ok(i) = v.parse::<T>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt").unwrap().collect::<Vec<u32>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator<T: PartialOrd>(
        iter1: &mut impl Iterator<Item = T>,
        iter2: &mut impl Iterator<Item = T>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<|endoftext|>


<commit_before>use std::{
    convert::TryFrom,
    error::Error,
    fmt::{self, Display, Formatter},
};

use serde::{Deserialize, Serialize};

use super::{Action, ConditionalPushRule, PatternedPushRule, PushCondition, PushRule};

/// Like `PushRule`, but may represent any kind of push rule
/// thanks to `pattern` and `conditions` being optional.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AnyPushRule {
    /// The actions to perform when this rule is matched.
    pub actions: Vec<Action>,

    /// Whether this is a default rule, or has been set explicitly.
    pub default: bool,

    /// Whether the push rule is enabled or not.
    pub enabled: bool,

    /// The ID of this rule.
    pub rule_id: String,

    /// The conditions that must hold true for an event in order for a rule to be applied to an event. A rule with no conditions always matches.
    /// Only applicable to underride and override rules.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conditions: Option<Vec<PushCondition>>,

    /// The glob-style pattern to match against. Only applicable to content rules.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub pattern: Option<String>,
}

impl From<PushRule> for AnyPushRule {
    fn from(push_rule: PushRule) -> Self {
        let PushRule { actions, default, enabled, rule_id } = push_rule;
        AnyPushRule { actions, default, enabled, rule_id, pattern: None, conditions: None }
    }
}

impl From<PatternedPushRule> for AnyPushRule {
    fn from(push_rule: PatternedPushRule) -> Self {
        let PatternedPushRule { actions, default, enabled, rule_id, pattern } = push_rule;
        AnyPushRule { actions, default, enabled, rule_id, pattern: Some(pattern), conditions: None }
    }
}

impl From<ConditionalPushRule> for AnyPushRule {
    fn from(push_rule: ConditionalPushRule) -> Self {
        let ConditionalPushRule { actions, default, enabled, rule_id, conditions } = push_rule;
        AnyPushRule {
            actions,
            default,
            enabled,
            rule_id,
            pattern: None,
            conditions: Some(conditions),
        }
    }
}

impl From<AnyPushRule> for PushRule {
    fn from(push_rule: AnyPushRule) -> Self {
        let AnyPushRule { actions, default, enabled, rule_id, .. } = push_rule;
        PushRule { actions, default, enabled, rule_id }
    }
}

/// An error that happens when `AnyPushRule` cannot
/// be converted into `PatternedPushRule`
#[derive(Debug)]
pub struct MissingPatternError;

impl Display for MissingPatternError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Push rule does not have a pattern.")
    }
}

impl Error for MissingPatternError {}

impl TryFrom<AnyPushRule> for PatternedPushRule {
    type Error = MissingPatternError;

    fn try_from(push_rule: AnyPushRule) -> Result<Self, Self::Error> {
        if let AnyPushRule { actions, default, enabled, rule_id, pattern: Some(pattern), .. } =
            push_rule
        {
            Ok(PatternedPushRule { actions, default, enabled, rule_id, pattern })
        } else {
            Err(MissingPatternError)
        }
    }
}

/// An error that happens when `AnyPushRule` cannot
/// be converted into `ConditionalPushRule`
#[derive(Debug)]
pub struct MissingConditionsError;

impl Display for MissingConditionsError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Push rule has no conditions.")
    }
}

impl Error for MissingConditionsError {}

impl TryFrom<AnyPushRule> for ConditionalPushRule {
    type Error = MissingConditionsError;

    fn try_from(push_rule: AnyPushRule) -> Result<Self, Self::Error> {
        if let AnyPushRule {
            actions,
            default,
            enabled,
            rule_id,
            conditions: Some(conditions),
            ..
        } = push_rule
        {
            Ok(ConditionalPushRule { actions, default, enabled, rule_id, conditions })
        } else {
            Err(MissingConditionsError)
        }
    }
}
<commit_msg>ruma-common: Small refactorings in any_push_rule.rs<commit_after>use std::{
    convert::TryFrom,
    error::Error,
    fmt::{self, Display, Formatter},
};

use serde::{Deserialize, Serialize};

use super::{Action, ConditionalPushRule, PatternedPushRule, PushCondition, PushRule};

/// Like `PushRule`, but may represent any kind of push rule
/// thanks to `pattern` and `conditions` being optional.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AnyPushRule {
    /// The actions to perform when this rule is matched.
    pub actions: Vec<Action>,

    /// Whether this is a default rule, or has been set explicitly.
    pub default: bool,

    /// Whether the push rule is enabled or not.
    pub enabled: bool,

    /// The ID of this rule.
    pub rule_id: String,

    /// The conditions that must hold true for an event in order for a rule to be applied to an event. A rule with no conditions always matches.
    /// Only applicable to underride and override rules.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conditions: Option<Vec<PushCondition>>,

    /// The glob-style pattern to match against. Only applicable to content rules.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub pattern: Option<String>,
}

impl From<PushRule> for AnyPushRule {
    fn from(push_rule: PushRule) -> Self {
        let PushRule { actions, default, enabled, rule_id } = push_rule;
        Self { actions, default, enabled, rule_id, conditions: None, pattern: None }
    }
}

impl From<PatternedPushRule> for AnyPushRule {
    fn from(push_rule: PatternedPushRule) -> Self {
        let PatternedPushRule { actions, default, enabled, rule_id, pattern } = push_rule;
        Self { actions, default, enabled, rule_id, conditions: None, pattern: Some(pattern) }
    }
}

impl From<ConditionalPushRule> for AnyPushRule {
    fn from(push_rule: ConditionalPushRule) -> Self {
        let ConditionalPushRule { actions, default, enabled, rule_id, conditions } = push_rule;
        Self { actions, default, enabled, rule_id, conditions: Some(conditions), pattern: None }
    }
}

impl From<AnyPushRule> for PushRule {
    fn from(push_rule: AnyPushRule) -> Self {
        let AnyPushRule { actions, default, enabled, rule_id, .. } = push_rule;
        PushRule { actions, default, enabled, rule_id }
    }
}

/// An error that happens when `AnyPushRule` cannot
/// be converted into `PatternedPushRule`
#[derive(Debug)]
pub struct MissingPatternError;

impl Display for MissingPatternError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Push rule does not have a pattern.")
    }
}

impl Error for MissingPatternError {}

impl TryFrom<AnyPushRule> for PatternedPushRule {
    type Error = MissingPatternError;

    fn try_from(push_rule: AnyPushRule) -> Result<Self, Self::Error> {
        if let AnyPushRule { actions, default, enabled, rule_id, pattern: Some(pattern), .. } =
            push_rule
        {
            Ok(PatternedPushRule { actions, default, enabled, rule_id, pattern })
        } else {
            Err(MissingPatternError)
        }
    }
}

/// An error that happens when `AnyPushRule` cannot
/// be converted into `ConditionalPushRule`
#[derive(Debug)]
pub struct MissingConditionsError;

impl Display for MissingConditionsError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Push rule has no conditions.")
    }
}

impl Error for MissingConditionsError {}

impl TryFrom<AnyPushRule> for ConditionalPushRule {
    type Error = MissingConditionsError;

    fn try_from(push_rule: AnyPushRule) -> Result<Self, Self::Error> {
        if let AnyPushRule {
            actions,
            default,
            enabled,
            rule_id,
            conditions: Some(conditions),
            ..
        } = push_rule
        {
            Ok(ConditionalPushRule { actions, default, enabled, rule_id, conditions })
        } else {
            Err(MissingConditionsError)
        }
    }
}
<|endoftext|>


<commit_before>use hir::Semantics;
use ide_db::{
    defs::{Definition, NameClass, NameRefClass},
    RootDatabase,
};
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, T};

use crate::{FilePosition, NavigationTarget, RangeInfo};

// Feature: Go to Declaration
//
// Navigates to the declaration of an identifier.
//
// This is currently the same as `Go to Definition` with the exception of outline modules where it
// will navigate to the `mod name;` item declaration.
pub(crate) fn goto_declaration(
    db: &RootDatabase,
    position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
    let sema = Semantics::new(db);
    let file = sema.parse(position.file_id).syntax().clone();
    let original_token = file
        .token_at_offset(position.offset)
        .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?;
    let range = original_token.text_range();
    let info: Vec<NavigationTarget> = sema
        .descend_into_macros(original_token)
        .iter()
        .filter_map(|token| {
            let parent = token.parent()?;
            let def = match_ast! {
                match parent {
                    ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
                        NameRefClass::Definition(it) => Some(it),
                        _ => None
                    },
                    ast::Name(name) => match NameClass::classify(&sema, &name)? {
                        NameClass::Definition(it) => Some(it),
                        _ => None
                    },
                    _ => None
                }
            };
            match def? {
                Definition::Module(module) => {
                    Some(NavigationTarget::from_module_to_decl(db, module))
                }
                _ => None,
            }
        })
        .collect();

    Some(RangeInfo::new(range, info))
}

#[cfg(test)]
mod tests {
    use ide_db::base_db::FileRange;
    use itertools::Itertools;

    use crate::fixture;

    fn check(ra_fixture: &str) {
        let (analysis, position, expected) = fixture::annotations(ra_fixture);
        let navs = analysis
            .goto_declaration(position)
            .unwrap()
            .expect("no declaration or definition found")
            .info;
        if navs.is_empty() {
            panic!("unresolved reference")
        }

        let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start());
        let navs = navs
            .into_iter()
            .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
            .sorted_by_key(cmp)
            .collect::<Vec<_>>();
        let expected = expected
            .into_iter()
            .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range })
            .sorted_by_key(cmp)
            .collect::<Vec<_>>();
        assert_eq!(expected, navs);
    }

    #[test]
    fn goto_decl_module_outline() {
        check(
            r#"
//- /main.rs
mod foo;
 // ^^^
//- /foo.rs
use self$0;
"#,
        )
    }

    #[test]
    fn goto_decl_module_inline() {
        check(
            r#"
mod foo {
 // ^^^
    use self$0;
}
"#,
        )
    }
}
<commit_msg>Auto merge of #13671 - Veykril:goto-decl, r=Veykril<commit_after>use hir::{AsAssocItem, Semantics};
use ide_db::{
    defs::{Definition, NameClass, NameRefClass},
    RootDatabase,
};
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, T};

use crate::{
    goto_definition::goto_definition, navigation_target::TryToNav, FilePosition, NavigationTarget,
    RangeInfo,
};

// Feature: Go to Declaration
//
// Navigates to the declaration of an identifier.
//
// This is the same as `Go to Definition` with the following exceptions:
// - outline modules will navigate to the `mod name;` item declaration
// - trait assoc items will navigate to the assoc item of the trait declaration opposed to the trait impl
pub(crate) fn goto_declaration(
    db: &RootDatabase,
    position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
    let sema = Semantics::new(db);
    let file = sema.parse(position.file_id).syntax().clone();
    let original_token = file
        .token_at_offset(position.offset)
        .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?;
    let range = original_token.text_range();
    let info: Vec<NavigationTarget> = sema
        .descend_into_macros(original_token)
        .iter()
        .filter_map(|token| {
            let parent = token.parent()?;
            let def = match_ast! {
                match parent {
                    ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
                        NameRefClass::Definition(it) => Some(it),
                        NameRefClass::FieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db),
                    },
                    ast::Name(name) => match NameClass::classify(&sema, &name)? {
                        NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
                        NameClass::PatFieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db),
                    },
                    _ => None
                }
            };
            let assoc = match def? {
                Definition::Module(module) => {
                    return Some(NavigationTarget::from_module_to_decl(db, module))
                }
                Definition::Const(c) => c.as_assoc_item(db),
                Definition::TypeAlias(ta) => ta.as_assoc_item(db),
                Definition::Function(f) => f.as_assoc_item(db),
                _ => None,
            }?;

            let trait_ = assoc.containing_trait_impl(db)?;
            let name = Some(assoc.name(db)?);
            let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
            item.try_to_nav(db)
        })
        .collect();

    if info.is_empty() {
        goto_definition(db, position)
    } else {
        Some(RangeInfo::new(range, info))
    }
}

#[cfg(test)]
mod tests {
    use ide_db::base_db::FileRange;
    use itertools::Itertools;

    use crate::fixture;

    fn check(ra_fixture: &str) {
        let (analysis, position, expected) = fixture::annotations(ra_fixture);
        let navs = analysis
            .goto_declaration(position)
            .unwrap()
            .expect("no declaration or definition found")
            .info;
        if navs.is_empty() {
            panic!("unresolved reference")
        }

        let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start());
        let navs = navs
            .into_iter()
            .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
            .sorted_by_key(cmp)
            .collect::<Vec<_>>();
        let expected = expected
            .into_iter()
            .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range })
            .sorted_by_key(cmp)
            .collect::<Vec<_>>();
        assert_eq!(expected, navs);
    }

    #[test]
    fn goto_decl_module_outline() {
        check(
            r#"
//- /main.rs
mod foo;
 // ^^^
//- /foo.rs
use self$0;
"#,
        )
    }

    #[test]
    fn goto_decl_module_inline() {
        check(
            r#"
mod foo {
 // ^^^
    use self$0;
}
"#,
        )
    }

    #[test]
    fn goto_decl_goto_def_fallback() {
        check(
            r#"
struct Foo;
    // ^^^
impl Foo$0 {}
"#,
        );
    }

    #[test]
    fn goto_decl_assoc_item_no_impl_item() {
        check(
            r#"
trait Trait {
    const C: () = ();
       // ^
}
impl Trait for () {}

fn main() {
    <()>::C$0;
}
"#,
        );
    }

    #[test]
    fn goto_decl_assoc_item() {
        check(
            r#"
trait Trait {
    const C: () = ();
       // ^
}
impl Trait for () {
    const C: () = ();
}

fn main() {
    <()>::C$0;
}
"#,
        );
        check(
            r#"
trait Trait {
    const C: () = ();
       // ^
}
impl Trait for () {
    const C$0: () = ();
}
"#,
        );
    }

    #[test]
    fn goto_decl_field_pat_shorthand() {
        check(
            r#"
struct Foo { field: u32 }
           //^^^^^
fn main() {
    let Foo { field$0 };
}
"#,
        );
    }

    #[test]
    fn goto_decl_constructor_shorthand() {
        check(
            r#"
struct Foo { field: u32 }
           //^^^^^
fn main() {
    let field = 0;
    Foo { field$0 };
}
"#,
        );
    }
}
<|endoftext|>