<commit_before>
// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! LookupHost result from a resolution with a Resolver

use std::io;
use std::mem;
use std::net::IpAddr;
use std::slice::Iter;

use futures::{Async, future, Future, Poll, task};

use trust_dns::client::ClientHandle;
use trust_dns::error::ClientError;
use trust_dns::op::Message;
use trust_dns::rr::{DNSClass, Name, RData, RecordType};

use config::LookupIpStrategy;

/// Result of a DNS query when querying for A or AAAA records.
#[derive(Debug)]
pub struct LookupIp {
    ips: Vec<IpAddr>,
}

impl LookupIp {
    fn new(ips: Vec<IpAddr>) -> Self {
        LookupIp { ips }
    }

    /// Returns a borrowed iterator of the returned IPs
    pub fn iter(&self) -> LookupIpIter {
        LookupIpIter(self.ips.iter())
    }
}

impl Iterator for LookupIp {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.ips.pop()
    }
}

/// Borrowed view of set of IPs returned from a LookupIp
pub struct LookupIpIter<'a>(Iter<'a, IpAddr>);

impl<'a> Iterator for LookupIpIter<'a> {
    type Item = &'a IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// The Future returned from ResolverFuture when performing an A or AAAA lookup.
pub struct LookupIpFuture {
    future: Box<Future<Item = LookupIp, Error = io::Error>>,
}

impl LookupIpFuture {
    pub(crate) fn lookup<C: ClientHandle + 'static>(
        host: &str,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let name = match Name::parse(host, None) {
            Ok(name) => name,
            Err(err) => {
                return LookupIpFuture { future: Box::new(future::err(io::Error::from(err))) }
            }
        };

        let query = LookupIpState::lookup(name, strategy, client);
        LookupIpFuture { future: Box::new(query) }
    }
}

impl Future for LookupIpFuture {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future.poll()
    }
}

// TODO: maximum recursion on CNAME, etc, chains...
// struct LookupStack(Vec<Query>);

// impl LookupStack {
//     // pushes the Query onto the stack, and returns a reference. An error will be returned
//     fn push(&mut self, query: Query) -> io::Result<&Query> {
//         if self.0.contains(&query) {
//             return Err(io::Error::new(io::ErrorKind::Other, "circular CNAME or other recursion"));
//         }

//         self.0.push(query);
//         Ok(self.0.last().unwrap())
//     }
// }

enum LookupIpState {
    Query(Box<Future<Item = Vec<IpAddr>, Error = ClientError>>),
    Fin(Vec<IpAddr>),
}

impl LookupIpState {
    pub fn lookup<C: ClientHandle + 'static>(
        name: Name,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let query_future = lookup(name, strategy, client);

        LookupIpState::Query(query_future)
    }

    fn transition_query(&mut self, ips: Vec<IpAddr>) {
        assert!(if let LookupIpState::Query(_) = *self {
            true
        } else {
            false
        });

        // transition
        mem::replace(self, LookupIpState::Fin(ips));
    }
}

impl Future for LookupIpState {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // first transition any polling that is needed (mutable refs...)
        let poll;
        match *self {
            LookupIpState::Query(ref mut query) => {
                poll = query.poll().map_err(|e| e.into());
                match poll {
                    Ok(Async::NotReady) => {
                        return Ok(Async::NotReady);
                    }
                    Ok(Async::Ready(_)) => (), // handled in next match
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
            LookupIpState::Fin(ref mut ips) => {
                let ips = mem::replace(ips, Vec::<IpAddr>::new());
                let ips = LookupIp::new(ips);
                return Ok(Async::Ready(ips));
            }
        }

        // getting here means there are Aync::Ready available.
        match *self {
            LookupIpState::Query(_) => {
                match poll {
                    Ok(Async::Ready(ips)) => self.transition_query(ips),
                    _ => panic!("should have returned earlier"),
                }
            }
            LookupIpState::Fin(_) => panic!("should have returned earlier"),
        }

        task::current().notify(); // yield
        Ok(Async::NotReady)
    }
}

fn lookup<C: ClientHandle + 'static>(
    name: Name,
    strategy: LookupIpStrategy,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    match strategy {
        LookupIpStrategy::Ipv4Only => ipv4_only(name, client),
        LookupIpStrategy::Ipv6Only => ipv6_only(name, client),
        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client),
        LookupIpStrategy::Ipv6thenIpv4 => ipv6_then_ipv4(name, client),
        LookupIpStrategy::Ipv4thenIpv6 => ipv4_then_ipv6(name, client),
    }
}

fn map_message_to_ipaddr(mut message: Message) -> Vec<IpAddr> {
    message
        .take_answers()
        .iter()
        .filter_map(|r| match *r.rdata() {
            RData::A(ipaddr) => Some(IpAddr::V4(ipaddr)),
            RData::AAAA(ipaddr) => Some(IpAddr::V6(ipaddr)),
            _ => None,
        })
        .collect()
}

/// queries only for A records
fn ipv4_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::A).map(
        map_message_to_ipaddr,
    ))
}

/// queries only for AAAA records
fn ipv6_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::AAAA).map(
        map_message_to_ipaddr,
    ))
}

/// queries only for A and AAAA in parallel
fn ipv4_and_ipv6<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, RecordType::A)
            .map(map_message_to_ipaddr)
            .select(client.query(name, DNSClass::IN, RecordType::AAAA).map(
                map_message_to_ipaddr,
            ))
            .then(|sel_res| {
                match sel_res {
                    // Some ips returned, get the other record result, or else just return record
                    Ok((mut ips, remaining_query)) => {
                        Box::new(remaining_query.then(move |query_res| match query_res {
                            /// join AAAA and A results
                            Ok(mut rem_ips) => {
                                rem_ips.append(&mut ips);
                                future::ok(rem_ips)
                            }
                            // One failed, just return the other
                            Err(_) => future::ok(ips),
                        })) as
                            // This cast is to resolve a comilation error, not sure of it's necessity
                            Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                    }

                    // One failed, just return the other
                    Err((_, remaining_query)) => Box::new(remaining_query),
                }
            }),
    )
}

/// queries only for AAAA and on no results queries for A
fn ipv6_then_ipv4<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    rt_then_swap(name, client, RecordType::AAAA, RecordType::A)
}

/// queries only for A and on no results queries for AAAA
fn ipv4_then_ipv6<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    rt_then_swap(name, client, RecordType::A, RecordType::AAAA)
}

/// queries only for first_type and on no results queries for second_type
fn rt_then_swap<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
    first_type: RecordType,
    second_type: RecordType,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    let mut or_client = client.clone();
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, first_type)
            .map(map_message_to_ipaddr)
            .then(move |res| {
                match res {
                    Ok(ips) => {
                        println!("ips");
                        if ips.is_empty() {
                            println!("ips, are empty");

                            // no ips returns, NXDomain or Otherwise, doesn't matter
                            Box::new(
                                or_client
                                    .query(name.clone(), DNSClass::IN, second_type)
                                    .map(map_message_to_ipaddr),
                            ) as
                                Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                        } else {
                            Box::new(future::ok(ips)) as
                                Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                        }
                    }
                    Err(_) => {
                        Box::new(
                            or_client
                                .query(name.clone(), DNSClass::IN, second_type)
                                .map(map_message_to_ipaddr),
                        )
                    }
                }
            }),
    )
}

// TODO: need to add some Err(result) tests...
#[cfg(test)]
mod tests {
    use std::io;
    use std::mem;
    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
    use std::slice::Iter;
    use std::sync::{Arc, Mutex};

    use futures::{Async, future, Future, Poll, task};

    use trust_dns::client::ClientHandle;
    use trust_dns::error::ClientError;
    use trust_dns::op::Message;
    use trust_dns::rr::{DNSClass, Name, Record, RData, RecordType};

    use config::LookupIpStrategy;

    use super::*;

    #[derive(Clone)]
    struct MockClientHandle {
        messages: Arc<Mutex<Vec<Message>>>,
    }

    impl ClientHandle for MockClientHandle {
        fn send(&mut self, message: Message) -> Box<Future<Item = Message, Error = ClientError>> {
            Box::new(future::ok(self.messages.lock().unwrap().pop().unwrap_or(
                Message::new(),
            )))
        }
    }

    fn v4_message() -> Message {
        let mut message = Message::new();
        message.insert_answers(vec![
            Record::from_rdata(
                Name::root(),
                0,
                RecordType::A,
                RData::A(Ipv4Addr::new(127, 0, 0, 1))
            ),
        ]);
        message
    }

    fn v6_message() -> Message {
        let mut message = Message::new();
        message.insert_answers(vec![
            Record::from_rdata(
                Name::root(),
                0,
                RecordType::AAAA,
                RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
            ),
        ]);
        message
    }

    fn mock(messages: Vec<Message>) -> MockClientHandle {
        MockClientHandle { messages: Arc::new(Mutex::new(messages)) }
    }

    #[test]
    fn test_ipv4_only_strategy() {
        assert_eq!(
            ipv4_only(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv6_only_strategy() {
        assert_eq!(
            ipv6_only(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv4_and_ipv6_strategy() {
        // both succeed
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v4_message(), v6_message()]))
                .wait()
                .unwrap(),
            vec![
                IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
                IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
            ]
        );

        // only ipv4 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))]
        );

        // only ipv6 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
        );
    }

    #[test]
    fn test_ipv6_then_ipv4_strategy() {
        // ipv6 first
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );

        // nothing then ipv4
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v4_message(), Message::new()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv4_then_ipv6_strategy() {
        // ipv6 first
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );

        // nothing then ipv6
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v6_message(), Message::new()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );
    }
}<commit_msg>add some negative tests for the lookup ip strategies<commit_after>
// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! LookupHost result from a resolution with a Resolver

use std::io;
use std::mem;
use std::net::IpAddr;
use std::slice::Iter;

use futures::{Async, future, Future, Poll, task};

use trust_dns::client::ClientHandle;
use trust_dns::error::ClientError;
use trust_dns::op::Message;
use trust_dns::rr::{DNSClass, Name, RData, RecordType};

use config::LookupIpStrategy;

/// Result of a DNS query when querying for A or AAAA records.
#[derive(Debug)]
pub struct LookupIp {
    ips: Vec<IpAddr>,
}

impl LookupIp {
    fn new(ips: Vec<IpAddr>) -> Self {
        LookupIp { ips }
    }

