<commit_before>#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate quickcheck;

extern crate bytes;
#[macro_use]
extern crate combine;

extern crate futures;
extern crate partial_io;
extern crate tokio_io;

use std::cell::Cell;
use std::io::{self, Cursor};
use std::rc::Rc;
use std::str;

use bytes::BytesMut;

use futures::{Future, Stream};
use tokio_io::codec::FramedRead;

use tokio_io::codec::Decoder;

use combine::combinator::{
    any_partial_state, no_partial, optional, recognize, skip_many1, try, AnyPartialState,
};
use combine::parser::char::{char, digit, letter};
use combine::parser::item::item;
use combine::parser::range::{range, recognize_with_value, take_while, take_while1};
use combine::parser::repeat;
use combine::stream::{easy, RangeStream};
use combine::{any, count_min_max, many1, skip_many, Parser};

quick_error! {
    #[derive(Debug)]
    enum Error {
        Io(err: io::Error) {
            display("{}", err)
            from()
        }
        Parse(err: easy::Errors<char, String, usize>) {
            display("{}", err)
            from()
        }
        Utf8(err: std::str::Utf8Error) {
            display("{}", err)
            from()
        }
        Message(err: String) {
            display("{}", err)
            from()
        }
    }
}

macro_rules! mk_parser {
    ($parser:expr, $self_:expr,()) => {

        $parser
    };
    ($parser:expr, $self_:expr,($custom_state:ty)) => {

        $parser($self_.1.clone())
    };
}
macro_rules! impl_decoder {
    ($typ: ident, $item: ty, $parser: expr, $custom_state: ty) => {
        #[derive(Default)]
        struct $typ(AnyPartialState, $custom_state);
        impl_decoder!{$typ, $item, $parser; ($custom_state)}
    };
    ($typ: ident, $item: ty, $parser: expr) => {
        #[derive(Default)]
        struct $typ(AnyPartialState);
        impl_decoder!{$typ, $item, $parser; ()}
    };
    ($typ: ident, $item: ty, $parser: expr; ( $($custom_state: tt)* )) => {
        impl Decoder for $typ {
            type Item = $item;
            type Error = Error;

            fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
                (&mut &mut *self).decode(src)
            }
        }

        impl<'a> Decoder for &'a mut $typ {
            type Item = $item;
            type Error = Error;

            fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
                let (opt, removed_len) = {
                    let str_src = str::from_utf8(&src[..])?;
                    println!("Decoding `{}`", str_src);
                    combine::stream::decode(
                        any_partial_state(mk_parser!($parser, self, ($($custom_state)*))),
                        easy::Stream(combine::stream::PartialStream(str_src)),
                        &mut self.0,
                    ).map_err(|err| {
                        // Since err contains references into `src` we must remove these before
                        // returning the error and before we call `split_to` to remove the input we
                        // just consumed
                        let err = err.map_range(|r| r.to_string())
                            .map_position(|p| p.translate_position(&src[..]));
                        format!("{}\nIn input: `{}`", err, str_src)
                    })?
                };

                src.split_to(removed_len);
                match opt {
                    None => println!("Need more input!"),
                    Some(_) => (),
                }
                Ok(opt)
            }
        }
    }
}

use partial_io::{GenWouldBlock, PartialAsyncRead, PartialOp, PartialWithErrors};

fn run_decoder<D, S>(input: &str, seq: S, decoder: D) -> Result<Vec<D::Item>, D::Error>
where
    D: Decoder,
    D::Item: ::std::fmt::Display,
    S: IntoIterator<Item = PartialOp> + 'static,
    S::IntoIter: Send,
{
    let ref mut reader = Cursor::new(input.as_bytes());
    let partial_reader = PartialAsyncRead::new(reader, seq);
    FramedRead::new(partial_reader, decoder)
        .map(|x| {
            println!("Decoded `{}`", x);
            x
        })
        .collect()
        .wait()
}

parser!{
    type PartialState = AnyPartialState;
    fn basic_parser['a, I]()(I) -> String
        where [ I: RangeStream<Item = char, Range = &'a str> ]
    {
        any_partial_state(
            many1(digit()).skip(range(&"\r\n"[..])),
        )
    }
}

impl_decoder!{ Basic, String, basic_parser() }

#[test]
fn many1_skip_no_errors() {
    let input = "123\r\n\
                 456\r\n";

    let result = run_decoder(input, vec![], Basic::default());

    assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
    assert_eq!(result.unwrap(), vec!["123".to_string(), "456".to_string()]);
}

parser!{
    type PartialState = AnyPartialState;
    fn prefix_many_then_parser['a, I]()(I) -> String
        where [ I: RangeStream<Item = char, Range = &'a str> ]
    {
        any_partial_state((char('#'), skip_many(char(' ')), many1(digit()))
            .then_partial(|t| {
                let s: &String = &t.2;
                let c = s.parse().unwrap();
                count_min_max(c, c, any())
            })
        )
    }
}

parser!{
    type PartialState = AnyPartialState;
    fn choice_parser['a, I]()(I) -> String
        where [ I: RangeStream<Item = char, Range = &'a str> ]
    {
        any_partial_state(
            many1(digit())
                .or(many1(letter()))
                .skip(range(&"\r\n"[..]))
        )
    }
}

quickcheck! {
    fn many1_skip_test(seq: PartialWithErrors<GenWouldBlock>) -> () {

        let input = "123\r\n\
                     456\r\n\
                     1\r\n\
                     5\r\n\
                     666666\r\n";

        let result = run_decoder(input, seq, Basic::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            vec!["123".to_string(), "456".to_string(), "1".to_string(), "5".to_string(), "666666".to_string()]
        );
    }

    fn prefix_many_then_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String, prefix_many_then_parser() }

        let input = "# 1a\
                     # 4abcd\
                     #0\
                     #3:?a\
                     #10abcdefghij";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["a", "abcd", "", ":?a", "abcdefghij"]
        );
    }

    fn choice_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String, choice_parser() }

        let input = "1\r\n\
                     abcd\r\n\
                     123\r\n\
                     abc\r\n\
                     1232751\r\n";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1", "abcd", "123", "abc", "1232751"]
        );
    }

    fn recognize_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            recognize(
                (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
            )
                .skip(range(&"\r\n"[..]))
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     1.\r\n\
                     2\r\n";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "1.", "2"]
        );
    }

    fn recognize_range_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            recognize_with_value(
                (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
            )
                .map(|(r, _)| String::from(r))
                .skip(range(&"\r\n"[..]))
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     1.\r\n\
                     2\r\n";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "1.", "2"]
        );
    }

    fn take_while_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |counter: Rc<Cell<i32>>|
                take_while(move |c| { counter.set(counter.get() + 1); c != '\r' })
                    .map(String::from)
                    .skip(range("\r\n")),
            Rc<Cell<i32>>
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     \r\n\
                     2\r\n";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "", "2"]
        );

        assert_eq!(counter.get(), 26);
    }

    fn take_while1_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |count: Rc<Cell<i32>>|
                take_while1(move |c| { count.set(count.get() + 1); c != '\r' })
                    .map(String::from)
                    .skip(range("\r\n")),
            Rc<Cell<i32>>
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     1.\r\n\
                     2\r\n";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "1.", "2"]
        );

        assert_eq!(counter.get(), 28);
    }

    fn take_until(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |count: Rc<Cell<i32>>|
                repeat::take_until(item(',').map(move |_| count.set(count.get() + 1))).skip(item(',')),
            Rc<Cell<i32>>
        }

        let input = "123,456,789,";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["123", "456", "789"]
        );

        assert_eq!(counter.get(), 3);
    }

    fn take_until_consumed(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |count: Rc<Cell<i32>>| {
                let end = try((item(':').map(move |_| count.set(count.get() + 1)), item(':')));
                repeat::take_until(end).skip((item(':'), item(':')))
            },
            Rc<Cell<i32>>
        }

        let input = "123::456::789::";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["123", "456", "789"]
        );

        assert_eq!(counter.get(), 3);
    }
}
#[test]
fn inner_no_partial_test() {
    let seq = vec![PartialOp::Limited(10)];
    impl_decoder!{ TestParser, String,
        no_partial(many1(digit()))
            .or(many1(letter()))
            .skip(range(&"\r\n"[..]))
    }

    let input = "1\r\n\
                 abcd\r\n\
                 123\r\n\
                 abc\r\n\
                 1232751\r\n";

    let result = run_decoder(input, seq, TestParser::default());

    assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
    assert_eq!(result.unwrap(), ["1", "abcd", "123", "abc", "1232751"]);
}
<commit_msg>test: add failing test for take_until_range partial parses<commit_after>#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate quickcheck;

extern crate bytes;
#[macro_use]
extern crate combine;

extern crate futures;
extern crate partial_io;
extern crate tokio_io;

use std::cell::Cell;
use std::io::{self, Cursor};
use std::rc::Rc;
use std::str;

use bytes::BytesMut;

use futures::{Future, Stream};
use tokio_io::codec::FramedRead;

use tokio_io::codec::Decoder;