    /// Returns a borrowed iterator of the returned IPs
    pub fn iter(&self) -> LookupIpIter {
        LookupIpIter(self.ips.iter())
    }
}

impl Iterator for LookupIp {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.ips.pop()
    }
}

/// Borrowed view of set of IPs returned from a LookupIp
pub struct LookupIpIter<'a>(Iter<'a, IpAddr>);

impl<'a> Iterator for LookupIpIter<'a> {
    type Item = &'a IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// The Future returned from ResolverFuture when performing an A or AAAA lookup.
pub struct LookupIpFuture {
    future: Box<Future<Item = LookupIp, Error = io::Error>>,
}

impl LookupIpFuture {
    pub(crate) fn lookup<C: ClientHandle + 'static>(
        host: &str,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let name = match Name::parse(host, None) {
            Ok(name) => name,
            Err(err) => {
                return LookupIpFuture { future: Box::new(future::err(io::Error::from(err))) }
            }
        };

        let query = LookupIpState::lookup(name, strategy, client);
        LookupIpFuture { future: Box::new(query) }
    }
}

impl Future for LookupIpFuture {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future.poll()
    }
}

// TODO: maximum recursion on CNAME, etc, chains...
// struct LookupStack(Vec<Query>);

// impl LookupStack {
//     // pushes the Query onto the stack, and returns a reference. An error will be returned
//     fn push(&mut self, query: Query) -> io::Result<&Query> {
//         if self.0.contains(&query) {
//             return Err(io::Error::new(io::ErrorKind::Other, "circular CNAME or other recursion"));
//         }

//         self.0.push(query);
//         Ok(self.0.last().unwrap())
//     }
// }

enum LookupIpState {
    Query(Box<Future<Item = Vec<IpAddr>, Error = ClientError>>),
    Fin(Vec<IpAddr>),
}

impl LookupIpState {
    pub fn lookup<C: ClientHandle + 'static>(
        name: Name,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let query_future = lookup(name, strategy, client);

        LookupIpState::Query(query_future)
    }

    fn transition_query(&mut self, ips: Vec<IpAddr>) {
        assert!(if let LookupIpState::Query(_) = *self {
            true
        } else {
            false
        });

        // transition
        mem::replace(self, LookupIpState::Fin(ips));
    }
}

impl Future for LookupIpState {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // first transition any polling that is needed (mutable refs...)
        let poll;
        match *self {
            LookupIpState::Query(ref mut query) => {
                poll = query.poll().map_err(|e| e.into());
                match poll {
                    Ok(Async::NotReady) => {
                        return Ok(Async::NotReady);
                    }
                    Ok(Async::Ready(_)) => (), // handled in next match
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
            LookupIpState::Fin(ref mut ips) => {
                let ips = mem::replace(ips, Vec::<IpAddr>::new());
                let ips = LookupIp::new(ips);
                return Ok(Async::Ready(ips));
            }
        }

        // getting here means there are Aync::Ready available.
        match *self {
            LookupIpState::Query(_) => {
                match poll {
                    Ok(Async::Ready(ips)) => self.transition_query(ips),
                    _ => panic!("should have returned earlier"),
                }
            }
            LookupIpState::Fin(_) => panic!("should have returned earlier"),
        }

        task::current().notify(); // yield
        Ok(Async::NotReady)
    }
}

fn lookup<C: ClientHandle + 'static>(
    name: Name,
    strategy: LookupIpStrategy,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    match strategy {
        LookupIpStrategy::Ipv4Only => ipv4_only(name, client),
        LookupIpStrategy::Ipv6Only => ipv6_only(name, client),
        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client),
        LookupIpStrategy::Ipv6thenIpv4 => ipv6_then_ipv4(name, client),
        LookupIpStrategy::Ipv4thenIpv6 => ipv4_then_ipv6(name, client),
    }
}

fn map_message_to_ipaddr(mut message: Message) -> Vec<IpAddr> {
    message
        .take_answers()
        .iter()
        .filter_map(|r| match *r.rdata() {
            RData::A(ipaddr) => Some(IpAddr::V4(ipaddr)),
            RData::AAAA(ipaddr) => Some(IpAddr::V6(ipaddr)),
            _ => None,
        })
        .collect()
}

/// queries only for A records
fn ipv4_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::A).map(
        map_message_to_ipaddr,
    ))
}

/// queries only for AAAA records
fn ipv6_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::AAAA).map(
        map_message_to_ipaddr,
    ))
}

/// queries only for A and AAAA in parallel
fn ipv4_and_ipv6<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, RecordType::A)
            .map(map_message_to_ipaddr)
            .select(client.query(name, DNSClass::IN, RecordType::AAAA).map(
                map_message_to_ipaddr,
            ))
            .then(|sel_res| {
                match sel_res {
                    // Some ips returned, get the other record result, or else just return record
                    Ok((mut ips, remaining_query)) => {
                        Box::new(remaining_query.then(move |query_res| match query_res {
                            /// join AAAA and A results
                            Ok(mut rem_ips) => {
                                rem_ips.append(&mut ips);
                                future::ok(rem_ips)
                            }
                            // One failed, just return the other
                            Err(_) => future::ok(ips),
                        })) as
                            // This cast is to resolve a comilation error, not sure of it's necessity
                            Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                    }

                    // One failed, just return the other
                    Err((_, remaining_query)) => Box::new(remaining_query),
                }
            }),
    )
}

/// queries only for AAAA and on no results queries for A
fn ipv6_then_ipv4<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    rt_then_swap(name, client, RecordType::AAAA, RecordType::A)
}

/// queries only for A and on no results queries for AAAA
fn ipv4_then_ipv6<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    rt_then_swap(name, client, RecordType::A, RecordType::AAAA)
}

/// queries only for first_type and on no results queries for second_type
fn rt_then_swap<C: ClientHandle + 'static>(
    name: Name,
    client: &mut C,
    first_type: RecordType,
    second_type: RecordType,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    let mut or_client = client.clone();
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, first_type)
            .map(map_message_to_ipaddr)
            .then(move |res| {
                match res {
                    Ok(ips) => {
                        println!("ips");
                        if ips.is_empty() {
                            println!("ips, are empty");

                            // no ips returns, NXDomain or Otherwise, doesn't matter
                            Box::new(
                                or_client
                                    .query(name.clone(), DNSClass::IN, second_type)
                                    .map(map_message_to_ipaddr),
                            ) as
                                Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                        } else {
                            Box::new(future::ok(ips)) as
                                Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                        }
                    }
                    Err(_) => {
                        Box::new(
                            or_client
                                .query(name.clone(), DNSClass::IN, second_type)
                                .map(map_message_to_ipaddr),
                        )
                    }
                }
            }),
    )
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::mem;
    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
    use std::slice::Iter;
    use std::sync::{Arc, Mutex};

    use futures::{Async, future, Future, Poll, task};

    use trust_dns::client::ClientHandle;
    use trust_dns::error::*;
    use trust_dns::op::Message;
    use trust_dns::rr::{DNSClass, Name, Record, RData, RecordType};

    use config::LookupIpStrategy;

    use super::*;

    #[derive(Clone)]
    struct MockClientHandle {
        messages: Arc<Mutex<Vec<ClientResult<Message>>>>,
    }

    impl ClientHandle for MockClientHandle {
        fn send(&mut self, message: Message) -> Box<Future<Item = Message, Error = ClientError>> {
            Box::new(future::result(
                self.messages.lock().unwrap().pop().unwrap_or(empty()),
            ))
        }
    }

    fn v4_message() -> ClientResult<Message> {
        let mut message = Message::new();
        message.insert_answers(vec![
            Record::from_rdata(
                Name::root(),
                0,
                RecordType::A,
                RData::A(Ipv4Addr::new(127, 0, 0, 1))
            ),
        ]);
        Ok(message)
    }

    fn v6_message() -> ClientResult<Message> {
        let mut message = Message::new();
        message.insert_answers(vec![
            Record::from_rdata(
                Name::root(),
                0,
                RecordType::AAAA,
                RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
            ),
        ]);
        Ok(message)
    }

    fn empty() -> ClientResult<Message> {
        Ok(Message::new())
    }

    fn error() -> ClientResult<Message> {
        Err(ClientErrorKind::Io.into())
    }

    fn mock(messages: Vec<ClientResult<Message>>) -> MockClientHandle {
        MockClientHandle { messages: Arc::new(Mutex::new(messages)) }
    }

    #[test]
    fn test_ipv4_only_strategy() {
        assert_eq!(
            ipv4_only(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv6_only_strategy() {
        assert_eq!(
            ipv6_only(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv4_and_ipv6_strategy() {
        // both succeed
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v4_message(), v6_message()]))
                .wait()
                .unwrap(),
            vec![
                IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
                IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
            ]
        );

        // only ipv4 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))]
        );

        // only ipv6 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
        );

        // error, then only ipv6 available
        assert_eq!(
            ipv4_and_ipv6(Name::root(), &mut mock(vec![error(), v6_message()]))
                .wait()
                .unwrap(),
            vec![IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
        );
    }

    #[test]
    fn test_ipv6_then_ipv4_strategy() {
        // ipv6 first
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v6_message()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );

        // nothing then ipv4
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v4_message(), empty()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );

        // ipv4 and error
        assert_eq!(
            ipv6_then_ipv4(Name::root(), &mut mock(vec![v4_message(), error()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );
    }

    #[test]
    fn test_ipv4_then_ipv6_strategy() {
        // ipv6 first
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v4_message()]))
                .wait()
                .unwrap(),
            vec![Ipv4Addr::new(127, 0, 0, 1)]
        );

        // nothing then ipv6
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v6_message(), empty()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );

        // error then ipv6
        assert_eq!(
            ipv4_then_ipv6(Name::root(), &mut mock(vec![v6_message(), error()]))
                .wait()
                .unwrap(),
            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
        );
    }
}<|endoftext|>


<commit_before>use super::{Edge, Graph, NodeId};

use std::collections::VecDeque;
use std::time::Instant;

impl<E: Edge> Graph<E> {
    pub fn count_components(&self) -> usize {
        let start = Instant::now();
        let mut visited = vec![false; self.node_info.len()];
        let mut queue = VecDeque::<NodeId>::new();
        let mut count = 0;
        for id in 0..visited.len() {
            if !visited[id] {
                queue.push_front(id);
            } else {
                continue;
            }
            while let Some(n) = queue.pop_front() {
                if !visited[n] {
                    visited[n] = true;
                    queue.extend(self.outgoing_edges_for(n)
                                     .iter()
                                     .map(|e| e.get_dest_id())
                                     .filter(|&n| !visited[n]));
                }
            }
            count += 1;
        }

        let end = Instant::now();
        println!("Counting Components took {:?}", end.duration_since(start));
        count
    }
}
<commit_msg>Check components explicitly<commit_after>use super::{Edge, Graph, NodeId};