use combine::combinator::{
    any_partial_state, no_partial, optional, recognize, skip_many1, try, AnyPartialState,
};
use combine::parser::char::{char, digit, letter};
use combine::parser::item::item;
use combine::parser::range::{range, recognize_with_value, take_while, take_while1, take_until_range};
use combine::parser::repeat;
use combine::stream::{easy, RangeStream};
use combine::{any, count_min_max, many1, skip_many, Parser};

quick_error! {
    #[derive(Debug)]
    enum Error {
        Io(err: io::Error) {
            display("{}", err)
            from()
        }
        Parse(err: easy::Errors<char, String, usize>) {
            display("{}", err)
            from()
        }
        Utf8(err: std::str::Utf8Error) {
            display("{}", err)
            from()
        }
        Message(err: String) {
            display("{}", err)
            from()
        }
    }
}

macro_rules! mk_parser {
    ($parser:expr, $self_:expr,()) => {

        $parser
    };
    ($parser:expr, $self_:expr,($custom_state:ty)) => {

        $parser($self_.1.clone())
    };
}
macro_rules! impl_decoder {
    ($typ: ident, $item: ty, $parser: expr, $custom_state: ty) => {
        #[derive(Default)]
        struct $typ(AnyPartialState, $custom_state);
        impl_decoder!{$typ, $item, $parser; ($custom_state)}
    };
    ($typ: ident, $item: ty, $parser: expr) => {
        #[derive(Default)]
        struct $typ(AnyPartialState);
        impl_decoder!{$typ, $item, $parser; ()}
    };
    ($typ: ident, $item: ty, $parser: expr; ( $($custom_state: tt)* )) => {
        impl Decoder for $typ {
            type Item = $item;
            type Error = Error;

            fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
                (&mut &mut *self).decode(src)
            }
        }

        impl<'a> Decoder for &'a mut $typ {
            type Item = $item;
            type Error = Error;

            fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
                let (opt, removed_len) = {
                    let str_src = str::from_utf8(&src[..])?;
                    println!("Decoding `{}`", str_src);
                    combine::stream::decode(
                        any_partial_state(mk_parser!($parser, self, ($($custom_state)*))),
                        easy::Stream(combine::stream::PartialStream(str_src)),
                        &mut self.0,
                    ).map_err(|err| {
                        // Since err contains references into `src` we must remove these before
                        // returning the error and before we call `split_to` to remove the input we
                        // just consumed
                        let err = err.map_range(|r| r.to_string())
                            .map_position(|p| p.translate_position(&src[..]));
                        format!("{}\nIn input: `{}`", err, str_src)
                    })?
                };

                src.split_to(removed_len);
                match opt {
                    None => println!("Need more input!"),
                    Some(_) => (),
                }
                Ok(opt)
            }
        }
    }
}

use partial_io::{GenWouldBlock, PartialAsyncRead, PartialOp, PartialWithErrors};

fn run_decoder<D, S>(input: &str, seq: S, decoder: D) -> Result<Vec<D::Item>, D::Error>
where
    D: Decoder,
    D::Item: ::std::fmt::Display,
    S: IntoIterator<Item = PartialOp> + 'static,
    S::IntoIter: Send,
{
    let ref mut reader = Cursor::new(input.as_bytes());
    let partial_reader = PartialAsyncRead::new(reader, seq);
    FramedRead::new(partial_reader, decoder)
        .map(|x| {
            println!("Decoded `{}`", x);
            x
        })
        .collect()
        .wait()
}

parser!{
    type PartialState = AnyPartialState;
    fn basic_parser['a, I]()(I) -> String
        where [ I: RangeStream<Item = char, Range = &'a str> ]
    {
        any_partial_state(
            many1(digit()).skip(range(&"\r\n"[..])),
        )
    }
}

impl_decoder!{ Basic, String, basic_parser() }

#[test]
fn many1_skip_no_errors() {
    let input = "123\r\n\
                 456\r\n";

    let result = run_decoder(input, vec![], Basic::default());

    assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
    assert_eq!(result.unwrap(), vec!["123".to_string(), "456".to_string()]);
}

parser!{
    type PartialState = AnyPartialState;
    fn prefix_many_then_parser['a, I]()(I) -> String
        where [ I: RangeStream<Item = char, Range = &'a str> ]
    {
        any_partial_state((char('#'), skip_many(char(' ')), many1(digit()))
            .then_partial(|t| {
                let s: &String = &t.2;
                let c = s.parse().unwrap();
                count_min_max(c, c, any())
            })
        )
    }
}

parser!{
    type PartialState = AnyPartialState;
    fn choice_parser['a, I]()(I) -> String
        where [ I: RangeStream<Item = char, Range = &'a str> ]
    {
        any_partial_state(
            many1(digit())
                .or(many1(letter()))
                .skip(range(&"\r\n"[..]))
        )
    }
}

quickcheck! {
    fn many1_skip_test(seq: PartialWithErrors<GenWouldBlock>) -> () {

        let input = "123\r\n\
                     456\r\n\
                     1\r\n\
                     5\r\n\
                     666666\r\n";

        let result = run_decoder(input, seq, Basic::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            vec!["123".to_string(), "456".to_string(), "1".to_string(), "5".to_string(), "666666".to_string()]
        );
    }

    fn prefix_many_then_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String, prefix_many_then_parser() }

        let input = "# 1a\
                     # 4abcd\
                     #0\
                     #3:?a\
                     #10abcdefghij";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["a", "abcd", "", ":?a", "abcdefghij"]
        );
    }

    fn choice_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String, choice_parser() }

        let input = "1\r\n\
                     abcd\r\n\
                     123\r\n\
                     abc\r\n\
                     1232751\r\n";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1", "abcd", "123", "abc", "1232751"]
        );
    }

    fn recognize_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            recognize(
                (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
            )
                .skip(range(&"\r\n"[..]))
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     1.\r\n\
                     2\r\n";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "1.", "2"]
        );
    }

    fn recognize_range_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            recognize_with_value(
                (skip_many1(digit()), optional((char('.'), skip_many(digit()))))
            )
                .map(|(r, _)| String::from(r))
                .skip(range(&"\r\n"[..]))
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     1.\r\n\
                     2\r\n";

        let result = run_decoder(input, seq, TestParser::default());

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "1.", "2"]
        );
    }

    fn take_while_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |counter: Rc<Cell<i32>>|
                take_while(move |c| { counter.set(counter.get() + 1); c != '\r' })
                    .map(String::from)
                    .skip(range("\r\n")),
            Rc<Cell<i32>>
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     \r\n\
                     2\r\n";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "", "2"]
        );

        assert_eq!(counter.get(), 26);
    }

    fn take_while1_test(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |count: Rc<Cell<i32>>|
                take_while1(move |c| { count.set(count.get() + 1); c != '\r' })
                    .map(String::from)
                    .skip(range("\r\n")),
            Rc<Cell<i32>>
        }

        let input = "1.0\r\n\
                     123.123\r\n\
                     17824\r\n\
                     3.14\r\n\
                     1.\r\n\
                     2\r\n";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["1.0", "123.123", "17824", "3.14", "1.", "2"]
        );

        assert_eq!(counter.get(), 28);
    }

    fn take_until(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |count: Rc<Cell<i32>>|
                repeat::take_until(item(',').map(move |_| count.set(count.get() + 1))).skip(item(',')),
            Rc<Cell<i32>>
        }

        let input = "123,456,789,";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["123", "456", "789"]
        );

        assert_eq!(counter.get(), 3);
    }

    fn take_until_consumed(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            |count: Rc<Cell<i32>>| {
                let end = try((item(':').map(move |_| count.set(count.get() + 1)), item(':')));
                repeat::take_until(end).skip((item(':'), item(':')))
            },
            Rc<Cell<i32>>
        }

        let input = "123::456::789::";

        let counter = Rc::new(Cell::new(0));
        let result = run_decoder(input, seq, TestParser(Default::default(), counter.clone()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(
            result.unwrap(),
            ["123", "456", "789"]
        );

        assert_eq!(counter.get(), 3);
    }

    fn take_until_range_consumed(seq: PartialWithErrors<GenWouldBlock>) -> () {
        impl_decoder!{ TestParser, String,
            take_until_range("::").map(String::from).skip((item(':'), item(':')))
        }

        let input = "123::456::789::";

        let result = run_decoder(input, seq, TestParser(Default::default()));

        assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
        assert_eq!(result.unwrap(), ["123", "456", "789"]);
    }
}
#[test]
fn inner_no_partial_test() {
    let seq = vec![PartialOp::Limited(10)];
    impl_decoder!{ TestParser, String,
        no_partial(many1(digit()))
            .or(many1(letter()))
            .skip(range(&"\r\n"[..]))
    }

    let input = "1\r\n\
                 abcd\r\n\
                 123\r\n\
                 abc\r\n\
                 1232751\r\n";

    let result = run_decoder(input, seq, TestParser::default());

    assert!(result.as_ref().is_ok(), "{}", result.unwrap_err());
    assert_eq!(result.unwrap(), ["1", "abcd", "123", "abc", "1232751"]);
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com>

//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.

extern crate context;
extern crate libc;

use std::iter::Iterator;
use std::mem::transmute;
use std::cell::UnsafeCell;
use std::default::Default;
use std::ops::DerefMut;
use std::fmt;
use std::rt::unwind::try;
use std::rt::unwind::begin_unwind;
use std::rt;
use std::boxed::FnBox;
use std::any::Any;

use context::Context;
use context::stack::{Stack, StackPool};

pub struct Options {
    stack_size: usize,
    name: Option<String>,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            stack_size: rt::min_stack(),
            name: None,
        }
    }
}

#[derive(Debug)]
pub enum CoroError {
    Panicking(Box<Any + Send>),
    Panicked,
}

pub type CoroResult<T> = Result<T, CoroError>;

thread_local!(static STACK_POOL: UnsafeCell<StackPool> = UnsafeCell::new(StackPool::new()));

struct ForceUnwind;

/// Initialization function for make context
extern "C" fn coroutine_initialize(_: usize, f: *mut libc::c_void) -> ! {
    {
        let func: Box<Box<FnBox()>> = unsafe {
            Box::from_raw(f as *mut Box<FnBox()>)
        };

        func();
    }

    unreachable!("Never reach here");
}

#[derive(Debug, Copy, Clone)]
enum State {
    Created,
    Running,
    Finished,
    ForceUnwind,
}

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct CoroutineImpl<T = ()>
    where T: Send
{
    parent: Context,
    context: Context,
    stack: Option<Stack>,

    name: Option<String>,
    state: State,

    result: Option<CoroResult<*mut Option<T>>>,
}

unsafe impl<T> Send for CoroutineImpl<T>
    where T: Send,
{}

impl<T> fmt::Display for CoroutineImpl<T>
    where T: Send
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Coroutine({})", self.name.as_ref()
                                            .map(|s| &s[..])
                                            .unwrap_or("<unnamed>"))
    }
}

impl<T> CoroutineImpl<T>
    where T: Send,
{
    unsafe fn yield_back(&mut self) -> Option<T> {
        Context::swap(&mut self.context, &self.parent);

        if let State::ForceUnwind = self.state {
            begin_unwind(ForceUnwind, &(file!(), line!()));
        }

        match self.result.take() {
            None => None,
            Some(Ok(x)) => (*x).take(),
            _ => unreachable!("Coroutine is panicking"),
        }
    }

    unsafe fn resume(&mut self) -> CoroResult<Option<T>> {
        Context::swap(&mut self.parent, &self.context);
        match self.result.take() {
            None => Ok(None),
            Some(Ok(x)) => Ok((*x).take()),
            Some(Err(err)) => Err(err),
        }
    }

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|s| &s[..])
    }

    fn take_data(&mut self) -> Option<T> {
        match self.result.take() {
            None => None,
            Some(Ok(x)) => unsafe { (*x).take() },
            _ => unreachable!("Coroutine is panicking")
        }
    }

    unsafe fn yield_with(&mut self, data: T) -> Option<T> {
        self.result = Some(Ok(&mut Some(data)));
        self.yield_back()
    }

    unsafe fn resume_with(&mut self, data: T) -> CoroResult<Option<T>> {
        self.result = Some(Ok(&mut Some(data)));
        self.resume()
    }

    unsafe fn force_unwind(&mut self) {
        if let State::Running = self.state {
            self.state = State::ForceUnwind;
            let _ = try(|| { let _ = self.resume(); });
        }
    }
}

impl<T> Drop for CoroutineImpl<T>
    where T: Send,
{
    fn drop(&mut self) {
        unsafe {
            self.force_unwind();
        }
        STACK_POOL.with(|pool| unsafe {
            if let Some(stack) = self.stack.take() {
                (&mut *pool.get()).give_stack(stack);
            }
        });
    }
}

pub struct Coroutine<T>
    where T: Send + 'static,
{
    coro: UnsafeCell<Box<CoroutineImpl<T>>>,
}

impl<T> fmt::Debug for Coroutine<T>
    where T: Send,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.coro.get())
    }
}

impl<T> Coroutine<T>
    where T: Send,
{
    #[inline]
    pub fn spawn_opts<F>(f: F, opts: Options) -> Coroutine<T>
        where F: FnOnce(CoroutineRef<T>)
    {
        let mut stack = STACK_POOL.with(|pool| unsafe {
            (&mut *pool.get()).take_stack(opts.stack_size)
        });

        let mut coro = Box::new(CoroutineImpl {
            parent: Context::empty(),
            context: Context::empty(),
            stack: None,
            name: opts.name,
            state: State::Created,
            result: None,
        });

        let coro_ref: &mut CoroutineImpl<T> = unsafe {
            let ptr: *mut CoroutineImpl<T> = coro.deref_mut();
            &mut *ptr
        };

        let puller_ref = CoroutineRef {
            coro: coro_ref
        };

        // Coroutine function wrapper
        // Responsible for calling the function and dealing with panicking
        let wrapper = move|| -> ! {
            let ret = unsafe {
                let puller_ref = puller_ref.clone();
                try(|| {
                    let coro_ref: &mut CoroutineImpl<T> = &mut *puller_ref.coro;
                    coro_ref.state = State::Running;
                    f(puller_ref)
                })
            };

            unsafe {
                let coro_ref: &mut CoroutineImpl<T> = &mut *puller_ref.coro;
                coro_ref.state = State::Finished;
            }

            let is_panicked = match ret {
                Ok(..) => false,
                Err(err) => {
                    if let None = err.downcast_ref::<ForceUnwind>() {
                        {
                            use std::io::stderr;
                            use std::io::Write;
                            let msg = match err.downcast_ref::<&'static str>() {
                                Some(s) => *s,
                                None => match err.downcast_ref::<String>() {
                                    Some(s) => &s[..],
                                    None => "Box<Any>",
                                }
                            };

                            let name = coro_ref.name().unwrap_or("<unnamed>");
                            let _ = writeln!(&mut stderr(), "Coroutine '{}' panicked at '{}'", name, msg);
                        }

                        coro_ref.result = Some(Err(CoroError::Panicking(err)));
                        true
                    } else {
                        false
                    }
                }
            };

            loop {
                if is_panicked {
                    coro_ref.result = Some(Err(CoroError::Panicked));
                }

                unsafe {
                    coro_ref.yield_back();
                }
            }
        };

        coro.context.init_with(coroutine_initialize, 0, Box::new(wrapper), &mut stack);
        coro.stack = Some(stack);

        Coroutine {
            coro: UnsafeCell::new(coro)
        }
    }

    #[inline]
    pub fn spawn<F>(f: F) -> Coroutine<T>
        where F: FnOnce(CoroutineRef<T>)
    {
        Coroutine::spawn_opts(f, Default::default())
    }

    #[inline]
    pub fn name(&self) -> Option<&str> {
        unsafe {
            (&*self.coro.get()).name()
        }
    }

    #[inline]
    pub fn resume(&self) -> CoroResult<Option<T>> {
        unsafe {
            (&mut *self.coro.get()).resume()
        }
    }

    #[inline]
    pub fn resume_with(&self, data: T) -> CoroResult<Option<T>> {
        unsafe {
            (&mut *self.coro.get()).resume_with(data)
        }
    }
}

pub struct CoroutineRef<T>
    where T: Send,
{
    coro: *mut CoroutineImpl<T>,
}

impl<T> Copy for CoroutineRef<T>
    where T: Send,
{}

impl<T> Clone for CoroutineRef<T>
    where T: Send,
{
    fn clone(&self) -> CoroutineRef<T> {
        CoroutineRef {
            coro: self.coro,
        }
    }
}

unsafe impl<T> Send for CoroutineRef<T>
    where T: Send,
{}

impl<T> CoroutineRef<T>
    where T: Send,
{
    #[inline]
    pub fn yield_back(&self) -> Option<T> {
        unsafe {
            let coro: &mut CoroutineImpl<T> = transmute(self.coro);
            coro.yield_back()
        }
    }

    #[inline]
    pub fn yield_with(&self, data: T) -> Option<T> {
        unsafe {
            let coro: &mut CoroutineImpl<T> = transmute(self.coro);
            coro.yield_with(data)
        }
    }

    #[inline]
    pub fn name(&self) -> Option<&str> {
        unsafe {
            (&*self.coro).name()
        }
    }

    #[inline]
    pub fn take_data(&self) -> Option<T> {
        unsafe {
            let coro: &mut CoroutineImpl<T> = transmute(self.coro);
            coro.take_data()
        }
    }
}

impl<T> Iterator for Coroutine<T>
    where T: Send,
{
    type Item = CoroResult<T>;

    fn next(&mut self) -> Option<CoroResult<T>> {
        match self.resume() {
            Ok(r) => r.map(|x| Ok(x)),
            Err(err) => Some(Err(err)),
        }
    }
}
<commit_msg>add benchmarks and tests<commit_after>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com>

//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.

extern crate context;
extern crate libc;

use std::iter::Iterator;
use std::mem::transmute;
use std::cell::UnsafeCell;
use std::default::Default;
use std::ops::DerefMut;
use std::fmt;
use std::rt::unwind::try;
use std::rt::unwind::begin_unwind;
use std::rt;
use std::boxed::FnBox;
use std::any::Any;