use std::collections::{BTreeSet, VecDeque};
use std::time::Instant;

type Component = BTreeSet<NodeId>;
impl<E: Edge> Graph<E> {
    pub fn count_components(&self) -> usize {
        let start = Instant::now();
        let mut visited = vec![false; self.node_info.len()];
        let mut components = Vec::<Component>::new();
        for id in 0..visited.len() {
            if !visited[id] {
                let mut comp = self.dfs(id, &mut visited);
                for component in &mut components {
                    if !component.is_disjoint(&comp) {
                        component.append(&mut comp);
                        break;
                    }
                }
                if !comp.is_empty() {
                    components.push(comp);
                }
            } else {
                continue;
            }
        }

        let end = Instant::now();
        println!("Counting Components took {:?}", end.duration_since(start));
        components.len()
    }

    fn dfs(&self, start: NodeId, visited: &mut Vec<bool>) -> Component {
        let mut result = BTreeSet::new();
        let mut queue = VecDeque::<NodeId>::new();
        queue.push_front(start);
        while let Some(n) = queue.pop_front() {
            if !visited[n] {
                visited[n] = true;
                result.insert(n);
                queue.extend(self.outgoing_edges_for(n)
                                 .iter()
                                 .map(|e| e.get_dest_id())
                                 .filter(|&n| !visited[n]));
            }
        }
        result
    }
}

#[test]
fn count() {
    use super::{EdgeInfo, NodeInfo};
    let g = Graph::new(vec![NodeInfo::new(1, 2.3, 3.4, 0),
                            NodeInfo::new(2, 2.3, 3.4, 0),
                            NodeInfo::new(3, 2.3, 3.4, 0),
                            NodeInfo::new(4, 2.3, 3.4, 0)],
                       vec![EdgeInfo::new(0, 1, 3, 3),
                            EdgeInfo::new(0, 2, 3, 3),
                            EdgeInfo::new(2, 3, 3, 3),
                            EdgeInfo::new(4, 0, 3, 3)]);
    assert_eq!(g.count_components(), 1)
}
<|endoftext|>


<commit_before>// Copyright 2015 Joe Neeman.
//
// 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.

use char_map::CharSet;
use nfa::Nfa;
use transition::{Accept, Predicate, PredicatePart};
use regex_syntax::{CharClass, ClassRange, Expr, Repeater};
use std::ops::Deref;

// When constructing an Nfa from a regex, the states have special structure: if the transition
// accepts any input or matches a predicate, then it always moves to the next state. Therefore,
// there is no need to store the target state of a transition or predicate.  Also, the last state
// is always the accepting state, so there is no need to store whether a state is accepting.
#[derive(Debug, PartialEq)]
struct BuilderState {
    chars: CharSet,
    eps: Vec<usize>,
    predicates: Vec<Predicate>
}

impl BuilderState {
    fn new() -> BuilderState {
        BuilderState {
            chars: CharSet::new(),
            eps: Vec::new(),
            predicates: Vec::new(),
        }
    }

    fn from_chars(chars: CharSet) -> BuilderState {
        BuilderState {
            chars: chars,
            eps: Vec::new(),
            predicates: Vec::new(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct NfaBuilder {
    states: Vec<BuilderState>,
}

impl NfaBuilder {
    pub fn len(&self) -> usize {
        self.states.len()
    }

    pub fn to_automaton(&self) -> Nfa {
        let mut ret = Nfa::with_capacity(self.len());
        let mut ret_len: usize = 0;
        for s in &self.states {
            ret_len += 1;
            ret.add_state(if ret_len == self.len() { Accept::Always } else { Accept::Never });

            for ch in &s.chars {
                ret.add_transition(ret_len - 1, ret_len, *ch);
            }
            for eps in &s.eps {
                ret.add_eps(ret_len - 1, *eps);
            }
            for p in &s.predicates {
                ret.add_predicate(ret_len - 1, ret_len, p.clone());
            }
        }

        ret
    }

    pub fn from_expr(expr: &Expr) -> NfaBuilder {
        let mut ret = NfaBuilder { states: Vec::new() };
        ret.add_expr(expr);
        ret
    }

    fn add_eps(&mut self, from: usize, to: usize) {
        self.states[from].eps.push(to);
    }

    // Appends two states, with a given transition between them.
    fn add_single_transition(&mut self, chars: CharSet) {
        self.states.push(BuilderState::from_chars(chars));
        self.states.push(BuilderState::new());
     }

    // Adds a sequence of states, and a sequence of transitions between them.
    fn add_literal<C, I>(&mut self, chars: I, case_insensitive: bool)
        where C: Deref<Target=char>,
              I: Iterator<Item=C>
    {
        for ch in chars {
            let ranges = if case_insensitive {
                // NOTE: it isn't really necessary to create a new CharClass here, but
                // regex_syntax doesn't expose case_fold (or new) on ClassRange.
                let cc = CharClass::new(vec![ClassRange { start: *ch, end: *ch }]);
                CharSet::from_char_class(&cc.case_fold())
            } else {
                CharSet::single(*ch as u32)
            };
            self.states.push(BuilderState::from_chars(ranges));
        }
        self.states.push(BuilderState::new());
    }

    fn add_concat_exprs(&mut self, exprs: &Vec<Expr>) {
        if let Some((expr, rest)) = exprs.split_first() {
            self.add_expr(expr);

            for expr in rest {
                let cur_len = self.states.len();
                self.add_eps(cur_len - 1, cur_len);
                self.add_expr(expr);
            }
        }
    }

    fn add_alternate_exprs(&mut self, alts: &Vec<Expr>) {
        // Add the new initial state that feeds into the alternate.
        let init_idx = self.states.len();
        self.states.push(BuilderState::new());

        let mut expr_end_indices = Vec::<usize>::new();
        for expr in alts {
            let expr_init_idx = self.states.len();
            self.add_eps(init_idx, expr_init_idx);
            self.add_expr(expr);
            expr_end_indices.push(self.states.len() - 1);
        }

        // Make the final state of each alternative point to our new final state.
        self.states.push(BuilderState::new());
        let final_idx = self.states.len() - 1;
        for idx in expr_end_indices {
            self.add_eps(idx, final_idx);
        }
    }

    fn add_repeat(&mut self, expr: &Expr, rep: Repeater) {
        match rep {
            Repeater::ZeroOrOne => {
                self.add_repeat_min_max(expr, 0, Some(1));
            },
            Repeater::ZeroOrMore => {
                self.add_repeat_min_max(expr, 0, None);
            },
            Repeater::OneOrMore => {
                self.add_repeat_min_max(expr, 1, None);
            },
            Repeater::Range{ min, max } => {
                self.add_repeat_min_max(expr, min, max);
            }
        }
    }

    fn add_repeat_min_max(&mut self, expr: &Expr, min: u32, maybe_max: Option<u32>) {
        // The starting index of the repetition that we are currently working on.
        let mut cur_init_idx = self.states.len();
        if min > 0 {
            self.add_expr(expr);
            for _ in 1..min {
                cur_init_idx = self.states.len();
                self.add_expr(expr);
                self.add_eps(cur_init_idx - 1, cur_init_idx);
            }
        }

        if let Some(max) = maybe_max {
            let mut init_indices = Vec::<usize>::with_capacity((max - min) as usize);
            for i in 0..(max - min) {
                cur_init_idx = self.states.len();
                self.add_expr(expr);
                init_indices.push(cur_init_idx);

                if i > 0 || min > 0 {
                    self.add_eps(cur_init_idx - 1, cur_init_idx);
                }
            }
            let final_idx = self.states.len() - 1;
            for idx in init_indices {
                self.add_eps(idx, final_idx);
            }
        } else {
            if min == 0 {
                cur_init_idx = self.states.len();
                self.add_expr(expr);
                let final_idx = self.states.len() - 1;
                self.add_eps(cur_init_idx, final_idx);
            }

            let final_idx = self.states.len() - 1;
            self.add_eps(final_idx, cur_init_idx);
        }
    }

    fn add_predicate(&mut self, part1: PredicatePart, part2: PredicatePart) {
        self.states.push(BuilderState::new());
        self.states.last_mut().unwrap().predicates.push(Predicate(part1, part2));
        self.states.push(BuilderState::new());
    }

    // Adds an extra predicate between the last two states (there must be at least two states).
    fn extra_predicate(&mut self, part1: PredicatePart, part2: PredicatePart) {
        let len = self.states.len();
        self.states[len-2].predicates.push(Predicate(part1, part2));
    }

    fn add_expr(&mut self, expr: &Expr) {
        use regex_syntax::Expr::*;

        match expr {
            &Empty => {},
            &Class(ref c) => self.add_single_transition(CharSet::from_char_class(c)),
            &AnyChar => self.add_single_transition(CharSet::full()),
            &AnyCharNoNL => self.add_single_transition(CharSet::except("\n\r")),
            &Concat(ref es) => self.add_concat_exprs(es),
            &Alternate(ref es) => self.add_alternate_exprs(es),
            &Literal { ref chars, casei } => self.add_literal(chars.iter(), casei),
            &StartLine => {
                self.add_predicate(PredicatePart::single_char('\n').or_at_boundary(),
                                   PredicatePart::full());
            },
            &StartText => {
                self.add_predicate(PredicatePart::at_boundary(), PredicatePart::full());
            }
            &EndLine => {
                self.add_predicate(PredicatePart::full(),
                                   PredicatePart::single_char('\n').or_at_boundary());
            },
            &EndText => {
                self.add_predicate(PredicatePart::full(), PredicatePart::at_boundary());
            }
            &WordBoundary => {
                self.add_predicate(PredicatePart::word_char(), PredicatePart::not_word_char());
                self.extra_predicate(PredicatePart::not_word_char(), PredicatePart::word_char());
            },
            &NotWordBoundary => {
                self.add_predicate(PredicatePart::word_char(), PredicatePart::word_char());
                self.extra_predicate(PredicatePart::not_word_char(), PredicatePart::word_char());
            },

            // We don't support capture groups, so there is no need to keep track of
            // the group name or number.
            &Group { ref e, .. } => self.add_expr(e),

            // We don't support greedy vs. lazy matching, because I don't know
            // if it can be expressed in a DFA.
            &Repeat { ref e, r, .. } => self.add_repeat(e, r),
        }
    }
}

    #[cfg(test)]
mod tests {
    use builder::{NfaBuilder, BuilderState};
    use char_map::CharRange;
    use regex_syntax;

    fn parse(s: &str) -> regex_syntax::Result<NfaBuilder> {
        let expr = try!(regex_syntax::Expr::parse(s));
        Ok(NfaBuilder::from_expr(&expr))
    }

    fn make_builder(n_states: usize) -> NfaBuilder {
        let mut ret = NfaBuilder { states: Vec::new() };
        for _ in 0..n_states {
            ret.states.push(BuilderState::new());
        }
        ret
    }

    #[test]
    fn test_char_class() {
        let builder = parse("[a-z][A-Z]").unwrap();
        let mut target = make_builder(4);
        target.states[0].chars.push(CharRange::new('a' as u32, 'z' as u32));
        target.add_eps(1, 2);
        target.states[2].chars.push(CharRange::new('A' as u32, 'Z' as u32));

        assert_eq!(builder, target);
    }

    #[test]
    fn test_literal() {
        let builder = parse("aZ").unwrap();
        let mut target = make_builder(3);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[1].chars.push(CharRange::single('Z' as u32));

        assert_eq!(builder, target);
    }

    #[test]
    fn test_repeat_zero_or_more() {
        let builder = parse("a*z").unwrap();
        let builder2 = parse("a{0,}z").unwrap();
        let mut target = make_builder(4);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('z' as u32));
        target.add_eps(0, 1);
        target.add_eps(1, 0);
        target.add_eps(1, 2);

        assert_eq!(builder, target);
        assert_eq!(builder2, target);
    }

    #[test]
    fn test_repeat_one_or_more() {
        let builder = parse("a+z").unwrap();
        let builder2 = parse("a{1,}z").unwrap();
        let mut target = make_builder(4);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('z' as u32));
        target.add_eps(1, 0);
        target.add_eps(1, 2);

        assert_eq!(builder, target);
        assert_eq!(builder2, target);
    }

    #[test]
    fn test_repeat_zero_or_one() {
        let builder = parse("a?z").unwrap();
        let builder2 = parse("a{0,1}z").unwrap();
        let mut target = make_builder(4);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('z' as u32));
        target.add_eps(0, 1);
        target.add_eps(1, 2);

        assert_eq!(builder, target);
        assert_eq!(builder2, target);
    }

    #[test]
    fn test_repeat_exact() {
        let builder = parse("a{3}z").unwrap();
        let mut target = make_builder(8);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('a' as u32));
        target.states[4].chars.push(CharRange::single('a' as u32));
        target.states[6].chars.push(CharRange::single('z' as u32));
        target.add_eps(1, 2);
        target.add_eps(3, 4);
        target.add_eps(5, 6);

        assert_eq!(builder, target);
    }

    #[test]
    fn test_repeat_between() {
        let builder = parse("a{2,4}z").unwrap();
        let mut target = parse("a{4}z").unwrap();
        target.add_eps(4, 7);
        target.add_eps(6, 7);

        assert_eq!(builder, target);

        let builder = parse("a{0,2}z").unwrap();
        let mut target = parse("a{2}z").unwrap();
        target.add_eps(0, 3);
        target.add_eps(2, 3);

        assert_eq!(builder, target);
    }

    #[test]
    fn test_alternate() {
        let builder = parse("a|z").unwrap();
        let mut target = make_builder(6);
        target.states[1].chars.push(CharRange::single('a' as u32));
        target.states[3].chars.push(CharRange::single('z' as u32));
        target.add_eps(0, 1);
        target.add_eps(2, 5);
        target.add_eps(0, 3);
        target.add_eps(4, 5);

        assert_eq!(builder, target);
    }

    #[test]
    fn test_case_insensitive() {
        let builder = parse("(?i)ab").unwrap();
        let mut target = make_builder(3);
        target.states[0].chars.push(CharRange::single('A' as u32));
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[1].chars.push(CharRange::single('B' as u32));
        target.states[1].chars.push(CharRange::single('b' as u32));

        assert_eq!(builder, target);
    }
}

<commit_msg>Add docs and tests to builder.<commit_after>// Copyright 2015 Joe Neeman.
//
// 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.

use char_map::CharSet;
use nfa::Nfa;
use transition::{Accept, Predicate, PredicatePart};
use regex_syntax::{CharClass, ClassRange, Expr, Repeater};
use std::ops::Deref;

/// When constructing an Nfa from a regex, the states have special structure: if the transition
/// accepts any input or matches a predicate, then it always moves to the next state. Therefore,
/// there is no need to store the target state of a transition or predicate.  Also, the last state
/// is always the accepting state, so there is no need to store whether a state is accepting.
#[derive(Debug, PartialEq)]
struct BuilderState {
    chars: CharSet,
    eps: Vec<usize>,
    predicates: Vec<Predicate>
}

impl BuilderState {
    fn new() -> BuilderState {
        BuilderState {
            chars: CharSet::new(),
            eps: Vec::new(),
            predicates: Vec::new(),
        }
    }

    fn from_chars(chars: CharSet) -> BuilderState {
        BuilderState {
            chars: chars,
            eps: Vec::new(),
            predicates: Vec::new(),
        }
    }
}

/// Builds an `Nfa` from a `regex_syntax::Expr`.
#[derive(Debug, PartialEq)]
pub struct NfaBuilder {
    states: Vec<BuilderState>,
}

impl NfaBuilder {
    /// Returns the number of states.
    pub fn len(&self) -> usize {
        self.states.len()
    }

    /// Converts this `NfaBuilder` into an `Nfa`.
    pub fn to_automaton(&self) -> Nfa {
        let mut ret = Nfa::with_capacity(self.len());
        let mut ret_len: usize = 0;
        for s in &self.states {
            ret_len += 1;
            ret.add_state(if ret_len == self.len() { Accept::Always } else { Accept::Never });

            for ch in &s.chars {
                ret.add_transition(ret_len - 1, ret_len, *ch);
            }
            for eps in &s.eps {
                ret.add_eps(ret_len - 1, *eps);
            }
            for p in &s.predicates {
                ret.add_predicate(ret_len - 1, ret_len, p.clone());
            }
        }

        ret
    }

    /// Creates an `NfaBuilder` from an `Expr`.
    pub fn from_expr(expr: &Expr) -> NfaBuilder {
        let mut ret = NfaBuilder { states: Vec::new() };
        ret.add_expr(expr);
        ret
    }

    /// Adds an eps transition between the given states.
    fn add_eps(&mut self, from: usize, to: usize) {
        self.states[from].eps.push(to);
    }

    /// Appends two states, with a given transition between them.
    fn add_single_transition(&mut self, chars: CharSet) {
        self.states.push(BuilderState::from_chars(chars));
        self.states.push(BuilderState::new());
     }

    /// Appends a sequence of states that recognizes a literal.
    fn add_literal<C, I>(&mut self, chars: I, case_insensitive: bool)
        where C: Deref<Target=char>,
              I: Iterator<Item=C>
    {
        for ch in chars {
            let ranges = if case_insensitive {
                let cc = CharClass::new(vec![ClassRange { start: *ch, end: *ch }]);
                CharSet::from_char_class(&cc.case_fold())
            } else {
                CharSet::single(*ch as u32)
            };
            self.states.push(BuilderState::from_chars(ranges));
        }
        self.states.push(BuilderState::new());
    }

    /// Appends a sequence of states that recognizes the concatenation of `exprs`.
    fn add_concat_exprs(&mut self, exprs: &Vec<Expr>) {
        if let Some((expr, rest)) = exprs.split_first() {
            self.add_expr(expr);

            for expr in rest {
                let cur_len = self.states.len();
                self.add_eps(cur_len - 1, cur_len);
                self.add_expr(expr);
            }
        }
    }

    /// Appends a sequence of states that recognizes one of the expressions in `alts`.
    fn add_alternate_exprs(&mut self, alts: &Vec<Expr>) {
        // Add the new initial state that feeds into the alternate.
        let init_idx = self.states.len();
        self.states.push(BuilderState::new());

        let mut expr_end_indices = Vec::<usize>::new();
        for expr in alts {
            let expr_init_idx = self.states.len();
            self.add_eps(init_idx, expr_init_idx);
            self.add_expr(expr);
            expr_end_indices.push(self.states.len() - 1);
        }

        // Make the final state of each alternative point to our new final state.
        self.states.push(BuilderState::new());
        let final_idx = self.states.len() - 1;
        for idx in expr_end_indices {
            self.add_eps(idx, final_idx);
        }
    }

    /// Appends new states, representing multiple copies of `expr`.
    fn add_repeat(&mut self, expr: &Expr, rep: Repeater) {
        match rep {
            Repeater::ZeroOrOne => {
                self.add_repeat_min_max(expr, 0, Some(1));
            },
            Repeater::ZeroOrMore => {
                self.add_repeat_min_max(expr, 0, None);
            },
            Repeater::OneOrMore => {
                self.add_repeat_min_max(expr, 1, None);
            },
            Repeater::Range{ min, max } => {
                self.add_repeat_min_max(expr, min, max);
            }
        }
    }

    /// Appends new states, representing multiple copies of `expr`.
    ///
    /// The new states represent a language that accepts at least `min` and at most `maybe_max`
    /// copies of `expr`. (If `maybe_max` is `None`, there is no upper bound.)
    fn add_repeat_min_max(&mut self, expr: &Expr, min: u32, maybe_max: Option<u32>) {
        // The starting index of the repetition that we are currently working on.
        let mut cur_init_idx = self.states.len();
        if min > 0 {
            self.add_expr(expr);
            for _ in 1..min {
                cur_init_idx = self.states.len();
                self.add_expr(expr);
                self.add_eps(cur_init_idx - 1, cur_init_idx);
            }
        }

        if let Some(max) = maybe_max {
            let mut init_indices = Vec::<usize>::with_capacity((max - min) as usize);
            for i in 0..(max - min) {
                cur_init_idx = self.states.len();
                self.add_expr(expr);
                init_indices.push(cur_init_idx);

                if i > 0 || min > 0 {
                    self.add_eps(cur_init_idx - 1, cur_init_idx);
                }
            }
            let final_idx = self.states.len() - 1;
            for idx in init_indices {
                self.add_eps(idx, final_idx);
            }
        } else {
            if min == 0 {
                cur_init_idx = self.states.len();
                self.add_expr(expr);
                let final_idx = self.states.len() - 1;
                self.add_eps(cur_init_idx, final_idx);
            }

            let final_idx = self.states.len() - 1;
            self.add_eps(final_idx, cur_init_idx);
        }
    }