use context::Context;
use context::stack::{Stack, StackPool};

pub struct Options {
    stack_size: usize,
    name: Option<String>,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            stack_size: rt::min_stack(),
            name: None,
        }
    }
}

#[derive(Debug)]
pub enum CoroError {
    Panicking(Box<Any + Send>),
    Panicked,
}

pub type CoroResult<T> = Result<T, CoroError>;

thread_local!(static STACK_POOL: UnsafeCell<StackPool> = UnsafeCell::new(StackPool::new()));

struct ForceUnwind;

/// Initialization function for make context
extern "C" fn coroutine_initialize(_: usize, f: *mut libc::c_void) -> ! {
    {
        let func: Box<Box<FnBox()>> = unsafe {
            Box::from_raw(f as *mut Box<FnBox()>)
        };

        func();
    }

    unreachable!("Never reach here");
}

#[derive(Debug, Copy, Clone)]
enum State {
    Created,
    Running,
    Finished,
    ForceUnwind,
}

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct CoroutineImpl<T = ()>
    where T: Send
{
    parent: Context,
    context: Context,
    stack: Option<Stack>,

    name: Option<String>,
    state: State,

    result: Option<CoroResult<*mut Option<T>>>,
}

unsafe impl<T> Send for CoroutineImpl<T>
    where T: Send,
{}

impl<T> fmt::Display for CoroutineImpl<T>
    where T: Send
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Coroutine({})", self.name.as_ref()
                                            .map(|s| &s[..])
                                            .unwrap_or("<unnamed>"))
    }
}

impl<T> CoroutineImpl<T>
    where T: Send,
{
    unsafe fn yield_back(&mut self) -> Option<T> {
        Context::swap(&mut self.context, &self.parent);

        if let State::ForceUnwind = self.state {
            begin_unwind(ForceUnwind, &(file!(), line!()));
        }

        match self.result.take() {
            None => None,
            Some(Ok(x)) => (*x).take(),
            _ => unreachable!("Coroutine is panicking"),
        }
    }

    unsafe fn resume(&mut self) -> CoroResult<Option<T>> {
        Context::swap(&mut self.parent, &self.context);
        match self.result.take() {
            None => Ok(None),
            Some(Ok(x)) => Ok((*x).take()),
            Some(Err(err)) => Err(err),
        }
    }

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|s| &s[..])
    }

    fn take_data(&mut self) -> Option<T> {
        match self.result.take() {
            None => None,
            Some(Ok(x)) => unsafe { (*x).take() },
            _ => unreachable!("Coroutine is panicking")
        }
    }

    unsafe fn yield_with(&mut self, data: T) -> Option<T> {
        self.result = Some(Ok(&mut Some(data)));
        self.yield_back()
    }

    unsafe fn resume_with(&mut self, data: T) -> CoroResult<Option<T>> {
        self.result = Some(Ok(&mut Some(data)));
        self.resume()
    }

    unsafe fn force_unwind(&mut self) {
        if let State::Running = self.state {
            self.state = State::ForceUnwind;
            let _ = try(|| { let _ = self.resume(); });
        }
    }
}

impl<T> Drop for CoroutineImpl<T>
    where T: Send,
{
    fn drop(&mut self) {
        unsafe {
            self.force_unwind();
        }
        STACK_POOL.with(|pool| unsafe {
            if let Some(stack) = self.stack.take() {
                (&mut *pool.get()).give_stack(stack);
            }
        });
    }
}

pub struct Coroutine<T>
    where T: Send + 'static,
{
    coro: UnsafeCell<Box<CoroutineImpl<T>>>,
}

impl<T> fmt::Debug for Coroutine<T>
    where T: Send,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.coro.get())
    }
}

impl<T> Coroutine<T>
    where T: Send,
{
    #[inline]
    pub fn spawn_opts<F>(f: F, opts: Options) -> Coroutine<T>
        where F: FnOnce(CoroutineRef<T>)
    {
        let mut stack = STACK_POOL.with(|pool| unsafe {
            (&mut *pool.get()).take_stack(opts.stack_size)
        });

        let mut coro = Box::new(CoroutineImpl {
            parent: Context::empty(),
            context: Context::empty(),
            stack: None,
            name: opts.name,
            state: State::Created,
            result: None,
        });

        let coro_ref: &mut CoroutineImpl<T> = unsafe {
            let ptr: *mut CoroutineImpl<T> = coro.deref_mut();
            &mut *ptr
        };

        let puller_ref = CoroutineRef {
            coro: coro_ref
        };

        // Coroutine function wrapper
        // Responsible for calling the function and dealing with panicking
        let wrapper = move|| -> ! {
            let ret = unsafe {
                let puller_ref = puller_ref.clone();
                try(|| {
                    let coro_ref: &mut CoroutineImpl<T> = &mut *puller_ref.coro;
                    coro_ref.state = State::Running;
                    f(puller_ref)
                })
            };

            unsafe {
                let coro_ref: &mut CoroutineImpl<T> = &mut *puller_ref.coro;
                coro_ref.state = State::Finished;
            }

            let is_panicked = match ret {
                Ok(..) => false,
                Err(err) => {
                    if let None = err.downcast_ref::<ForceUnwind>() {
                        {
                            let msg = match err.downcast_ref::<&'static str>() {
                                Some(s) => *s,
                                None => match err.downcast_ref::<String>() {
                                    Some(s) => &s[..],
                                    None => "Box<Any>",
                                }
                            };

                            let name = coro_ref.name().unwrap_or("<unnamed>");
                            error!("Coroutine '{}' panicked at '{}'", name, msg);
                        }

                        coro_ref.result = Some(Err(CoroError::Panicking(err)));
                        true
                    } else {
                        false
                    }
                }
            };

            loop {
                if is_panicked {
                    coro_ref.result = Some(Err(CoroError::Panicked));
                }

                unsafe {
                    coro_ref.yield_back();
                }
            }
        };

        coro.context.init_with(coroutine_initialize, 0, Box::new(wrapper), &mut stack);
        coro.stack = Some(stack);

        Coroutine {
            coro: UnsafeCell::new(coro)
        }
    }

    #[inline]
    pub fn spawn<F>(f: F) -> Coroutine<T>
        where F: FnOnce(CoroutineRef<T>)
    {
        Coroutine::spawn_opts(f, Default::default())
    }

    #[inline]
    pub fn name(&self) -> Option<&str> {
        unsafe {
            (&*self.coro.get()).name()
        }
    }

    #[inline]
    pub fn resume(&self) -> CoroResult<Option<T>> {
        unsafe {
            (&mut *self.coro.get()).resume()
        }
    }

    #[inline]
    pub fn resume_with(&self, data: T) -> CoroResult<Option<T>> {
        unsafe {
            (&mut *self.coro.get()).resume_with(data)
        }
    }
}

pub struct CoroutineRef<T>
    where T: Send,
{
    coro: *mut CoroutineImpl<T>,
}

impl<T> Copy for CoroutineRef<T>
    where T: Send,
{}

impl<T> Clone for CoroutineRef<T>
    where T: Send,
{
    fn clone(&self) -> CoroutineRef<T> {
        CoroutineRef {
            coro: self.coro,
        }
    }
}

unsafe impl<T> Send for CoroutineRef<T>
    where T: Send,
{}

impl<T> CoroutineRef<T>
    where T: Send,
{
    #[inline]
    pub fn yield_back(&self) -> Option<T> {
        unsafe {
            let coro: &mut CoroutineImpl<T> = transmute(self.coro);
            coro.yield_back()
        }
    }

    #[inline]
    pub fn yield_with(&self, data: T) -> Option<T> {
        unsafe {
            let coro: &mut CoroutineImpl<T> = transmute(self.coro);
            coro.yield_with(data)
        }
    }

    #[inline]
    pub fn name(&self) -> Option<&str> {
        unsafe {
            (&*self.coro).name()
        }
    }

    #[inline]
    pub fn take_data(&self) -> Option<T> {
        unsafe {
            let coro: &mut CoroutineImpl<T> = transmute(self.coro);
            coro.take_data()
        }
    }
}