    /// Adds two new states, with a predicate connecting them.
    fn add_predicate(&mut self, part1: PredicatePart, part2: PredicatePart) {
        self.states.push(BuilderState::new());
        self.states.last_mut().unwrap().predicates.push(Predicate(part1, part2));
        self.states.push(BuilderState::new());
    }

    /// Adds an extra predicate between the last two states (there must be at least two states).
    fn extra_predicate(&mut self, part1: PredicatePart, part2: PredicatePart) {
        let len = self.states.len();
        self.states[len-2].predicates.push(Predicate(part1, part2));
    }

    /// Appends a bunch of new states, representing `expr`.
    fn add_expr(&mut self, expr: &Expr) {
        use regex_syntax::Expr::*;

        match expr {
            &Empty => {},
            &Class(ref c) => self.add_single_transition(CharSet::from_char_class(c)),
            &AnyChar => self.add_single_transition(CharSet::full()),
            &AnyCharNoNL => self.add_single_transition(CharSet::except("\n\r")),
            &Concat(ref es) => self.add_concat_exprs(es),
            &Alternate(ref es) => self.add_alternate_exprs(es),
            &Literal { ref chars, casei } => self.add_literal(chars.iter(), casei),
            &StartLine => {
                self.add_predicate(PredicatePart::single_char('\n').or_at_boundary(),
                                   PredicatePart::full());
            },
            &StartText => {
                self.add_predicate(PredicatePart::at_boundary(), PredicatePart::full());
            }
            &EndLine => {
                self.add_predicate(PredicatePart::full(),
                                   PredicatePart::single_char('\n').or_at_boundary());
            },
            &EndText => {
                self.add_predicate(PredicatePart::full(), PredicatePart::at_boundary());
            }
            &WordBoundary => {
                self.add_predicate(PredicatePart::word_char(), PredicatePart::not_word_char());
                self.extra_predicate(PredicatePart::not_word_char(), PredicatePart::word_char());
            },
            &NotWordBoundary => {
                self.add_predicate(PredicatePart::word_char(), PredicatePart::word_char());
                self.extra_predicate(PredicatePart::not_word_char(), PredicatePart::word_char());
            },

            // We don't support capture groups, so there is no need to keep track of
            // the group name or number.
            &Group { ref e, .. } => self.add_expr(e),

            // We don't support greedy vs. lazy matching, because I don't know
            // if it can be expressed in a DFA.
            &Repeat { ref e, r, .. } => self.add_repeat(e, r),
        }
    }
}

    #[cfg(test)]
mod tests {
    use builder::{NfaBuilder, BuilderState};
    use char_map::CharRange;
    use regex_syntax;

    fn parse(s: &str) -> regex_syntax::Result<NfaBuilder> {
        let expr = try!(regex_syntax::Expr::parse(s));
        Ok(NfaBuilder::from_expr(&expr))
    }

    fn make_builder(n_states: usize) -> NfaBuilder {
        let mut ret = NfaBuilder { states: Vec::new() };
        for _ in 0..n_states {
            ret.states.push(BuilderState::new());
        }
        ret
    }

    #[test]
    fn test_char_class() {
        let builder = parse("[a-z][A-Z]").unwrap();
        let mut target = make_builder(4);
        target.states[0].chars.push(CharRange::new('a' as u32, 'z' as u32));
        target.add_eps(1, 2);
        target.states[2].chars.push(CharRange::new('A' as u32, 'Z' as u32));

        assert_eq!(builder, target);
    }

    #[test]
    fn test_literal() {
        let builder = parse("aZ").unwrap();
        let mut target = make_builder(3);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[1].chars.push(CharRange::single('Z' as u32));

        assert_eq!(builder, target);
    }

    #[test]
    fn test_repeat_zero_or_more() {
        let builder = parse("ab*z").unwrap();
        let builder2 = parse("ab{0,}z").unwrap();
        let mut target = make_builder(6);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('b' as u32));
        target.states[4].chars.push(CharRange::single('z' as u32));
        target.add_eps(1, 2);
        target.add_eps(2, 3);
        target.add_eps(3, 2);
        target.add_eps(3, 4);

        assert_eq!(builder, target);
        assert_eq!(builder2, target);
    }

    #[test]
    fn test_repeat_one_or_more() {
        let builder = parse("ab+z").unwrap();
        let builder2 = parse("ab{1,}z").unwrap();
        let mut target = make_builder(6);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('b' as u32));
        target.states[4].chars.push(CharRange::single('z' as u32));
        target.add_eps(1, 2);
        target.add_eps(3, 2);
        target.add_eps(3, 4);

        assert_eq!(builder, target);
        assert_eq!(builder2, target);
    }

    #[test]
    fn test_repeat_zero_or_one() {
        let builder = parse("ab?z").unwrap();
        let builder2 = parse("ab{0,1}z").unwrap();
        let mut target = make_builder(6);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('b' as u32));
        target.states[4].chars.push(CharRange::single('z' as u32));
        target.add_eps(1, 2);
        target.add_eps(2, 3);
        target.add_eps(3, 4);

        assert_eq!(builder, target);
        assert_eq!(builder2, target);
    }

    #[test]
    fn test_repeat_exact() {
        let builder = parse("ab{3}z").unwrap();
        let mut target = make_builder(10);
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[2].chars.push(CharRange::single('b' as u32));
        target.states[4].chars.push(CharRange::single('b' as u32));
        target.states[6].chars.push(CharRange::single('b' as u32));
        target.states[8].chars.push(CharRange::single('z' as u32));
        target.add_eps(1, 2);
        target.add_eps(3, 4);
        target.add_eps(5, 6);
        target.add_eps(7, 8);

        assert_eq!(builder, target);
    }

    #[test]
    fn test_repeat_between() {
        let builder = parse("a{2,4}z").unwrap();
        let mut target = parse("a{4}z").unwrap();
        target.add_eps(4, 7);
        target.add_eps(6, 7);

        assert_eq!(builder, target);

        let builder = parse("a{0,2}z").unwrap();
        let mut target = parse("a{2}z").unwrap();
        target.add_eps(0, 3);
        target.add_eps(2, 3);

        assert_eq!(builder, target);
    }

    #[test]
    fn test_alternate() {
        let builder = parse("a|z").unwrap();
        let mut target = make_builder(6);
        target.states[1].chars.push(CharRange::single('a' as u32));
        target.states[3].chars.push(CharRange::single('z' as u32));
        target.add_eps(0, 1);
        target.add_eps(2, 5);
        target.add_eps(0, 3);
        target.add_eps(4, 5);

        assert_eq!(builder, target);
    }

    #[test]
    fn test_case_insensitive() {
        let builder = parse("(?i)ab").unwrap();
        let mut target = make_builder(3);
        target.states[0].chars.push(CharRange::single('A' as u32));
        target.states[0].chars.push(CharRange::single('a' as u32));
        target.states[1].chars.push(CharRange::single('B' as u32));
        target.states[1].chars.push(CharRange::single('b' as u32));

        assert_eq!(builder, target);
    }
}

<|endoftext|>


<commit_before>use std::env;
use std::error::Error as StdError;
use std::io::Write;
use std::time::Instant;

use atty;
use chrono::Duration;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};

use errors::Error;
use site::Site;

lazy_static! {
    /// Termcolor color choice.
    /// We do not rely on ColorChoice::Auto behavior
    /// as the check is already performed by has_color.
    static ref COLOR_CHOICE: ColorChoice =
        if has_color() {
            ColorChoice::Always
        } else {
            ColorChoice::Never
        };
}

pub fn info(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true));
}

pub fn warn(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Yellow)));
}

pub fn success(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Green)));
}

pub fn error(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Red)));
}

/// Print a colorized message to stdout
fn colorize(message: &str, color: &ColorSpec) {
    let mut stdout = StandardStream::stdout(*COLOR_CHOICE);
    stdout.set_color(color).unwrap();
    writeln!(&mut stdout, "{}", message).unwrap();
    stdout.set_color(&ColorSpec::new()).unwrap();
}

/// Display in the console the number of pages/sections in the site, and number of images to process
pub fn notify_site_size(site: &Site) {
    let library = site.library.read().unwrap();
    println!(
        "-> Creating {} pages ({} orphan), {} sections, and processing {} images",
        library.pages().len(),
        site.get_number_orphan_pages(),
        library.sections().len() - 1, // -1 since we do not count the index as a section there
        site.num_img_ops(),
    );
}

/// Display in the console only the number of pages/sections in the site
pub fn check_site_summary(site: &Site) {
    let library = site.library.read().unwrap();
    let orphans = library.get_all_orphan_pages();
    println!(
        "-> Site content: {} pages ({} orphan), {} sections",
        library.pages().len(),
        orphans.len(),
        library.sections().len() - 1, // -1 since we do not count the index as a section there
    );

    for orphan in orphans {
        warn(&format!("Orphan page found: {}", orphan.path));
    }
}

/// Display a warning in the console if there are ignored pages in the site
pub fn warn_about_ignored_pages(site: &Site) {
    let library = site.library.read().unwrap();
    let ignored_pages: Vec<_> = library
        .sections_values()
        .iter()
        .flat_map(|s| s.ignored_pages.iter().map(|k| library.get_page_by_key(*k).file.path.clone()))
        .collect();

    if !ignored_pages.is_empty() {
        warn(&format!(
            "{} page(s) ignored (missing date or weight in a sorted section):",
            ignored_pages.len()
        ));
        for path in ignored_pages {
            warn(&format!("- {}", path.display()));
        }
    }
}

/// Print the time elapsed rounded to 1 decimal
pub fn report_elapsed_time(instant: Instant) {
    let duration_ms = Duration::from_std(instant.elapsed()).unwrap().num_milliseconds() as f64;

    if duration_ms < 1000.0 {
        success(&format!("Done in {}ms.\n", duration_ms));
    } else {
        let duration_sec = duration_ms / 1000.0;
        success(&format!("Done in {:.1}s.\n", ((duration_sec * 10.0).round() / 10.0)));
    }
}

/// Display an error message and the actual error(s)
pub fn unravel_errors(message: &str, error: &Error) {
    if !message.is_empty() {
        self::error(message);
    }
    self::error(&format!("Error: {}", error));
    let mut cause = error.source();
    while let Some(e) = cause {
        self::error(&format!("Reason: {}", e));
        cause = e.source();
    }
}

/// Check whether to output colors
fn has_color() -> bool {
    let use_colors = env::var("CLICOLOR").unwrap_or_else(|_| "1".to_string()) != "0"
        && env::var("NO_COLOR").is_err();
    let force_colors = env::var("CLICOLOR_FORCE").unwrap_or_else(|_| "0".to_string()) != "0";

    force_colors || use_colors && atty::is(atty::Stream::Stdout)
}
<commit_msg>Reset color after writing message in colorize<commit_after>use std::env;
use std::error::Error as StdError;
use std::io::Write;
use std::time::Instant;

use atty;
use chrono::Duration;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};

use errors::Error;
use site::Site;

lazy_static! {
    /// Termcolor color choice.
    /// We do not rely on ColorChoice::Auto behavior
    /// as the check is already performed by has_color.
    static ref COLOR_CHOICE: ColorChoice =
        if has_color() {
            ColorChoice::Always
        } else {
            ColorChoice::Never
        };
}

pub fn info(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true));
}

pub fn warn(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Yellow)));
}

pub fn success(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Green)));
}

pub fn error(message: &str) {
    colorize(message, ColorSpec::new().set_bold(true).set_fg(Some(Color::Red)));
}

/// Print a colorized message to stdout
fn colorize(message: &str, color: &ColorSpec) {
    let mut stdout = StandardStream::stdout(*COLOR_CHOICE);
    stdout.set_color(color).unwrap();
    write!(&mut stdout, "{}", message).unwrap();
    stdout.set_color(&ColorSpec::new()).unwrap();
    writeln!(&mut stdout).unwrap();
}

/// Display in the console the number of pages/sections in the site, and number of images to process
pub fn notify_site_size(site: &Site) {
    let library = site.library.read().unwrap();
    println!(
        "-> Creating {} pages ({} orphan), {} sections, and processing {} images",
        library.pages().len(),
        site.get_number_orphan_pages(),
        library.sections().len() - 1, // -1 since we do not count the index as a section there
        site.num_img_ops(),
    );
}

/// Display in the console only the number of pages/sections in the site
pub fn check_site_summary(site: &Site) {
    let library = site.library.read().unwrap();
    let orphans = library.get_all_orphan_pages();
    println!(
        "-> Site content: {} pages ({} orphan), {} sections",
        library.pages().len(),
        orphans.len(),
        library.sections().len() - 1, // -1 since we do not count the index as a section there
    );

    for orphan in orphans {
        warn(&format!("Orphan page found: {}", orphan.path));
    }
}

/// Display a warning in the console if there are ignored pages in the site
pub fn warn_about_ignored_pages(site: &Site) {
    let library = site.library.read().unwrap();
    let ignored_pages: Vec<_> = library
        .sections_values()
        .iter()
        .flat_map(|s| s.ignored_pages.iter().map(|k| library.get_page_by_key(*k).file.path.clone()))
        .collect();

    if !ignored_pages.is_empty() {
        warn(&format!(
            "{} page(s) ignored (missing date or weight in a sorted section):",
            ignored_pages.len()
        ));
        for path in ignored_pages {
            warn(&format!("- {}", path.display()));
        }
    }
}

/// Print the time elapsed rounded to 1 decimal
pub fn report_elapsed_time(instant: Instant) {
    let duration_ms = Duration::from_std(instant.elapsed()).unwrap().num_milliseconds() as f64;

    if duration_ms < 1000.0 {
        success(&format!("Done in {}ms.\n", duration_ms));
    } else {
        let duration_sec = duration_ms / 1000.0;
        success(&format!("Done in {:.1}s.\n", ((duration_sec * 10.0).round() / 10.0)));
    }
}

/// Display an error message and the actual error(s)
pub fn unravel_errors(message: &str, error: &Error) {
    if !message.is_empty() {
        self::error(message);
    }
    self::error(&format!("Error: {}", error));
    let mut cause = error.source();
    while let Some(e) = cause {
        self::error(&format!("Reason: {}", e));
        cause = e.source();
    }
}

/// Check whether to output colors
fn has_color() -> bool {
    let use_colors = env::var("CLICOLOR").unwrap_or_else(|_| "1".to_string()) != "0"
        && env::var("NO_COLOR").is_err();
    let force_colors = env::var("CLICOLOR_FORCE").unwrap_or_else(|_| "0".to_string()) != "0";

    force_colors || use_colors && atty::is(atty::Stream::Stdout)
}
<|endoftext|>


<commit_before>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate image;

use std::io::Cursor;
use image::ImageResult;
use image::codecs::openexr::*;

// "just dont panic"
fn roundtrip(bytes: &[u8]) -> ImageResult<()> {

    /// Read the file from the specified path into an `Rgba32FImage`.
    fn read_as_rgba_image(read: impl BufRead + Seek) -> ImageResult<Rgb32FImage> {
        let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?;
        let (width, height) = decoder.dimensions();
        let buffer: Vec<f32> = decoder_to_vec(decoder)?;

        ImageBuffer::from_raw(width, height, buffer)

            // this should be the only reason for the "from raw" call to fail,
            // even though such a large allocation would probably cause an error much earlier
            .ok_or_else(|| ImageError::Limits(LimitError::from_kind(LimitErrorKind::InsufficientMemory)))
    }

    /// Write an `Rgba32FImage`.
    /// Assumes the writer is buffered. In most cases,
    /// you should wrap your writer in a `BufWriter` for best performance.
    fn write_rgba_image(write: impl Write/* + Seek*/, image: &Rgba32FImage) -> ImageResult<()> {
        OpenEXREncoder::new(write).write_image(
            bytemuck::cast_slice(image.as_raw().as_slice()),
            image.width(), image.height(),
            ColorType::Rgba32F
        )
    }

    let decoded_image = read_as_rgba_image(Cursor::new(bytes))?;

    let mut bytes = Vec::with_capacity(bytes.len() + 20);
    write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?;
    let redecoded_image = read_as_rgba_image(Cursor::new(bytes))?;

    // if both images are valid, assert read/write consistency
    assert_eq!(decoded_image, redecoded_image, "image was valid but was not reproducible");
    Ok(())
}

fuzz_target!(|data: &[u8]| {
    let _img = roundtrip(data); // fixme not optimized away?
});
<commit_msg>re-implement even more helper methods copy&paste for external fuzzer test script<commit_after>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate image;
extern crate bytemuck;

use std::io::Cursor;
use image::ImageResult;
use image::codecs::openexr::*;
use image::Rgba32FImage;
use image::error::LimitError;
use image::ImageError;
use image::ImageBuffer;
use image::Rgb32FImage;
use std::io::Seek;
use std::io::BufRead;

// "just dont panic"
fn roundtrip(bytes: &[u8]) -> ImageResult<()> {
    use std::io::Write;

    /// Read the file from the specified path into an `Rgba32FImage`.
    // TODO this method should probably already exist in the main image crate
    fn read_as_rgba_image(read: impl BufRead + Seek) -> ImageResult<Rgb32FImage> {

        // TODO this method should probably already exist in the main image crate
        fn decoder_to_vec<'a, T>(decoder: impl ImageDecoder<'a>) -> ImageResult<Vec<T>>
            where T: crate::traits::Primitive + bytemuck::Pod,
        {
            let mut buf = vec![num_traits::Zero::zero(); usize::try_from(decoder.total_bytes()).unwrap() / std::mem::size_of::<T>()];
            decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;
            Ok(buf)
        }

        let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?;
        let (width, height) = decoder.dimensions();
        let buffer: Vec<f32> = decoder_to_vec(decoder)?;

        ImageBuffer::from_raw(width, height, buffer)

            // this should be the only reason for the "from raw" call to fail,
            // even though such a large allocation would probably cause an error much earlier
            .ok_or_else(|| ImageError::Limits(LimitError::from_kind(LimitErrorKind::InsufficientMemory)))
    }

    /// Write an `Rgba32FImage`.
    /// Assumes the writer is buffered. In most cases,
    /// you should wrap your writer in a `BufWriter` for best performance.
    // TODO this method should probably already exist in the main image crate
    fn write_rgba_image(write: impl Write/* + Seek*/, image: &Rgba32FImage) -> ImageResult<()> {
        OpenEXREncoder::new(write).write_image(
            bytemuck::cast_slice(image.as_raw().as_slice()),
            image.width(), image.height(),
            ColorType::Rgba32F
        )
    }

    let decoded_image = read_as_rgba_image(Cursor::new(bytes))?;

    let mut bytes = Vec::with_capacity(bytes.len() + 20);
    write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?;
    let redecoded_image = read_as_rgba_image(Cursor::new(bytes))?;

    // if both images are valid, assert read/write consistency
    assert_eq!(decoded_image, redecoded_image, "image was valid but was not reproducible");
    Ok(())
}

fuzz_target!(|data: &[u8]| {
    let _img = roundtrip(data); // fixme not optimized away?
});
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(glassful_macros)]
#![deny(warnings)]

#[allow(dead_code)]
const TEST_PROG: &'static str = glassful! {
    #![version="110"]

    static foo: f32 = 3.0;

    #[varying] static zed: vec2 = UNINIT;
    #[uniform] static prev_frame: sampler2D = UNINIT;
    #[uniform] static _p_scale: f32 = UNINIT;

    fn complex_to_tex(p: vec2) -> vec2 {
        (0.5/_p_scale)*p + vec2(0.5, 0.5)
    }

    fn complex_mul(a: vec2, b: vec2) -> vec2 {
        vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x)
    }

    fn in_bounds(p: vec2) -> bool {
        macro_rules! check {
            ($i:ident) => ((p.$i >= -_p_scale) && (p.$i <= _p_scale))
        }

        check!(x) && check!(y)
    }

    #[uniform] static param: vec2 = UNINIT;

    fn main() {
        let color: vec3;
        let oldpoint: vec2 = complex_mul(zed, zed) + 1.6*param;

        if in_bounds(oldpoint) {
            let oldcoord: vec2 = complex_to_tex(oldpoint);
            color = 1.8*texture2D(prev_frame, oldcoord).brg;
        } else {
            color = vec3(1.0, 0.0, 0.0);
        }

        gl_FragColor = vec4(color, 1.0);
    }
};