impl<T> Iterator for Coroutine<T>
    where T: Send,
{
    type Item = CoroResult<T>;

    fn next(&mut self) -> Option<CoroResult<T>> {
        match self.resume() {
            Ok(r) => r.map(|x| Ok(x)),
            Err(err) => Some(Err(err)),
        }
    }
}

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

    #[test]
    fn test_asymmetric_basic() {
        let coro = Coroutine::spawn(|me| {
            for i in 0..10 {
                me.yield_with(i);
            }
        });

        for (i, j) in coro.zip(0..10) {
            assert_eq!(i.unwrap(), j);
        }
    }

    #[test]
    fn test_asymmetric_panic() {
        use std::sync::atomic::{AtomicUsize, Ordering};
        use std::sync::Arc;

        let counter = Arc::new(AtomicUsize::new(0));

        let cloned_counter = counter.clone();
        let coro: Coroutine<()> = Coroutine::spawn(move|_| {
            struct Foo(Arc<AtomicUsize>);

            impl Drop for Foo {
                fn drop(&mut self) {
                    self.0.store(1, Ordering::SeqCst);
                }
            }

            let _foo = Foo(cloned_counter);

            panic!("Panicked inside");
        });

        let result = coro.resume();
        assert!(result.is_err());

        assert_eq!(1, counter.load(Ordering::SeqCst));
    }

    #[test]
    fn test_asymmetric_unwinding() {
        use std::sync::atomic::{AtomicUsize, Ordering};
        use std::sync::Arc;

        let counter = Arc::new(AtomicUsize::new(0));

        {
            let cloned_counter = counter.clone();
            let coro: Coroutine<()> = Coroutine::spawn(move|me| {
                struct Foo(Arc<AtomicUsize>);

                impl Drop for Foo {
                    fn drop(&mut self) {
                        self.0.store(1, Ordering::SeqCst);
                    }
                }

                let _foo = Foo(cloned_counter);

                me.yield_back();

                unreachable!("Never reach here");
            });

            let result = coro.resume();
            assert!(result.is_ok());

            // Destroy the coro without resume
        }

        assert_eq!(1, counter.load(Ordering::SeqCst));
    }
}

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

    use test::Bencher;

    #[bench]
    fn bench_asymmetric_spawn(b: &mut Bencher) {
        b.iter(|| {
            let _coro: Coroutine<i32> = Coroutine::spawn(|_| { 1; });
        });
    }

    #[bench]
    fn bench_asymmetric_resume(b: &mut Bencher) {
        let coro: Coroutine<()> = Coroutine::spawn(|me| {
            while let None = me.yield_back() {}
        });

        b.iter(|| {
            coro.resume().unwrap();
        });

        coro.resume_with(()).unwrap();;
    }
}
<|endoftext|>


<commit_before>
// Std imports
use std::num::{Zero, One};

// local imports

use matrix::*;

/*
/// A special view in matrix designed for computing determinants
struct DetView<'a, T:'a+MatrixElt>{
    // The rows of the matrix which have been excluded
    pub excluded_rows :Vec<bool>,
    pub excluded_cols : Vec<bool>,
    /// Number of rows or columns in the view
    view_size : uint,
    m : &'a Matrix<T>
}

impl <'a, T:MatrixElt> DetView<'a, T> {
    /// Creates a new view
    pub fn new(m : &Matrix<T>)->DetView<T>{
        let n = m.num_rows();
        let result = DetView{m : m,
            excluded_rows  : Vec::with_capacity(n),
            excluded_cols : Vec::with_capacity(n),
            view_size : 0
        };
        result

    }
}
*/

#[doc="Returns the determinant of a matrix view.
"]
pub fn  det<T:MatrixElt+Signed>(m : &Matrix<T>)->Result<T,MatrixError>{
    let n = m.num_cols();
    if !m.is_square(){
        return Err(NonSquareMatrix);
    }
    if m.is_scalar(){
        return Ok(m.get(0, 0));
    }
    //println!("m: {}", m);
    let mut result : T = Zero::zero();
    let mut m2 : Matrix<T> = Matrix::new(n-1, n-1);
    let ps = m.as_ptr();
    let pd = m2.as_mut_ptr();
    let mut sign : T = One::one();
    for i in range(0, n){
        for c in range(0, i){
            for r in range(1, n){
                //println!("first: i : {}, c : {}, r: {}", i , c, r);
                let src_offset = m.cell_to_offset(r, c);
                let dst_offset = m2.cell_to_offset(r  - 1, c);
                debug_assert!(src_offset < m.capacity() as int);
                debug_assert!(dst_offset < m2.capacity() as int);
                unsafe {
                    let v = *ps.offset(src_offset);
                    //println!("v = {}", v);
                    *pd.offset(dst_offset) = v;
                }
            }
        }
        for c in range(i+1, n){
            for r in range(1, n){
                //println!("second: i : {}, c : {}, r: {}", i , c, r);
                let src_offset = m.cell_to_offset(r, c);
                let dst_offset = m2.cell_to_offset(r  - 1, c - 1);
                debug_assert!(src_offset < m.capacity() as int);
                debug_assert!(dst_offset < m2.capacity() as int);
                unsafe {
                    let v = *ps.offset(src_offset);
                    //println!("v = {}", v);
                    *pd.offset(dst_offset) = v;
                }
            }
        }
        let ai = m.get(0, i);
        let ai_minor_det =  det(&m2).unwrap();
        //println!("sign: {}, ai: {}, Ai : {}", sign, ai, ai_minor_det);
        result = result + sign * ai * ai_minor_det;
        sign = -sign;
    }
    Ok(result)
}

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

    #[test]
    fn test_det_0(){
        let m = matrix_i64(2,2, [1, 2, 3, 4]);
        let d = det(&m).unwrap();
        assert_eq!(d, -2);
    }

    #[test]
    fn test_det_1(){
        let m = matrix_i64(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
        let d = det(&m).unwrap();
        assert_eq!(d, 0);
    }

    #[test]
    fn test_det_hadamard(){
        let m = hadamard(4).unwrap();
        let d = det(&m).unwrap();
        assert_eq!(d, 16.0);

        let m = hadamard(8).unwrap();
        let d = det(&m).unwrap();
        assert_eq!(d, 4096.0);
    }

    #[test]
    fn test_det_hilbert(){
        assert_eq!(hilbert(1).det().unwrap(), 1.0);
        assert!(num::abs(hilbert(2).det().unwrap() - 0.083333333333333) < 1e-10);
        assert!(num::abs(hilbert(4).det().unwrap() - 1.653439153439264e-07) < 1e-10);
        assert!(num::abs(hilbert(8).det().unwrap() - 2.737050310006999e-33) < 1e-10);
    }

}
<commit_msg>Optimizations in the implementation of determinant.<commit_after>
// Std imports
use std::num;

// local imports

use matrix::*;

#[doc="Returns the determinant of a matrix.

# Remarks

The determinant is defined only for square matrices.

The determinant of an empty matrix is 1.
See http://en.wikipedia.org/wiki/Matrix_(mathematics)#Empty_matrices.

"]
pub fn  det<T:MatrixElt+Signed>(m : &Matrix<T>)->Result<T,MatrixError>{
    if !m.is_square(){
        return Err(NonSquareMatrix);
    }
    if m.is_empty(){
        return Ok(num::One::one());
    }
    Ok(det_(m))
}

/// Private implementation of determinant
/// Assumes that matrix is indeed square.
fn det_<T:MatrixElt+Signed>(m : &Matrix<T>)->T{
    let a0 = m.get(0, 0);
    println!("m: {}", m);
    if m.is_scalar(){
        return a0;
    }
    let n = m.num_cols();
    let mut m2 = m.sub_matrix(1,1, n-1, n-1);
    let ps = m.as_ptr();
    let pd = m2.as_mut_ptr();
    let mut sign : T  = num::One::one();
    let mut result = sign * a0 * det_(&m2);
    sign = -sign;
    for c in range(0, n-1){
        for r in range(1, n){
            println!("r : {}, c : {}", r , c);
            let src_offset = m.cell_to_offset(r, c);
            let dst_offset = m2.cell_to_offset(r - 1, c);
            debug_assert!(src_offset < m.capacity() as int);
            debug_assert!(dst_offset < m2.capacity() as int);
            unsafe {
                let v = *ps.offset(src_offset);
                //println!("v = {}", v);
                *pd.offset(dst_offset) = v;
            }
        }
        let ai = m.get(0, c+1);
        let ai_minor_det =  det_(&m2);
        println!("sign: {}, ai: {}, Ai : {}", sign, ai, ai_minor_det);
        result = result + sign * ai * ai_minor_det;
        sign = -sign;
    }
    result
}

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

    #[test]
    fn test_det_0(){
        let m = matrix_i64(2,2, [1, 2, 3, 4]);
        let d = det(&m).unwrap();
        assert_eq!(d, -2);
    }

    #[test]
    fn test_det_1(){
        let m = matrix_i64(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
        let d = det(&m).unwrap();
        assert_eq!(d, 0);
    }

    #[test]
    fn test_det_hadamard(){
        let m = hadamard(4).unwrap();
        let d = det(&m).unwrap();
        assert_eq!(d, 16.0);

        let m = hadamard(8).unwrap();
        let d = det(&m).unwrap();
        assert_eq!(d, 4096.0);
    }

    #[test]
    fn test_det_hilbert(){
        assert_eq!(hilbert(1).det().unwrap(), 1.0);
        assert!(num::abs(hilbert(2).det().unwrap() - 0.083333333333333) < 1e-10);
        assert!(num::abs(hilbert(4).det().unwrap() - 1.653439153439264e-07) < 1e-10);
        assert!(num::abs(hilbert(8).det().unwrap() - 2.737050310006999e-33) < 1e-10);
    }

    #[test]
    fn test_empty_mat_det(){
        let m : MatrixI64 = Matrix::new(0, 0);
        let d = m.det().unwrap();
        assert_eq!(d, 1);
    }

}
<|endoftext|>


<commit_before>use std::f32;
use linalg::Point;
use linalg::Vector;

/// Ray is a standard 3D ray, starting at origin `o` and heading in direction `d`
/// The min and max points along the ray can be specified with `min_t` and `max_t`
/// `depth` is the recursion depth of the ray
#[deriving(Show, Copy, PartialEq)]
pub struct Ray {
    /// Origin of the ray
    pub o: Point,
    /// Direction the ray is heading
    pub d: Vector,
    /// Point along the ray that the actual ray starts at, `p = o + min_t * d`
    pub min_t: f32,
    /// Point along the ray at which it stops, will be inf if the ray is infinite
    pub max_t: f32,
    /// Recursion depth of the ray
    pub depth: i32,
}

impl Ray {
    /// Create a new ray from `o` heading in `d` with infinite length
    pub fn new(o: &Point, d: &Vector) -> Ray {
        Ray { o: *o, d: *d, min_t: 0f32, max_t: f32::INFINITY, depth: 0 }
    }
    /// Create a new segment ray from `o + min_t * d` to `o + max_t * d`
    pub fn segment(o: &Point, d: &Vector, min_t: f32, max_t: f32) -> Ray {
        Ray { o: *o, d: *d, min_t: min_t, max_t: max_t, depth: 0}
    }
    /// Create a child ray from the parent starting at `o` and heading in `d`
    pub fn child(&self, o: &Point, d: &Vector) -> Ray {
        Ray { o: *o, d: *d, min_t: 0f32, max_t: f32::INFINITY, depth: self.depth + 1 }
    }
    /// Create a child ray segment from `o + min_t * d` to `o + max_t * d`
    pub fn child_segment(&self, o: &Point, d: &Vector, min_t: f32, max_t: f32) -> Ray {
        Ray { o: *o, d: *d, min_t: min_t, max_t: max_t, depth: self.depth + 1}
    }
    /// Evaulate the ray equation at some t value and return the point
    /// returns result of `self.o + t * self.d`
    fn at(&self, t: f32) -> Point {
        self.o + self.d * t
    }
}

<commit_msg>Ray::at should be public<commit_after>use std::f32;
use linalg::Point;
use linalg::Vector;

/// Ray is a standard 3D ray, starting at origin `o` and heading in direction `d`
/// The min and max points along the ray can be specified with `min_t` and `max_t`
/// `depth` is the recursion depth of the ray
#[deriving(Show, Copy, PartialEq)]
pub struct Ray {
    /// Origin of the ray
    pub o: Point,
    /// Direction the ray is heading
    pub d: Vector,
    /// Point along the ray that the actual ray starts at, `p = o + min_t * d`
    pub min_t: f32,
    /// Point along the ray at which it stops, will be inf if the ray is infinite
    pub max_t: f32,
    /// Recursion depth of the ray
    pub depth: i32,
}

impl Ray {
    /// Create a new ray from `o` heading in `d` with infinite length
    pub fn new(o: &Point, d: &Vector) -> Ray {
        Ray { o: *o, d: *d, min_t: 0f32, max_t: f32::INFINITY, depth: 0 }
    }
    /// Create a new segment ray from `o + min_t * d` to `o + max_t * d`
    pub fn segment(o: &Point, d: &Vector, min_t: f32, max_t: f32) -> Ray {
        Ray { o: *o, d: *d, min_t: min_t, max_t: max_t, depth: 0}
    }
    /// Create a child ray from the parent starting at `o` and heading in `d`
    pub fn child(&self, o: &Point, d: &Vector) -> Ray {
        Ray { o: *o, d: *d, min_t: 0f32, max_t: f32::INFINITY, depth: self.depth + 1 }
    }
    /// Create a child ray segment from `o + min_t * d` to `o + max_t * d`
    pub fn child_segment(&self, o: &Point, d: &Vector, min_t: f32, max_t: f32) -> Ray {
        Ray { o: *o, d: *d, min_t: min_t, max_t: max_t, depth: self.depth + 1}
    }
    /// Evaulate the ray equation at some t value and return the point
    /// returns result of `self.o + t * self.d`
    pub fn at(&self, t: f32) -> Point {
        self.o + self.d * t
    }
}

<|endoftext|>


<commit_before>extern crate num;

use std::ops::Mul;
use std::ops::Add;

#[allow(dead_code)]
pub struct ZeroPaddedSignal<T> {
	values: Vec<T>,
}

impl<T: num::traits::Zero + Clone + Mul<Output = T> + Add> ZeroPaddedSignal<T> {
	/**
		Returns the number of initialized values.
	*/
	#[allow(dead_code)]
	pub fn size(&self) -> usize {
		self.values.len()
	}

	/**
		Returns the value at the given index, zero if index
		is negative or uninitialized.
	*/
	#[allow(dead_code)]
	pub fn get(&self, idx: isize) -> T {
		/* Check for negative index: */
		if idx < 0 {
			/* Negative, return zero: */
			T::zero()
		} else {
			/* Not negative, cast to unsigned: */
			let idx = idx as usize;
			/* Check if the index is initialized: */
			if let Some(v) = self.values.get(idx).cloned() {
				/* It is, return the value: */
				v
			} else {
				/* It's not, return zero: */
				T::zero()
			}
		}
	}

	/**
		Returns a vector of signal values, starting with index start,
		ending with index end.
	*/
	#[allow(dead_code)]
	pub fn to_vector(&self, start: isize, end: isize) -> Vec<T> {
		/* Create an empty vector: */
		let mut x: Vec<T> = Vec::new();
		/* Loop through the given range: */
		for i in start..(end+1) {
			/* Add the values to the vector: */
			x.push(self.get(i));
		}
		/* Make the vector immutable: */
		let x = x;
		/* Return the vector: */
		x
	}

	/**
		Creates a new signal by doing Linear Prediction using
		the given coefficients.
	*/
	#[allow(dead_code)]
	pub fn linear_prediction(&self, a: Vec<T>) -> ZeroPaddedSignal<T> {
		/* Create a vector for the values: */
		let mut vals: Vec<T> = Vec::new();
		/* Calculate the size of the new signal: */
		let size: usize = self.size() + a.len();
		/* Iterate over the new indices: */
		for i in 0..size {
			let mut val: T = T::zero();
			/* ... and the coefficients: */
			for j in 0..a.len() {
				/* Calculate and typecast the index in the old signal: */
				let idx = (i as isize) - ((j+1) as isize);
				/* Weight the value and add it up: */
				if let Some(v) = a.get(j).cloned() {
					val = val + v*self.get(idx);
				}
			}
			/* Add the value to the vector: */
			vals.push(val);
		}
		/* Create a signal from the vector and return it: */
		let x: ZeroPaddedSignal<T> = ZeroPaddedSignal { values: vals };
		x
	}
}

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

	#[test]
	fn zero_padded_signal() {
		/* Create test signals: */
		let x1: ZeroPaddedSignal<u32> = ZeroPaddedSignal { values: vec![42,7,11] };
		/* Test size method: */
		assert_eq!( 3, x1.size());
		/* Test get method: */
		assert_eq!( 0, x1.get(  -1));
		assert_eq!(42, x1.get(   0));
		assert_eq!( 7, x1.get(   1));
		assert_eq!(11, x1.get(   2));
		assert_eq!( 0, x1.get(   3));
		assert_eq!( 0, x1.get( 100));
		assert_eq!( 0, x1.get(-100));
		/* Test to_vector method: */
		assert_eq!(vec![0,0,0,42,7,11,0], x1.to_vector(-3,3));
	}

	#[test]
	fn linear_prediction() {
		let x2: ZeroPaddedSignal<f64> = ZeroPaddedSignal { values: vec![1.,1.,1.,1.,1.,1.] };
		/* Test linear_prediction method: */
		assert_eq!(vec![0., 0.8888888888888888, 0.8888888888888888, 0.8888888888888888, 0.7777777777777777, 0.7777777777777777, 0.7777777777777777, -0.1111111111111111, -0.1111111111111111, -0.1111111111111111], x2.linear_prediction(vec![8./9.,0.,0.,-1./9.]).values);
	}
}
<commit_msg>Summed Mul & Add up to Num<commit_after>extern crate num;

#[allow(dead_code)]
pub struct ZeroPaddedSignal<T> {
	values: Vec<T>,
}

impl<T: num::traits::Num + Clone> ZeroPaddedSignal<T> {
	/**
		Returns the number of initialized values.
	*/
	#[allow(dead_code)]
	pub fn size(&self) -> usize {
		self.values.len()
	}

	/**
		Returns the value at the given index, zero if index
		is negative or uninitialized.
	*/
	#[allow(dead_code)]
	pub fn get(&self, idx: isize) -> T {
		/* Check for negative index: */
		if idx < 0 {
			/* Negative, return zero: */
			T::zero()
		} else {
			/* Not negative, cast to unsigned: */
			let idx = idx as usize;
			/* Check if the index is initialized: */
			if let Some(v) = self.values.get(idx).cloned() {
				/* It is, return the value: */
				v
			} else {
				/* It's not, return zero: */
				T::zero()
			}
		}
	}

	/**
		Returns a vector of signal values, starting with index start,
		ending with index end.
	*/
	#[allow(dead_code)]
	pub fn to_vector(&self, start: isize, end: isize) -> Vec<T> {
		/* Create an empty vector: */
		let mut x: Vec<T> = Vec::new();
		/* Loop through the given range: */
		for i in start..(end+1) {
			/* Add the values to the vector: */
			x.push(self.get(i));
		}
		/* Make the vector immutable: */
		let x = x;
		/* Return the vector: */
		x
	}