#[test]
fn smoke_test() { }
<commit_msg>Fix smoke-test.rs<commit_after>#![feature(plugin)]
#![plugin(glassful_macros)]
#![deny(warnings)]

#[allow(dead_code)]
const TEST_PROG: (&'static str, &'static str) = glassful! {
    #![version="110"]

    const foo: f32 = 3.0;

    static prev_frame: sampler2D = UNINIT;
    static _p_scale: f32 = UNINIT;
    static param: vec2 = UNINIT;

    fn complex_to_tex(p: vec2) -> vec2 {
        (0.5/_p_scale)*p + vec2(0.5, 0.5)
    }

    fn complex_mul(a: vec2, b: vec2) -> vec2 {
        vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x)
    }

    fn in_bounds(p: vec2) -> bool {
        macro_rules! check {
            ($i:ident) => ((p.$i >= -_p_scale) && (p.$i <= _p_scale))
        }

        check!(x) && check!(y)
    }

    #[vertex]
    fn vert() {

    }

    #[fragment]
    fn frag(zed: Vec2) {
        let color: vec3;
        let oldpoint: vec2 = complex_mul(zed, zed) + 1.6*param;

        if in_bounds(oldpoint) {
            let oldcoord: vec2 = complex_to_tex(oldpoint);
            color = 1.8*texture2D(prev_frame, oldcoord).brg;
        } else {
            color = vec3(1.0, 0.0, 0.0);
        }

        gl_FragColor = vec4(color, 1.0);
    }
};

#[test]
fn smoke_test() { }
<|endoftext|>


<commit_before>use std::collections::btree_map;
use std::collections::btree_map::{BTreeMap, Entry, Keys};
use std::iter::{FromIterator, IntoIterator};
use std::cmp::{Ordering};

#[derive(Clone, Debug, PartialOrd, PartialEq, Ord, Eq)]
pub struct Index<T> {
    items: BTreeMap<T, usize>,
}

// #[derive(Debug)] Keys does not implement Debug :(
pub struct Iter<'a, T> where T: 'a {
    keys: Keys<'a, T, usize>,
}

#[derive(Clone, Debug)]
pub struct Changes<T> {
    pub inserted: Vec<T>,
    pub removed: Vec<T>,
}

impl<T: Ord + Clone> Index<T> {
    pub fn new() -> Self {
        Index{items: BTreeMap::new()}
    }

    pub fn insert(&mut self, item: T) {
        match self.items.entry(item) {
            Entry::Vacant(vacant) => {
                vacant.insert(1);
            }
            Entry::Occupied(mut occupied) => {
                let existing_count = *occupied.get();
                occupied.insert(existing_count + 1);
            }
        }
    }

    pub fn remove(&mut self, item: T) {
        match self.items.entry(item) {
            Entry::Vacant(_) => {
                panic!("Removed a non-existing entry");
            }
            Entry::Occupied(mut occupied) => {
                let new_count = *occupied.get() - 1;
                if new_count > 0 {
                    occupied.insert(new_count);
                } else if new_count == 0 {
                    occupied.remove();
                } else {
                    panic!("Removed a non-existing entry");
                }
            }
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter{keys: self.items.keys()}
    }

    pub fn change(&mut self, changes: Changes<T>) {
        for item in changes.removed {
            self.remove(item);
        }
        for item in changes.inserted {
            self.insert(item);
        }
    }

    pub fn changes_since(&self, before: &Index<T>) -> Changes<T> {
            let mut before_keys = before.items.keys();
            let mut after_keys = self.items.keys();
            let mut before_key = before_keys.next();
            let mut after_key = after_keys.next();
            let mut inserted = Vec::new();
            let mut removed = Vec::new();
            loop {
                match (before_key, after_key) {
                    (None, None) => {
                        break;
                    }
                    (Some(before), None) => {
                        removed.push(before.clone());
                        before_key = before_keys.next();
                    }
                    (None, Some(after)) => {
                        inserted.push(after.clone());
                        after_key = after_keys.next();
                    }
                    (Some(before), Some(after)) => {
                        match before.cmp(after) {
                            Ordering::Less => {
                                removed.push(before.clone());
                                before_key = before_keys.next();
                            }
                            Ordering::Greater => {
                                inserted.push(after.clone());
                                after_key = after_keys.next();
                            }
                            Ordering::Equal => {
                                before_key = before_keys.next();
                                after_key = after_keys.next();
                            }
                        }
                    }
                }
            }
            Changes{inserted: inserted, removed: removed}
    }
}

impl<'a, T: Ord> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.keys.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.keys.size_hint()
    }
}

impl<T: Ord> FromIterator<T> for Index<T> {
    fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> Self {
        Index{items: BTreeMap::from_iter(
            iterable.into_iter().map(|item| (item, 1))
            )}
    }
}

pub struct IntoIter<T> {
    items: btree_map::IntoIter<T, usize>
}

impl<T: Ord> Iterator for IntoIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        self.items.next().map(|(key, _)| key)
    }
}

impl<T: Ord> IntoIterator for Index<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> IntoIter<T> {
        IntoIter{items: self.items.into_iter()}
    }
}<commit_msg>Handle negative counts<commit_after>use std::collections::btree_map;
use std::collections::btree_map::{BTreeMap, Entry, Keys};
use std::iter::{FromIterator, IntoIterator};
use std::cmp::{Ordering};

#[derive(Clone, Debug, PartialOrd, PartialEq, Ord, Eq)]
pub struct Index<T> {
    items: BTreeMap<T, usize>,
}

// #[derive(Debug)] Keys does not implement Debug :(
pub struct Iter<'a, T> where T: 'a {
    iter: btree_map::Iter<'a, T, usize>,
}

#[derive(Clone, Debug)]
pub struct Changes<T> {
    pub inserted: Vec<T>,
    pub removed: Vec<T>,
}

impl<T: Ord + Clone> Index<T> {
    pub fn new() -> Self {
        Index{items: BTreeMap::new()}
    }

    pub fn insert(&mut self, item: T) {
        match self.items.entry(item) {
            Entry::Vacant(vacant) => {
                vacant.insert(1);
            }
            Entry::Occupied(mut occupied) => {
                let existing_count = *occupied.get();
                occupied.insert(existing_count + 1);
            }
        }
    }

    pub fn remove(&mut self, item: T) {
        match self.items.entry(item) {
            Entry::Vacant(mut vacant) => {
                vacant.insert(-1);
            }
            Entry::Occupied(mut occupied) => {
                let new_count = *occupied.get() - 1;
                if new_count != 0 {
                    occupied.insert(new_count);
                } else {
                    occupied.remove();
                }
            }
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter{iter: self.items.iter()}
    }

    pub fn change(&mut self, changes: Changes<T>) {
        for item in changes.removed {
            self.remove(item);
        }
        for item in changes.inserted {
            self.insert(item);
        }
    }

    pub fn changes_since(&self, before: &Index<T>) -> Changes<T> {
            let mut before_keys = before.items.keys();
            let mut after_keys = self.items.keys();
            let mut before_key = before_keys.next();
            let mut after_key = after_keys.next();
            let mut inserted = Vec::new();
            let mut removed = Vec::new();
            loop {
                match (before_key, after_key) {
                    (None, None) => {
                        break;
                    }
                    (Some(before), None) => {
                        removed.push(before.clone());
                        before_key = before_keys.next();
                    }
                    (None, Some(after)) => {
                        inserted.push(after.clone());
                        after_key = after_keys.next();
                    }
                    (Some(before), Some(after)) => {
                        match before.cmp(after) {
                            Ordering::Less => {
                                removed.push(before.clone());
                                before_key = before_keys.next();
                            }
                            Ordering::Greater => {
                                inserted.push(after.clone());
                                after_key = after_keys.next();
                            }
                            Ordering::Equal => {
                                before_key = before_keys.next();
                                after_key = after_keys.next();
                            }
                        }
                    }
                }
            }
            Changes{inserted: inserted, removed: removed}
    }
}

impl<'a, T: Ord> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        loop {
            match self.iter.next() {
                None => return None,
                Some((item, count)) if *count > 0 => return Some(item),
                _ => continue,
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<T: Ord> FromIterator<T> for Index<T> {
    fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> Self {
        Index{items: BTreeMap::from_iter(
            iterable.into_iter().map(|item| (item, 1))
            )}
    }
}

pub struct IntoIter<T> {
    items: btree_map::IntoIter<T, usize>
}

impl<T: Ord> Iterator for IntoIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        self.items.next().map(|(key, _)| key)
    }
}

impl<T: Ord> IntoIterator for Index<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> IntoIter<T> {
        IntoIter{items: self.items.into_iter()}
    }
}<|endoftext|>


<commit_before>use business::usecase::{NewEntry, UpdateEntry};
use entities::Entry;

pub fn email_confirmation_email(u_id: &str) -> String {
    format!("Na du Weltverbesserer*,\nwir freuen uns dass du bei der Karte von Morgen mit dabei bist!\nBitte bestätige deine Email-Adresse hier:\nhttps://prototyp.kartevonmorgen.org/#/?confirm_email={}.\neuphorische Grüße ;)\ndas Karte von Morgen-Team",
    u_id)
}

pub fn new_entry_email(e: &NewEntry, id: &str, categories: Vec<String>) -> String {
    let intro_sentence = "ein neuer Eintrag auf der Karte von Morgen wurde erstellt";
    let entry = Entry {
        id : id.into(),
        title:e.title.clone(),
        description:e.description.clone(),
        street:e.street.clone(),
        zip:e.zip.clone(),
        city:e.city.clone(),
        country :e.country.clone(),
        email:e.email.clone(),
        telephone:e.telephone.clone(),
        homepage:e.homepage.clone(),
        categories:e.categories.clone(),
        lat:0.0,
        lng:0.0,
        created:0,
        version:0,
        license:None
    };
    entry_email(&entry, categories, &e.tags, intro_sentence)
}