	/**
		Creates a new signal by doing Linear Prediction using
		the given coefficients.
	*/
	#[allow(dead_code)]
	pub fn linear_prediction(&self, a: Vec<T>) -> ZeroPaddedSignal<T> {
		/* Create a vector for the values: */
		let mut vals: Vec<T> = Vec::new();
		/* Calculate the size of the new signal: */
		let size: usize = self.size() + a.len();
		/* Iterate over the new indices: */
		for i in 0..size {
			let mut val: T = T::zero();
			/* ... and the coefficients: */
			for j in 0..a.len() {
				/* Calculate and typecast the index in the old signal: */
				let idx = (i as isize) - ((j+1) as isize);
				/* Weight the value and add it up: */
				if let Some(v) = a.get(j).cloned() {
					val = val + v*self.get(idx);
				}
			}
			/* Add the value to the vector: */
			vals.push(val);
		}
		/* Create a signal from the vector and return it: */
		let x: ZeroPaddedSignal<T> = ZeroPaddedSignal { values: vals };
		x
	}
}

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

	#[test]
	fn zero_padded_signal() {
		/* Create test signals: */
		let x1: ZeroPaddedSignal<u32> = ZeroPaddedSignal { values: vec![42,7,11] };
		/* Test size method: */
		assert_eq!( 3, x1.size());
		/* Test get method: */
		assert_eq!( 0, x1.get(  -1));
		assert_eq!(42, x1.get(   0));
		assert_eq!( 7, x1.get(   1));
		assert_eq!(11, x1.get(   2));
		assert_eq!( 0, x1.get(   3));
		assert_eq!( 0, x1.get( 100));
		assert_eq!( 0, x1.get(-100));
		/* Test to_vector method: */
		assert_eq!(vec![0,0,0,42,7,11,0], x1.to_vector(-3,3));
	}

	#[test]
	fn linear_prediction() {
		/* Create test signals: */
		let x2: ZeroPaddedSignal<f64> = ZeroPaddedSignal { values: vec![1.,1.,1.,1.,1.,1.] };
		/* Test linear_prediction method: */
		assert_eq!(vec![0., 0.8888888888888888, 0.8888888888888888, 0.8888888888888888, 0.7777777777777777, 0.7777777777777777, 0.7777777777777777, -0.1111111111111111, -0.1111111111111111, -0.1111111111111111], x2.linear_prediction(vec![8./9.,0.,0.,-1./9.]).values);
	}
}
<|endoftext|>


<commit_before>//! Utilities for generalized iterators over trees of arbitrary types.

use std;

/// Descriptions of actions that may be taken on a given node when traversing
/// a pattern tree.
pub mod action {
    enum Flag {
        /// Terminate iteration after performing other specified actions.
        TERMINATE = 1,
    }

    pub use self::Flag::*;

    struct Action<U,V> {
        yield_value: Option<U>,
        recurse_on: Option<V>,
        flags: u8
    }
}

pub use self::action::Action;

/// Interface for patterns whose elements may be visited in
/// a runtime-specified manner.
///
/// @tparam Tag Marker type used to discriminate the "type" of walk being
///     implemented.  A particular type may be walked for different purposes,
///     such as to visit *all* elements, or only certain ones.
///
/// @tparam Yielded Type of item the walkable should implement an iterator for.
trait Walkable<Tag,Yielded>: std::marker::PhantomFn<Tag> {
    /// Iterator type that for the implementer's underlying container.
    type BaseIterator;
    type Item = <Self::BaseIterator as Iterator>::Item;
    type Action = Action<Yielded,Self::Item>;

    /// Fetch the initial iterator to use for a walk.
    fn iter(&self) -> Self::BaseIterator;

    /// Determine the action to take for a given node in the implementor's
    /// element tree.
    ///
    /// @param element Pattern element to process.
    ///
    /// @return Tuple containing the optionally-yielded element, and a set of
    ///     flags indicating how to proceed.  Action::RECURSE is only valid
    ///     when `Item` implements Walkable<Yielded>.
    fn action<'a>(element: &'a Self::Item) -> Self::Action
        where Self::Item: Walkable<Tag,Yielded>;
}

// FIXME: should the order of `T` and `Yielded` be reversed?
/// Iterator used to perform a particular walk on a particular type.
///
/// @tparam Tag Walk-type tag.
///
/// @tparam Yielded `Item` type for the iterator implementation of
///     the structure.
///
/// @tparam T Top-level Walkable type for which this structure is an iterator.
struct Walker<Tag,Yielded,T> where T: Walkable<Tag,Yielded> {
    base_iterator: Option<<T as Walkable<Tag,Yielded>>::BaseIterator>,
    sub_iterator: Option<Walker<Tag,Yielded,Yielded>>,
}

impl<Tag,Yielded,T> Walker<Tag,Yielded,T>
where T: Walkable<Tag,Yielded> {
    /// Create a new walker iterator from the given base iterator.
    pub fn new(base: <T as Walkable<Tag,Yielded>>::BaseIterator) -> Walker<Tag,Yielded,T> {
        Walker{base_iterator: base, sub_iterator: None}
    }
}

impl<'a,Tag,Yielded,T> Iterator for Walker<Tag,Yielded,T>
where T: Walkable<Tag,Yielded>, Yielded: Walkable<Tag,Yielded> {
    type Item = &'a Yielded;

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        // "can't use type parameter from outer function" Why not?  And it's not a function.
        //type Walk = Walkable<Tag,Yielded>;
        // "huh?  why's there a less-than sign in here?"  Because I put it there.
        //use self::Walkable<Tag,Yielded> as Walk;

        if let Some(ref iter) = self.sub_iterator {
            if let Some(yielded) = (*iter).next() {
                return yielded; }
            else {
                // Sub-iterator is empty; clear it and fall through to the
                // base iterator.
                self.sub_iterator = None;
            } }
        if let Some(ref iter) = self.base_iterator {
            if let Some(ref element) = (*iter).next() {
                let action = <T as Walkable<Tag,Yielded>>::action(element);

                // FIXME: need to provide a way to specify order in which
                // to recurse vs. yield.  The solution should allow for
                // selection of different traversal methods -- need to come
                // up with an API for that.
                if let Some(recurse_item) = action.recurse_on {
                    self.sub_iterator = Some(Walker::new(<Yielded as Walkable<Tag,Yielded>>::iter(recurse_item)));

                    // Recurse immediately if we have no value to yield.
                    if ! action.yield_value.is_some() {
                        self.next()
                    }
                }

                // For now we'll just do depth-first, since it's simplest.
                if let Some(yielded) = action.yield_value {
                    return yielded;
                }

                // Clear the base iterator if we were asked to terminate
                // the walk.  Note that any recursive walks on
                // `self.sub_iterator` will continue until that iterator
                // is exhausted.
                if action.flags & action::TERMINATE {
                    self.base_iterator = None; }
            } else {
                // Base iterator is exhausted; clear it.
                self.base_iterator = None;
            }
        }
        return None;
    }

    /// We implement `size_hint` as the sum of the hints for the current base-
    /// and sub-iterators, if they're not `None`.  We return an upper bound
    /// only if both iterators are `None`.
    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut min = 0;
        if let Some(iter) = self.sub_iterator { min += iter.size_hint().0 }
        if let Some(iter) = self.base_iterator { min += iter.size_hint().0 }

        (min, if self.sub_iterator.is_none() && self.base_iterator.is_none() { Some(0) } else { None })
    }
}
<commit_msg>pattern/walk: fixed typo in a comment<commit_after>//! Utilities for generalized iterators over trees of arbitrary types.

use std;

/// Descriptions of actions that may be taken on a given node when traversing
/// a pattern tree.
pub mod action {
    enum Flag {
        /// Terminate iteration after performing other specified actions.
        TERMINATE = 1,
    }

    pub use self::Flag::*;

    struct Action<U,V> {
        yield_value: Option<U>,
        recurse_on: Option<V>,
        flags: u8
    }
}

pub use self::action::Action;

/// Interface for patterns whose elements may be visited in
/// a runtime-specified manner.
///
/// @tparam Tag Marker type used to discriminate the "type" of walk being
///     implemented.  A particular type may be walked for different purposes,
///     such as to visit *all* elements, or only certain ones.
///
/// @tparam Yielded Type of item the walkable should implement an iterator for.
trait Walkable<Tag,Yielded>: std::marker::PhantomFn<Tag> {
    /// Iterator type for the implementer's underlying container.
    type BaseIterator;
    type Item = <Self::BaseIterator as Iterator>::Item;
    type Action = Action<Yielded,Self::Item>;

    /// Fetch the initial iterator to use for a walk.
    fn iter(&self) -> Self::BaseIterator;