pub fn changed_entry_email(e: &UpdateEntry, categories: Vec<String>) -> String {
    let intro_sentence = "folgender Eintrag der Karte von Morgen wurde verändert";
    let entry = Entry {
        id : e.id.clone(),
        title:e.title.clone(),
        description:e.description.clone(),
        street:e.street.clone(),
        zip:e.zip.clone(),
        city:e.city.clone(),
        country :e.country.clone(),
        email:e.email.clone(),
        telephone:e.telephone.clone(),
        homepage:e.homepage.clone(),
        categories:e.categories.clone(),
        lat:0.0,
        lng:0.0,
        created:0,
        version:0,
        license:None
    };
    entry_email(&entry, categories, &e.tags, intro_sentence)
}

fn entry_email(e: &Entry, categories: Vec<String>, tags: &Vec<String>, intro_sentence: &str) -> String{
    let category = if categories.len() > 0 { categories[0].clone() } else { "".to_string() };

    format!(
"Hallo,
{introSentence}:\n
    {title} ({category})
{description}\n
    Tags: {tags}
    Adresse: {street}, {zip} {city}, {country}
    Webseite: {homepage}
    Email-Adresse: {email}
    Telefon: {telephone}\n
Eintrag anschauen oder bearbeiten:
https://prototyp.kartevonmorgen.org/#/?entry={id}\n
Du kannst dein Abonnement des Kartenbereichs abbestellen indem du dich auf https://prototyp.kartevonmorgen.org einloggst.\n
euphorische Grüße ;)
das Karte von Morgen-Team",
        introSentence = intro_sentence,
        title = &e.title,
        id = &e.id,
        description= &e.description,
        street = e.street.clone().unwrap_or("".into()),
        zip = e.zip.clone().unwrap_or("".into()),
        city = e.city.clone().unwrap_or("".into()),
        country = e.country.clone().unwrap_or("".into()),
        email = e.email.clone().unwrap_or("".into()),
        telephone = e.telephone.clone().unwrap_or("".into()),
        homepage = e.homepage.clone().unwrap_or("".into()),
        category = category,
        tags = tags.join(", "))
}<commit_msg>fix(login): fixed email confirmation text<commit_after>use business::usecase::{NewEntry, UpdateEntry};
use entities::Entry;

pub fn email_confirmation_email(u_id: &str) -> String {
    format!("Na du Weltverbesserer*,\nwir freuen uns dass du bei der Karte von Morgen mit dabei bist!\nBitte bestätige deine Email-Adresse hier:\nhttps://prototyp.kartevonmorgen.org/#/?confirm_email={}.\n\neuphorische Grüße\ndas Karte von Morgen-Team",
    u_id)
}

pub fn new_entry_email(e: &NewEntry, id: &str, categories: Vec<String>) -> String {
    let intro_sentence = "ein neuer Eintrag auf der Karte von Morgen wurde erstellt";
    let entry = Entry {
        id : id.into(),
        title:e.title.clone(),
        description:e.description.clone(),
        street:e.street.clone(),
        zip:e.zip.clone(),
        city:e.city.clone(),
        country :e.country.clone(),
        email:e.email.clone(),
        telephone:e.telephone.clone(),
        homepage:e.homepage.clone(),
        categories:e.categories.clone(),
        lat:0.0,
        lng:0.0,
        created:0,
        version:0,
        license:None
    };
    entry_email(&entry, categories, &e.tags, intro_sentence)
}

pub fn changed_entry_email(e: &UpdateEntry, categories: Vec<String>) -> String {
    let intro_sentence = "folgender Eintrag der Karte von Morgen wurde verändert";
    let entry = Entry {
        id : e.id.clone(),
        title:e.title.clone(),
        description:e.description.clone(),
        street:e.street.clone(),
        zip:e.zip.clone(),
        city:e.city.clone(),
        country :e.country.clone(),
        email:e.email.clone(),
        telephone:e.telephone.clone(),
        homepage:e.homepage.clone(),
        categories:e.categories.clone(),
        lat:0.0,
        lng:0.0,
        created:0,
        version:0,
        license:None
    };
    entry_email(&entry, categories, &e.tags, intro_sentence)
}

fn entry_email(e: &Entry, categories: Vec<String>, tags: &Vec<String>, intro_sentence: &str) -> String{
    let category = if categories.len() > 0 { categories[0].clone() } else { "".to_string() };

    format!(
"Hallo,
{introSentence}:\n
    {title} ({category})
{description}\n
    Tags: {tags}
    Adresse: {street}, {zip} {city}, {country}
    Webseite: {homepage}
    Email-Adresse: {email}
    Telefon: {telephone}\n
Eintrag anschauen oder bearbeiten:
https://prototyp.kartevonmorgen.org/#/?entry={id}\n
Du kannst dein Abonnement des Kartenbereichs abbestellen indem du dich auf https://prototyp.kartevonmorgen.org einloggst.\n
euphorische Grüße
das Karte von Morgen-Team",
        introSentence = intro_sentence,
        title = &e.title,
        id = &e.id,
        description= &e.description,
        street = e.street.clone().unwrap_or("".into()),
        zip = e.zip.clone().unwrap_or("".into()),
        city = e.city.clone().unwrap_or("".into()),
        country = e.country.clone().unwrap_or("".into()),
        email = e.email.clone().unwrap_or("".into()),
        telephone = e.telephone.clone().unwrap_or("".into()),
        homepage = e.homepage.clone().unwrap_or("".into()),
        category = category,
        tags = tags.join(", "))
}<|endoftext|>


<commit_before>
struct AdaptonState {
    foo : bool,
}

trait Computer<Res> {
    type Arg;
    fn compute(self:&Self, st:&mut AdaptonState, arg:Self::Arg) -> Res;
    //fn size_hint(&self) -> (usize, Option<usize>) { ... }
}

struct ComputeNode<Res,Comp:Computer<Res>> {
    arg : Comp::Arg,
    res : Option<Res>,
    comp : Box<Comp>,
}

trait Nd where Self::Comp : Computer<Self::Res> {
    type Res;
    type Comp;
    fn get_node<'x>(self:&'x mut Self) -> &'x mut ComputeNode<Self::Res,Self::Comp>;
}

fn main () {

}
<commit_msg>filed issue with rustc<commit_after>// Filed issue:
// https://github.com/rust-lang/rust/issues/21909

trait A<X> { }
trait B { type X; type Y : A<Self::X>; }
fn main () { }
<|endoftext|>


<commit_before>extern crate conduit;
extern crate civet;
extern crate green;
extern crate rustuv;
extern crate routing = "route-recognizer";

use std::io::{IoResult, MemReader};
use std::collections::HashMap;
use std::fmt::Show;

use civet::{Config, Server, response};
use conduit::{Request, Response};
use routing::{Router, Params};

struct MyServer {
    router: Router<fn(&mut Request, &Params) -> IoResult<Response>>,
}

impl conduit::Handler for MyServer {
    fn call(&self, req: &mut Request) -> Result<Response, Box<Show + 'static>> {
        let hit = match self.router.recognize(req.path()) {
            Ok(m) => m,
            Err(e) => fail!("{}", e),
        };
        (*hit.handler)(req, &hit.params).map_err(|e| box e as Box<Show>)
    }
}

fn main() {
    let mut server = MyServer {
        router: Router::new(),
    };
    server.router.add("/:id", id);
    server.router.add("/", root);
    let _a = Server::start(Config { port: 8888, threads: 50 }, server);
    wait_for_sigint();
}

// libnative doesn't have signal handling yet
fn wait_for_sigint() {
    use green::{SchedPool, PoolConfig, GreenTaskBuilder};
    use std::io::signal::{Listener, Interrupt};
    use std::task::TaskBuilder;

    let mut config = PoolConfig::new();
    config.event_loop_factory = rustuv::event_loop;

    let mut pool = SchedPool::new(config);
    TaskBuilder::new().green(&mut pool).spawn(proc() {
        let mut l = Listener::new();
        l.register(Interrupt).unwrap();
        l.rx.recv();
    });
    pool.shutdown();
}

fn root(_req: &mut Request, _params: &Params) -> IoResult<Response> {
    let bytes = b"you found the root!\n".to_vec();
    Ok(response(200i, HashMap::new(), MemReader::new(bytes)))
}

fn id(_req: &mut Request, params: &Params) -> IoResult<Response> {
    let string = format!("you found the id {}!\n", params["id"]);
    let bytes = string.into_bytes();

    Ok(response(200i, HashMap::new(), MemReader::new(bytes)))
}
<commit_msg>Update to master<commit_after>extern crate conduit;
extern crate civet;
extern crate green;
extern crate rustuv;
extern crate "route-recognizer" as routing;

use std::io::{IoResult, MemReader};
use std::collections::HashMap;
use std::fmt::Show;

use civet::{Config, Server, response};
use conduit::{Request, Response};
use routing::{Router, Params};

struct MyServer {
    router: Router<fn(&mut Request, &Params) -> IoResult<Response>>,
}

impl conduit::Handler for MyServer {
    fn call(&self, req: &mut Request) -> Result<Response, Box<Show + 'static>> {
        let hit = match self.router.recognize(req.path()) {
            Ok(m) => m,
            Err(e) => fail!("{}", e),
        };
        (*hit.handler)(req, &hit.params).map_err(|e| box e as Box<Show>)
    }
}

fn main() {
    let mut server = MyServer {
        router: Router::new(),
    };
    server.router.add("/:id", id);
    server.router.add("/", root);
    let _a = Server::start(Config { port: 8888, threads: 50 }, server);
    wait_for_sigint();
}

// libnative doesn't have signal handling yet
fn wait_for_sigint() {
    use green::{SchedPool, PoolConfig, GreenTaskBuilder};
    use std::io::signal::{Listener, Interrupt};
    use std::task::TaskBuilder;

    let mut config = PoolConfig::new();
    config.event_loop_factory = rustuv::event_loop;

    let mut pool = SchedPool::new(config);
    TaskBuilder::new().green(&mut pool).spawn(proc() {
        let mut l = Listener::new();
        l.register(Interrupt).unwrap();
        l.rx.recv();
    });
    pool.shutdown();
}

fn root(_req: &mut Request, _params: &Params) -> IoResult<Response> {
    let bytes = b"you found the root!\n".to_vec();
    Ok(response(200i, HashMap::new(), MemReader::new(bytes)))
}

fn id(_req: &mut Request, params: &Params) -> IoResult<Response> {
    let string = format!("you found the id {}!\n", params["id"]);
    let bytes = string.into_bytes();

    Ok(response(200i, HashMap::new(), MemReader::new(bytes)))
}
<|endoftext|>