    /// Determine the action to take for a given node in the implementor's
    /// element tree.
    ///
    /// @param element Pattern element to process.
    ///
    /// @return Tuple containing the optionally-yielded element, and a set of
    ///     flags indicating how to proceed.  Action::RECURSE is only valid
    ///     when `Item` implements Walkable<Yielded>.
    fn action<'a>(element: &'a Self::Item) -> Self::Action
        where Self::Item: Walkable<Tag,Yielded>;
}

// FIXME: should the order of `T` and `Yielded` be reversed?
/// Iterator used to perform a particular walk on a particular type.
///
/// @tparam Tag Walk-type tag.
///
/// @tparam Yielded `Item` type for the iterator implementation of
///     the structure.
///
/// @tparam T Top-level Walkable type for which this structure is an iterator.
struct Walker<Tag,Yielded,T> where T: Walkable<Tag,Yielded> {
    base_iterator: Option<<T as Walkable<Tag,Yielded>>::BaseIterator>,
    sub_iterator: Option<Walker<Tag,Yielded,Yielded>>,
}

impl<Tag,Yielded,T> Walker<Tag,Yielded,T>
where T: Walkable<Tag,Yielded> {
    /// Create a new walker iterator from the given base iterator.
    pub fn new(base: <T as Walkable<Tag,Yielded>>::BaseIterator) -> Walker<Tag,Yielded,T> {
        Walker{base_iterator: base, sub_iterator: None}
    }
}

impl<'a,Tag,Yielded,T> Iterator for Walker<Tag,Yielded,T>
where T: Walkable<Tag,Yielded>, Yielded: Walkable<Tag,Yielded> {
    type Item = &'a Yielded;

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        // "can't use type parameter from outer function" Why not?  And it's not a function.
        //type Walk = Walkable<Tag,Yielded>;
        // "huh?  why's there a less-than sign in here?"  Because I put it there.
        //use self::Walkable<Tag,Yielded> as Walk;

        if let Some(ref iter) = self.sub_iterator {
            if let Some(yielded) = (*iter).next() {
                return yielded; }
            else {
                // Sub-iterator is empty; clear it and fall through to the
                // base iterator.
                self.sub_iterator = None;
            } }
        if let Some(ref iter) = self.base_iterator {
            if let Some(ref element) = (*iter).next() {
                let action = <T as Walkable<Tag,Yielded>>::action(element);

                // FIXME: need to provide a way to specify order in which
                // to recurse vs. yield.  The solution should allow for
                // selection of different traversal methods -- need to come
                // up with an API for that.
                if let Some(recurse_item) = action.recurse_on {
                    self.sub_iterator = Some(Walker::new(<Yielded as Walkable<Tag,Yielded>>::iter(recurse_item)));

                    // Recurse immediately if we have no value to yield.
                    if ! action.yield_value.is_some() {
                        self.next()
                    }
                }

                // For now we'll just do depth-first, since it's simplest.
                if let Some(yielded) = action.yield_value {
                    return yielded;
                }

                // Clear the base iterator if we were asked to terminate
                // the walk.  Note that any recursive walks on
                // `self.sub_iterator` will continue until that iterator
                // is exhausted.
                if action.flags & action::TERMINATE {
                    self.base_iterator = None; }
            } else {
                // Base iterator is exhausted; clear it.
                self.base_iterator = None;
            }
        }
        return None;
    }

    /// We implement `size_hint` as the sum of the hints for the current base-
    /// and sub-iterators, if they're not `None`.  We return an upper bound
    /// only if both iterators are `None`.
    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut min = 0;
        if let Some(iter) = self.sub_iterator { min += iter.size_hint().0 }
        if let Some(iter) = self.base_iterator { min += iter.size_hint().0 }

        (min, if self.sub_iterator.is_none() && self.base_iterator.is_none() { Some(0) } else { None })
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::collections::BTreeMap;

use url::{Url, ParseError};
use sidekiq::{Job, JobOpts, Value};
use url_serde::Serde;
use html5ever::tokenizer::{TokenSink, Token, TagToken, TokenSinkResult};

#[derive(Serialize, Debug)]
pub struct Page {
    pub url: Serde<Url>,
    pub document: String,
    pub headers: BTreeMap<String, String>,
    pub urls: Vec<Serde<Url>>,
}

impl TokenSink for Page {
    type Handle = ();

    fn process_token(&mut self, token: Token) -> TokenSinkResult<()> {
        if let TagToken(tag) = token {
            match tag.name {
                local_name!("a") => {
                    for attr in &tag.attrs {
                        if attr.name.local.to_string() == "href" {
                            if let Some(u) = self.can_enqueue(&attr.value) {
                                self.urls.push(Serde(u));
                            }
                        }
                    }
                }
                _ => {}
            }
        }
        TokenSinkResult::Continue
    }
}

impl Page {
    pub fn new(url: Url, document: String, headers: BTreeMap<String, String>) -> Self {
        Page {
            url: Serde(url),
            document: document,
            headers: headers,
            urls: Vec::new(),
        }
    }

    pub fn to_job(&self) -> Job {
        let job_opts = JobOpts {
            queue: maman_name!().to_string().to_lowercase(),
            ..Default::default()
        };
        Job::new(maman_name!().to_string(), vec![self.as_object()], job_opts)
    }

    pub fn as_object(&self) -> Value {
        json!({
            "url": &self.url,
            "document": &self.document,
            "headers": &self.headers,
            "urls": &self.urls,
        })
    }

    fn normalize_url(&self, url: &str) -> Option<Url> {
        match Url::parse(url) {
            Ok(u) => Some(u),
            Err(ParseError::RelativeUrlWithoutBase) => Some(self.url.join(url).unwrap()),
            Err(_) => None,
        }
    }

    fn url_without_fragment(&self, url: &str) -> Option<Url> {
        match self.normalize_url(url) {
            Some(mut u) => {
                u.set_fragment(None);
                Some(u)
            }
            None => None,
        }
    }

    fn url_eq(&self, url: &Url) -> bool {
        self.url == *url
    }

    fn domain_eq(&self, url: &Url) -> bool {
        self.url.domain() == url.domain()
    }

    fn can_enqueue(&self, url: &str) -> Option<Url> {
        match self.url_without_fragment(url) {
            Some(u) => {
                match u.scheme() {
                    "http" | "https" => {
                        if !self.url_eq(&u) && self.domain_eq(&u) {
                            Some(u)
                        } else {
                            None
                        }
                    }
                    _ => None,
                }
            }
            None => None,
        }
    }
}
<commit_msg>Allow single_match for process_token<commit_after>use std::default::Default;
use std::collections::BTreeMap;

use url::{Url, ParseError};
use sidekiq::{Job, JobOpts, Value};
use url_serde::Serde;
use html5ever::tokenizer::{TokenSink, Token, TagToken, TokenSinkResult};

#[derive(Serialize, Debug)]
pub struct Page {
    pub url: Serde<Url>,
    pub document: String,
    pub headers: BTreeMap<String, String>,
    pub urls: Vec<Serde<Url>>,
}

impl TokenSink for Page {
    type Handle = ();

    #[cfg_attr(feature = "clippy", allow(single_match))]
    fn process_token(&mut self, token: Token) -> TokenSinkResult<()> {
        if let TagToken(tag) = token {
            match tag.name {
                local_name!("a") => {
                    for attr in &tag.attrs {
                        if attr.name.local.to_string() == "href" {
                            if let Some(u) = self.can_enqueue(&attr.value) {
                                self.urls.push(Serde(u));
                            }
                        }
                    }
                }
                _ => {}
            }
        }
        TokenSinkResult::Continue
    }
}

impl Page {
    pub fn new(url: Url, document: String, headers: BTreeMap<String, String>) -> Self {
        Page {
            url: Serde(url),
            document: document,
            headers: headers,
            urls: Vec::new(),
        }
    }

    pub fn to_job(&self) -> Job {
        let job_opts = JobOpts {
            queue: maman_name!().to_string().to_lowercase(),
            ..Default::default()
        };
        Job::new(maman_name!().to_string(), vec![self.as_object()], job_opts)
    }

    pub fn as_object(&self) -> Value {
        json!({
            "url": &self.url,
            "document": &self.document,
            "headers": &self.headers,
            "urls": &self.urls,
        })
    }

    fn normalize_url(&self, url: &str) -> Option<Url> {
        match Url::parse(url) {
            Ok(u) => Some(u),
            Err(ParseError::RelativeUrlWithoutBase) => Some(self.url.join(url).unwrap()),
            Err(_) => None,
        }
    }

    fn url_without_fragment(&self, url: &str) -> Option<Url> {
        match self.normalize_url(url) {
            Some(mut u) => {
                u.set_fragment(None);
                Some(u)
            }
            None => None,
        }
    }

    fn url_eq(&self, url: &Url) -> bool {
        self.url == *url
    }

    fn domain_eq(&self, url: &Url) -> bool {
        self.url.domain() == url.domain()
    }

    fn can_enqueue(&self, url: &str) -> Option<Url> {
        match self.url_without_fragment(url) {
            Some(u) => {
                match u.scheme() {
                    "http" | "https" => {
                        if !self.url_eq(&u) && self.domain_eq(&u) {
                            Some(u)
                        } else {
                            None
                        }
                    }
                    _ => None,
                }
            }
            None => None,
        }
    }
}
<|endoftext|>