<commit_before>use libc;

use ffi;
use error::{YamlError, YamlErrorContext, YamlMark};
use event::YamlEvent;
use document::{YamlDocument};
use codecs;

use std::mem;
use std::io;
use std::io::{Read, ErrorKind};
use std::slice;

pub struct YamlEventStream<P> {
    parser: Box<P>,
}

impl<P:YamlParser> Iterator for YamlEventStream<P> {
    type Item = Result<YamlEvent, YamlError>;

    fn next(&mut self) -> Option<Result<YamlEvent, YamlError>> {
        unsafe {
            match self.parser.parse_event() {
                Some(YamlEvent::YamlNoEvent) => None,
                Some(evt) => Some(Ok(evt)),
                None => Some(Err(self.parser.get_error()))
            }
        }
    }
}

pub struct YamlDocumentStream<P> {
    parser: Box<P>,
}

impl<P:YamlParser> Iterator for YamlDocumentStream<P> {
    type Item = Result<Box<YamlDocument>, YamlError>;

    fn next(&mut self) -> Option<Result<Box<YamlDocument>, YamlError>> {
        unsafe {
            match YamlDocument::parser_load(&mut self.parser.base_parser_ref().parser_mem) {
                Some(doc) => if doc.is_empty() {
                    None
                } else {
                    Some(Ok(doc))
                },
                None => Some(Err(self.parser.get_error()))
            }
        }
    }
}

pub struct InternalEvent {
    event_mem: ffi::yaml_event_t
}

impl Drop for InternalEvent {
    fn drop(&mut self) {
        unsafe {
            self.event_mem.delete()
        }
    }
}

pub trait YamlParser: Sized {
    unsafe fn base_parser_ref<'r>(&'r mut self) -> &'r mut YamlBaseParser;
    unsafe fn get_error(&mut self) -> YamlError;

    unsafe fn parse_event(&mut self) -> Option<YamlEvent> {
        let mut event = InternalEvent {
            event_mem: mem::uninitialized()
        };

        if !self.base_parser_ref().parse(&mut event.event_mem) {
            None
        } else {
            Some(YamlEvent::load(&event.event_mem))
        }
    }

    fn parse(self: Box<Self>) -> YamlEventStream<Self> {
        YamlEventStream {
            parser: self,
        }
    }

    fn load(self: Box<Self>) -> YamlDocumentStream<Self> {
        YamlDocumentStream {
            parser: self,
        }
    }
}

extern fn handle_reader_cb(data: *mut YamlIoParser, buffer: *mut u8, size: libc::size_t, size_read: *mut libc::size_t) -> libc::c_int {
    unsafe {
        let mut buf = slice::from_raw_parts_mut(buffer, size as usize);
        let parser = &mut *data;
        match parser.reader.read(buf) {
            Ok(size) => {
                *size_read = size as libc::size_t;
                return 1;
            },
            Err(err) => {
                parser.io_error = Some(err);
                return 0;
            }
        }
    }
}

pub struct YamlBaseParser {
    parser_mem: ffi::yaml_parser_t,
}

impl YamlBaseParser {
    unsafe fn new() -> YamlBaseParser {
        YamlBaseParser {
            parser_mem: mem::uninitialized()
        }
    }

    unsafe fn initialize(&mut self) -> bool {
        ffi::yaml_parser_initialize(&mut self.parser_mem) != 0
    }

    unsafe fn set_input_string(&mut self, input: *const u8, size: usize) {
        ffi::yaml_parser_set_input_string(&mut self.parser_mem, input, size as libc::size_t);
    }

    unsafe fn parse(&mut self, event: &mut ffi::yaml_event_t) -> bool {
        ffi::yaml_parser_parse(&mut self.parser_mem, event) != 0
    }

    unsafe fn build_error(&self) -> YamlError {
        let context = YamlErrorContext {
            byte_offset: self.parser_mem.problem_offset as usize,
            problem_mark: YamlMark::conv(&self.parser_mem.problem_mark),
            context: codecs::decode_c_str(self.parser_mem.context as *const ffi::yaml_char_t),
            context_mark: YamlMark::conv(&self.parser_mem.context_mark),
        };

        YamlError {
            kind: self.parser_mem.error,
            problem: codecs::decode_c_str(self.parser_mem.problem as *const ffi::yaml_char_t),
            io_error: None,
            context: Some(context)
        }
    }
}

impl Drop for YamlBaseParser {
    fn drop(&mut self) {
        unsafe {
            ffi::yaml_parser_delete(&mut self.parser_mem);
        }
    }
}

pub struct YamlByteParser<'r> {
    base_parser: YamlBaseParser,
    data: &'r [u8]
}

impl<'r> YamlParser for YamlByteParser<'r> {
    unsafe fn base_parser_ref<'a>(&'a mut self) -> &'a mut YamlBaseParser {
        &mut self.base_parser
    }

    unsafe fn get_error(&mut self) -> YamlError {
        self.base_parser.build_error()
    }
}

impl<'r> YamlByteParser<'r> {
    pub fn init(bytes: &'r [u8], encoding: ffi::YamlEncoding) -> Box<YamlByteParser<'r>> {
        unsafe {
            let mut parser = box YamlByteParser {
                base_parser: YamlBaseParser::new(),
                data: bytes
            };

            if !parser.base_parser.initialize() {
                panic!("failed to initialize yaml_parser_t");
            }

            ffi::yaml_parser_set_encoding(&mut parser.base_parser.parser_mem, encoding);
            parser.base_parser.set_input_string(bytes.as_ptr(), bytes.len());

            parser
        }
    }
}

pub struct YamlIoParser<'r> {
    base_parser: YamlBaseParser,
    reader: &'r mut (Read+'r),
    io_error: Option<io::Error>,
}

impl<'r> YamlParser for YamlIoParser<'r> {
    unsafe fn base_parser_ref<'a>(&'a mut self) -> &'a mut YamlBaseParser {
        &mut self.base_parser
    }

    unsafe fn get_error(&mut self) -> YamlError {
        let mut error = self.base_parser.build_error();
        mem::swap(&mut (error.io_error), &mut (self.io_error));
        return error;
    }
}

impl<'r> YamlIoParser<'r> {
    pub fn init<'a>(reader: &'a mut Read, encoding: ffi::YamlEncoding) -> Box<YamlIoParser<'a>> {
        unsafe {
            let mut parser = box YamlIoParser {
                base_parser: YamlBaseParser::new(),
                reader: reader,
                io_error: None
            };

            if !parser.base_parser.initialize() {
                panic!("failed to initialize yaml_parser_t");
            }

            ffi::yaml_parser_set_encoding(&mut parser.base_parser.parser_mem, encoding);

            ffi::yaml_parser_set_input(&mut parser.base_parser.parser_mem, handle_reader_cb, mem::transmute(&mut *parser));

            parser
        }
    }
}

#[cfg(test)]
mod test {
    use event::{YamlEvent, YamlSequenceParam, YamlScalarParam};
    use event::YamlEvent::*;
    use document::{YamlDocument, YamlNode};
    use parser;
    use parser::YamlParser;
    use error::YamlError;
    use ffi::YamlErrorType;
    use ffi::YamlEncoding::*;
    use ffi::YamlScalarStyle::*;
    use ffi::YamlSequenceStyle::*;
    use std::io::BufReader;

    #[test]
    fn test_byte_parser() {
        let data = "[1, 2, 3]";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let expected = Ok(vec![
            YamlStreamStartEvent(YamlUtf8Encoding),
            YamlDocumentStartEvent(None, vec![], true),
            YamlSequenceStartEvent(YamlSequenceParam{anchor: None, tag: None, implicit: true, style: YamlFlowSequenceStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "1".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "2".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "3".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlSequenceEndEvent,
            YamlDocumentEndEvent(true),
            YamlStreamEndEvent
        ]);

        let stream: Result<Vec<YamlEvent>, YamlError> = parser.parse().collect();

        assert_eq!(expected, stream);
    }

    #[test]
    fn test_io_parser() {
        let data = "[1, 2, 3]";
        let mut reader = BufReader::new(data.as_bytes());
        let parser = parser::YamlIoParser::init(&mut reader, YamlUtf8Encoding);
        let expected = Ok(vec![
            YamlStreamStartEvent(YamlUtf8Encoding),
            YamlDocumentStartEvent(None, vec![], true),
            YamlSequenceStartEvent(YamlSequenceParam{anchor: None, tag: None, implicit: true, style: YamlFlowSequenceStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "1".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "2".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "3".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlSequenceEndEvent,
            YamlDocumentEndEvent(true),
            YamlStreamEndEvent
        ]);

        let stream: Result<Vec<YamlEvent>, YamlError> = parser.parse().collect();

        assert_eq!(expected, stream);
    }

    #[test]
    fn test_byte_parser_mapping() {
        let data = "{\"a\": 1, \"b\":2}";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let expected = Ok(vec![
            YamlStreamStartEvent(YamlUtf8Encoding),
            YamlDocumentStartEvent(None, vec![], true),
            YamlMappingStartEvent(YamlSequenceParam{anchor: None, tag: None, implicit: true, style: YamlFlowSequenceStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "a".to_string(), plain_implicit: false, quoted_implicit: true, style: YamlDoubleQuotedScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "1".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "b".to_string(), plain_implicit: false, quoted_implicit: true, style: YamlDoubleQuotedScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "2".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlMappingEndEvent,
            YamlDocumentEndEvent(true),
            YamlStreamEndEvent
        ]);

        let stream: Result<Vec<YamlEvent>, YamlError> = parser.parse().collect();

        assert_eq!(expected, stream);
    }

    #[test]
    fn test_parser_error() {
        let data = "\"ab";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let mut stream = parser.parse();

        let stream_start = stream.next();
        assert_eq!(Some(Ok(YamlStreamStartEvent(YamlUtf8Encoding))), stream_start);

        let stream_err = stream.next();
        match stream_err {
            Some(Err(err)) => assert_eq!(YamlErrorType::YAML_SCANNER_ERROR, err.kind),
            evt => panic!("unexpected result: {:?}", evt),
        }
    }

    #[test]
    fn test_document() {
        let data = "[1, 2, 3]";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let docs_res:Result<Vec<Box<YamlDocument>>, YamlError> = parser.load().collect();

        match docs_res {
            Err(e) => panic!("unexpected result: {:?}", e),
            Ok(docs) => match docs.as_slice().first().and_then(|doc| doc.root()) {
                Some(YamlNode::YamlSequenceNode(seq)) => {
                    let values:Vec<String> = seq.values().map(|node| {
                        match node {
                            YamlNode::YamlScalarNode(scalar) => scalar.get_value(),
                            _ => panic!("unexpected scalar")
                        }
                    }).collect();
                    assert_eq!(vec!["1".to_string(), "2".to_string(), "3".to_string()], values)
                },
                _ => panic!("unexpected result")
            }
        }
    }

    #[test]
    fn test_mapping_document() {
        let data = "{\"a\": 1, \"b\": 2}";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let docs_res:Result<Vec<Box<YamlDocument>>, YamlError> = parser.load().collect();

        match docs_res {
            Err(e) => panic!("unexpected result: {:?}", e),
            Ok(docs) => match docs.as_slice().first().and_then(|doc| doc.root()) {
                Some(YamlNode::YamlMappingNode(seq)) => {
                    let values:Vec<(String, String)> = seq.pairs().map(|(key, value)| {
                        (
                            match key {
                                YamlNode::YamlScalarNode(scalar) => scalar.get_value(),
                                _ => panic!("unexpected scalar")
                            },
                            match value {
                                YamlNode::YamlScalarNode(scalar) => scalar.get_value(),
                                _ => panic!("unexpected scalar")
                            }
                        )
                    }).collect();
                    assert_eq!(vec![("a".to_string(), "1".to_string()), ("b".to_string(), "2".to_string())], values)
                },
                _ => panic!("unexpected result")
            }
        }
    }
}
<commit_msg>Use PhantomData to represent lifetime of foreign pointer<commit_after>use libc;

use ffi;
use error::{YamlError, YamlErrorContext, YamlMark};
use event::YamlEvent;
use document::{YamlDocument};
use codecs;

use std::mem;
use std::io;
use std::io::Read;
use std::slice;
use std::marker::PhantomData;

pub struct YamlEventStream<P> {
    parser: Box<P>,
}

impl<P:YamlParser> Iterator for YamlEventStream<P> {
    type Item = Result<YamlEvent, YamlError>;

    fn next(&mut self) -> Option<Result<YamlEvent, YamlError>> {
        unsafe {
            match self.parser.parse_event() {
                Some(YamlEvent::YamlNoEvent) => None,
                Some(evt) => Some(Ok(evt)),
                None => Some(Err(self.parser.get_error()))
            }
        }
    }
}

pub struct YamlDocumentStream<P> {
    parser: Box<P>,
}

impl<P:YamlParser> Iterator for YamlDocumentStream<P> {
    type Item = Result<Box<YamlDocument>, YamlError>;

    fn next(&mut self) -> Option<Result<Box<YamlDocument>, YamlError>> {
        unsafe {
            match YamlDocument::parser_load(&mut self.parser.base_parser_ref().parser_mem) {
                Some(doc) => if doc.is_empty() {
                    None
                } else {
                    Some(Ok(doc))
                },
                None => Some(Err(self.parser.get_error()))
            }
        }
    }
}

pub struct InternalEvent {
    event_mem: ffi::yaml_event_t
}

impl Drop for InternalEvent {
    fn drop(&mut self) {
        unsafe {
            self.event_mem.delete()
        }
    }
}

pub trait YamlParser: Sized {
    unsafe fn base_parser_ref<'r>(&'r mut self) -> &'r mut YamlBaseParser;
    unsafe fn get_error(&mut self) -> YamlError;

    unsafe fn parse_event(&mut self) -> Option<YamlEvent> {
        let mut event = InternalEvent {
            event_mem: mem::uninitialized()
        };

        if !self.base_parser_ref().parse(&mut event.event_mem) {
            None
        } else {
            Some(YamlEvent::load(&event.event_mem))
        }
    }

    fn parse(self: Box<Self>) -> YamlEventStream<Self> {
        YamlEventStream {
            parser: self,
        }
    }

    fn load(self: Box<Self>) -> YamlDocumentStream<Self> {
        YamlDocumentStream {
            parser: self,
        }
    }
}

extern fn handle_reader_cb(data: *mut YamlIoParser, buffer: *mut u8, size: libc::size_t, size_read: *mut libc::size_t) -> libc::c_int {
    unsafe {
        let mut buf = slice::from_raw_parts_mut(buffer, size as usize);
        let parser = &mut *data;
        match parser.reader.read(buf) {
            Ok(size) => {
                *size_read = size as libc::size_t;
                return 1;
            },
            Err(err) => {
                parser.io_error = Some(err);
                return 0;
            }
        }
    }
}

pub struct YamlBaseParser {
    parser_mem: ffi::yaml_parser_t,
}

impl YamlBaseParser {
    unsafe fn new() -> YamlBaseParser {
        YamlBaseParser {
            parser_mem: mem::uninitialized()
        }
    }

    unsafe fn initialize(&mut self) -> bool {
        ffi::yaml_parser_initialize(&mut self.parser_mem) != 0
    }

    unsafe fn set_input_string(&mut self, input: *const u8, size: usize) {
        ffi::yaml_parser_set_input_string(&mut self.parser_mem, input, size as libc::size_t);
    }

    unsafe fn parse(&mut self, event: &mut ffi::yaml_event_t) -> bool {
        ffi::yaml_parser_parse(&mut self.parser_mem, event) != 0
    }

    unsafe fn build_error(&self) -> YamlError {
        let context = YamlErrorContext {
            byte_offset: self.parser_mem.problem_offset as usize,
            problem_mark: YamlMark::conv(&self.parser_mem.problem_mark),
            context: codecs::decode_c_str(self.parser_mem.context as *const ffi::yaml_char_t),
            context_mark: YamlMark::conv(&self.parser_mem.context_mark),
        };

        YamlError {
            kind: self.parser_mem.error,
            problem: codecs::decode_c_str(self.parser_mem.problem as *const ffi::yaml_char_t),
            io_error: None,
            context: Some(context)
        }
    }
}

impl Drop for YamlBaseParser {
    fn drop(&mut self) {
        unsafe {
            ffi::yaml_parser_delete(&mut self.parser_mem);
        }
    }
}

pub struct YamlByteParser<'r> {
    base_parser: YamlBaseParser,
    data: PhantomData<&'r [u8]>
}

impl<'r> YamlParser for YamlByteParser<'r> {
    unsafe fn base_parser_ref<'a>(&'a mut self) -> &'a mut YamlBaseParser {
        &mut self.base_parser
    }

    unsafe fn get_error(&mut self) -> YamlError {
        self.base_parser.build_error()
    }
}

impl<'r> YamlByteParser<'r> {
    pub fn init(bytes: &'r [u8], encoding: ffi::YamlEncoding) -> Box<YamlByteParser<'r>> {
        unsafe {
            let mut parser = box YamlByteParser {
                base_parser: YamlBaseParser::new(),
                data: PhantomData
            };

            if !parser.base_parser.initialize() {
                panic!("failed to initialize yaml_parser_t");
            }

            ffi::yaml_parser_set_encoding(&mut parser.base_parser.parser_mem, encoding);
            parser.base_parser.set_input_string(bytes.as_ptr(), bytes.len());

            parser
        }
    }
}

pub struct YamlIoParser<'r> {
    base_parser: YamlBaseParser,
    reader: &'r mut (Read+'r),
    io_error: Option<io::Error>,
}

impl<'r> YamlParser for YamlIoParser<'r> {
    unsafe fn base_parser_ref<'a>(&'a mut self) -> &'a mut YamlBaseParser {
        &mut self.base_parser
    }

    unsafe fn get_error(&mut self) -> YamlError {
        let mut error = self.base_parser.build_error();
        mem::swap(&mut (error.io_error), &mut (self.io_error));
        return error;
    }
}

impl<'r> YamlIoParser<'r> {
    pub fn init<'a>(reader: &'a mut Read, encoding: ffi::YamlEncoding) -> Box<YamlIoParser<'a>> {
        unsafe {
            let mut parser = box YamlIoParser {
                base_parser: YamlBaseParser::new(),
                reader: reader,
                io_error: None
            };

            if !parser.base_parser.initialize() {
                panic!("failed to initialize yaml_parser_t");
            }

            ffi::yaml_parser_set_encoding(&mut parser.base_parser.parser_mem, encoding);

            ffi::yaml_parser_set_input(&mut parser.base_parser.parser_mem, handle_reader_cb, mem::transmute(&mut *parser));

            parser
        }
    }
}

#[cfg(test)]
mod test {
    use event::{YamlEvent, YamlSequenceParam, YamlScalarParam};
    use event::YamlEvent::*;
    use document::{YamlDocument, YamlNode};
    use parser;
    use parser::YamlParser;
    use error::YamlError;
    use ffi::YamlErrorType;
    use ffi::YamlEncoding::*;
    use ffi::YamlScalarStyle::*;
    use ffi::YamlSequenceStyle::*;
    use std::io::BufReader;

    #[test]
    fn test_byte_parser() {
        let data = "[1, 2, 3]";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let expected = Ok(vec![
            YamlStreamStartEvent(YamlUtf8Encoding),
            YamlDocumentStartEvent(None, vec![], true),
            YamlSequenceStartEvent(YamlSequenceParam{anchor: None, tag: None, implicit: true, style: YamlFlowSequenceStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "1".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "2".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "3".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlSequenceEndEvent,
            YamlDocumentEndEvent(true),
            YamlStreamEndEvent
        ]);

        let stream: Result<Vec<YamlEvent>, YamlError> = parser.parse().collect();

        assert_eq!(expected, stream);
    }

    #[test]
    fn test_io_parser() {
        let data = "[1, 2, 3]";
        let mut reader = BufReader::new(data.as_bytes());
        let parser = parser::YamlIoParser::init(&mut reader, YamlUtf8Encoding);
        let expected = Ok(vec![
            YamlStreamStartEvent(YamlUtf8Encoding),
            YamlDocumentStartEvent(None, vec![], true),
            YamlSequenceStartEvent(YamlSequenceParam{anchor: None, tag: None, implicit: true, style: YamlFlowSequenceStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "1".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "2".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "3".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlSequenceEndEvent,
            YamlDocumentEndEvent(true),
            YamlStreamEndEvent
        ]);

        let stream: Result<Vec<YamlEvent>, YamlError> = parser.parse().collect();

        assert_eq!(expected, stream);
    }

    #[test]
    fn test_byte_parser_mapping() {
        let data = "{\"a\": 1, \"b\":2}";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let expected = Ok(vec![
            YamlStreamStartEvent(YamlUtf8Encoding),
            YamlDocumentStartEvent(None, vec![], true),
            YamlMappingStartEvent(YamlSequenceParam{anchor: None, tag: None, implicit: true, style: YamlFlowSequenceStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "a".to_string(), plain_implicit: false, quoted_implicit: true, style: YamlDoubleQuotedScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "1".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "b".to_string(), plain_implicit: false, quoted_implicit: true, style: YamlDoubleQuotedScalarStyle}),
            YamlScalarEvent(YamlScalarParam{anchor: None, tag: None, value: "2".to_string(), plain_implicit: true, quoted_implicit: false, style: YamlPlainScalarStyle}),
            YamlMappingEndEvent,
            YamlDocumentEndEvent(true),
            YamlStreamEndEvent
        ]);

        let stream: Result<Vec<YamlEvent>, YamlError> = parser.parse().collect();

        assert_eq!(expected, stream);
    }

    #[test]
    fn test_parser_error() {
        let data = "\"ab";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let mut stream = parser.parse();

        let stream_start = stream.next();
        assert_eq!(Some(Ok(YamlStreamStartEvent(YamlUtf8Encoding))), stream_start);

        let stream_err = stream.next();
        match stream_err {
            Some(Err(err)) => assert_eq!(YamlErrorType::YAML_SCANNER_ERROR, err.kind),
            evt => panic!("unexpected result: {:?}", evt),
        }
    }

    #[test]
    fn test_document() {
        let data = "[1, 2, 3]";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let docs_res:Result<Vec<Box<YamlDocument>>, YamlError> = parser.load().collect();

        match docs_res {
            Err(e) => panic!("unexpected result: {:?}", e),
            Ok(docs) => match docs.as_slice().first().and_then(|doc| doc.root()) {
                Some(YamlNode::YamlSequenceNode(seq)) => {
                    let values:Vec<String> = seq.values().map(|node| {
                        match node {
                            YamlNode::YamlScalarNode(scalar) => scalar.get_value(),
                            _ => panic!("unexpected scalar")
                        }
                    }).collect();
                    assert_eq!(vec!["1".to_string(), "2".to_string(), "3".to_string()], values)
                },
                _ => panic!("unexpected result")
            }
        }
    }

    #[test]
    fn test_mapping_document() {
        let data = "{\"a\": 1, \"b\": 2}";
        let parser = parser::YamlByteParser::init(data.as_bytes(), YamlUtf8Encoding);
        let docs_res:Result<Vec<Box<YamlDocument>>, YamlError> = parser.load().collect();

        match docs_res {
            Err(e) => panic!("unexpected result: {:?}", e),
            Ok(docs) => match docs.as_slice().first().and_then(|doc| doc.root()) {
                Some(YamlNode::YamlMappingNode(seq)) => {
                    let values:Vec<(String, String)> = seq.pairs().map(|(key, value)| {
                        (
                            match key {
                                YamlNode::YamlScalarNode(scalar) => scalar.get_value(),
                                _ => panic!("unexpected scalar")
                            },
                            match value {
                                YamlNode::YamlScalarNode(scalar) => scalar.get_value(),
                                _ => panic!("unexpected scalar")
                            }
                        )
                    }).collect();
                    assert_eq!(vec![("a".to_string(), "1".to_string()), ("b".to_string(), "2".to_string())], values)
                },
                _ => panic!("unexpected result")
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

type Triangle = [[f64; 2]; 3];

struct App {
    gl: GlGraphics,
    triangles: Vec<Triangle>,
    index: usize,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
        const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

        let i = self.index;
        let triangle = self.triangles[i];

        self.gl.draw(args.viewport(), |c, gl| {
            if i == 0 {
                clear(WHITE, gl);
            }

            let transform = c.transform.trans(0.0, 0.0);

            polygon(BLACK, &triangle, transform, gl);
        });
    }

    fn update(&mut self, _args: &UpdateArgs) {
        if (self.index as i32) + 1 >= self.triangles.len() as i32 {
            self.index = 0
        } else {
            self.index += 1;
        }
    }
}

fn sub_triangles(v: &Triangle) -> [Triangle; 4] {
    let (a, b, c) = (v[0], v[1], v[2]); // Vector destructuring is not yet stable in Rust 1.3.0.
    let (sax, say, sbx, sby, scx, scy) = (
            a[0] + ((b[0] - a[0]) / 2.0),
            a[1],
            b[0] - ((b[0] - c[0]) / 2.0),
            b[1] - ((b[1] - c[1]) / 2.0),
            a[0] + ((c[0] - a[0]) / 2.0),
            a[1] - ((a[1] - c[1]) / 2.0));

    [[[sax, say], [sbx, sby], [scx, scy]],
     [[a[0], a[1]], [sax, say], [scx, scy]],
     [[sax, say], [b[0], b[1]], [sbx, sby]],
     [[scx, scy], [sbx, sby], [c[0], c[1]]]]
}

fn sierpinski(depth: i32, vertices: Triangle) -> Vec<Triangle> {
    let mut triangles = vec![];

    match depth {
        0 => triangles,
        d => {
            let sub_tris = sub_triangles(&vertices);

            triangles.push(sub_tris[0]);

            for sub_tri in &sub_tris[1..] {
                for t in sierpinski(d - 1, *sub_tri) {
                    triangles.push(t);
                }
            }

            triangles
        },
    }
}

fn main() {
    const FPS: u64 = 60;
    let opengl = OpenGL::V3_2;
    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let triangles = sierpinski(8, [[50.0, 750.0], [950.0, 750.0], [500.0, 50.0]]);
    let mut app = App{gl: GlGraphics::new(opengl), triangles: triangles, index: 0};

    for e in window.events().max_fps(FPS).ups(FPS) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }

    }
}
<commit_msg>Use a reference in sierpinski<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

type Triangle = [[f64; 2]; 3];

struct App {
    gl: GlGraphics,
    triangles: Vec<Triangle>,
    index: usize,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
        const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

        let i = self.index;
        let triangle = self.triangles[i];

        self.gl.draw(args.viewport(), |c, gl| {
            if i == 0 {
                clear(WHITE, gl);
            }

            let transform = c.transform.trans(0.0, 0.0);

            polygon(BLACK, &triangle, transform, gl);
        });
    }

    fn update(&mut self, _args: &UpdateArgs) {
        if (self.index as i32) + 1 >= self.triangles.len() as i32 {
            self.index = 0
        } else {
            self.index += 1;
        }
    }
}

fn sub_triangles(v: &Triangle) -> [Triangle; 4] {
    let (a, b, c) = (v[0], v[1], v[2]); // Vector destructuring is not yet stable in Rust 1.3.0.
    let (sax, say, sbx, sby, scx, scy) = (
            a[0] + ((b[0] - a[0]) / 2.0),
            a[1],
            b[0] - ((b[0] - c[0]) / 2.0),
            b[1] - ((b[1] - c[1]) / 2.0),
            a[0] + ((c[0] - a[0]) / 2.0),
            a[1] - ((a[1] - c[1]) / 2.0));

    [[[sax, say], [sbx, sby], [scx, scy]],
     [[a[0], a[1]], [sax, say], [scx, scy]],
     [[sax, say], [b[0], b[1]], [sbx, sby]],
     [[scx, scy], [sbx, sby], [c[0], c[1]]]]
}

fn sierpinski(depth: i32, vertices: &Triangle) -> Vec<Triangle> {
    let mut triangles = vec![];

    match depth {
        0 => triangles,
        d => {
            let sub_tris = sub_triangles(vertices);

            triangles.push(sub_tris[0]);

            for sub_tri in &sub_tris[1..] {
                for t in sierpinski(d - 1, sub_tri) {
                    triangles.push(t);
                }
            }

            triangles
        },
    }
}

fn main() {
    const FPS: u64 = 60;
    let opengl = OpenGL::V3_2;
    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let triangles = sierpinski(8, &[[50.0, 750.0], [950.0, 750.0], [500.0, 50.0]]);
    let mut app = App{gl: GlGraphics::new(opengl), triangles: triangles, index: 0};

    for e in window.events().max_fps(FPS).ups(FPS) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }

    }
}
<|endoftext|>


<commit_before>// This module implements the Pike VM. That is, it guarantees linear time
// search of a regex on any text with memory use proportional to the size of
// the regex.
//
// It is equal in power to the backtracking engine in this crate, except the
// backtracking engine is typically faster on small regexes/texts at the
// expense of a bigger memory footprint.
//
// It can do more than the DFA can (specifically, record capture locations
// and execute Unicode word boundary assertions), but at a slower speed.
// Specifically, the Pike VM exectues a DFA implicitly by repeatedly expanding
// epsilon transitions. That is, the Pike VM engine can be in multiple states
// at once where as the DFA is only ever in one state at a time.
//
// Therefore, the Pike VM is generally treated as the fallback when the other
// matching engines either aren't feasible to run or are insufficient.

use std::mem;

use exec::ProgramCache;
use input::{Input, InputAt};
use prog::{InstPtr, Program};
use re_trait::Slot;
use sparse::SparseSet;

/// An NFA simulation matching engine.
#[derive(Debug)]
pub struct Fsm<'r, I> {
    /// The sequence of opcodes (among other things) that is actually executed.
    ///
    /// The program may be byte oriented or Unicode codepoint oriented.
    prog: &'r Program,
    /// An explicit stack used for following epsilon transitions. (This is
    /// borrowed from the cache.)
    stack: &'r mut Vec<FollowEpsilon>,
    /// The input to search.
    input: I,
}

/// A cached allocation that can be reused on each execution.
#[derive(Clone, Debug)]
pub struct Cache {
    /// A pair of ordered sets for tracking NFA states.
    clist: Threads,
    nlist: Threads,
    /// An explicit stack used for following epsilon transitions.
    stack: Vec<FollowEpsilon>,
}

/// An ordered set of NFA states and their captures.
#[derive(Clone, Debug)]
struct Threads {
    /// An ordered set of opcodes (each opcode is an NFA state).
    set: SparseSet,
    /// Captures for every NFA state.
    ///
    /// It is stored in row-major order, where the columns are the capture
    /// slots and the rows are the states.
    caps: Vec<Slot>,
    /// The number of capture slots stored per thread. (Every capture has
    /// two slots.)
    slots_per_thread: usize,
}

/// A representation of an explicit stack frame when following epsilon
/// transitions. This is used to avoid recursion.
#[derive(Clone, Debug)]
enum FollowEpsilon {
    /// Follow transitions at the given instruction pointer.
    IP(InstPtr),
    /// Restore the capture slot with the given position in the input.
    Capture { slot: usize, pos: Slot },
}

impl Cache {
    /// Create a new allocation used by the NFA machine to record execution
    /// and captures.
    pub fn new(_prog: &Program) -> Self {
        Cache { clist: Threads::new(), nlist: Threads::new(), stack: vec![] }
    }
}

impl<'r, I: Input> Fsm<'r, I> {
    /// Execute the NFA matching engine.
    ///
    /// If there's a match, `exec` returns `true` and populates the given
    /// captures accordingly.
    pub fn exec(
        prog: &'r Program,
        cache: &ProgramCache,
        matches: &mut [bool],
        slots: &mut [Slot],
        quit_after_match: bool,
        input: I,
        start: usize,
        end: usize,
    ) -> bool {
        let mut cache = cache.borrow_mut();
        let cache = &mut cache.pikevm;
        cache.clist.resize(prog.len(), prog.captures.len());
        cache.nlist.resize(prog.len(), prog.captures.len());
        let at = input.at(start);
        Fsm { prog: prog, stack: &mut cache.stack, input: input }.exec_(
            &mut cache.clist,
            &mut cache.nlist,
            matches,
            slots,
            quit_after_match,
            at,
            end,
        )
    }

    fn exec_(
        &mut self,
        mut clist: &mut Threads,
        mut nlist: &mut Threads,
        matches: &mut [bool],
        slots: &mut [Slot],
        quit_after_match: bool,
        mut at: InputAt,
        end: usize,
    ) -> bool {
        let mut matched = false;
        let mut all_matched = false;
        clist.set.clear();
        nlist.set.clear();
        'LOOP: loop {
            if clist.set.is_empty() {
                // Three ways to bail out when our current set of threads is
                // empty.
                //
                // 1. We have a match---so we're done exploring any possible
                //    alternatives. Time to quit. (We can't do this if we're
                //    looking for matches for multiple regexes, unless we know
                //    they all matched.)
                //
                // 2. If the expression starts with a '^' we can terminate as
                //    soon as the last thread dies.
                if (matched && matches.len() <= 1)
                    || all_matched
                    || (!at.is_start() && self.prog.is_anchored_start)
                {
                    break;
                }

                // 3. If there's a literal prefix for the program, try to
                //    jump ahead quickly. If it can't be found, then we can
                //    bail out early.
                if !self.prog.prefixes.is_empty() {
                    at = match self.input.prefix_at(&self.prog.prefixes, at) {
                        None => break,
                        Some(at) => at,
                    };
                }
            }

            // This simulates a preceding '.*?' for every regex by adding
            // a state starting at the current position in the input for the
            // beginning of the program only if we don't already have a match.
            if clist.set.is_empty()
                || (!self.prog.is_anchored_start && !all_matched)
            {
                self.add(&mut clist, slots, 0, at);
            }
            // The previous call to "add" actually inspects the position just
            // before the current character. For stepping through the machine,
            // we can to look at the current character, so we advance the
            // input.
            let at_next = self.input.at(at.next_pos());
            for i in 0..clist.set.len() {
                let ip = clist.set[i];
                if self.step(
                    &mut nlist,
                    matches,
                    slots,
                    clist.caps(ip),
                    ip,
                    at,
                    at_next,
                ) {
                    matched = true;
                    all_matched = all_matched || matches.iter().all(|&b| b);
                    if quit_after_match {
                        // If we only care if a match occurs (not its
                        // position), then we can quit right now.
                        break 'LOOP;
                    }
                    if self.prog.matches.len() == 1 {
                        // We don't need to check the rest of the threads
                        // in this set because we've matched something
                        // ("leftmost-first"). However, we still need to check
                        // threads in the next set to support things like
                        // greedy matching.
                        //
                        // This is only true on normal regexes. For regex sets,
                        // we need to mush on to observe other matches.
                        break;
                    }
                }
            }
            if at.pos() >= end {
                break;
            }
            at = at_next;
            mem::swap(clist, nlist);
            nlist.set.clear();
        }
        matched
    }

    /// Step through the input, one token (byte or codepoint) at a time.
    ///
    /// nlist is the set of states that will be processed on the next token
    /// in the input.
    ///
    /// caps is the set of captures passed by the caller of the NFA. They are
    /// written to only when a match state is visited.
    ///
    /// thread_caps is the set of captures set for the current NFA state, ip.
    ///
    /// at and at_next are the current and next positions in the input. at or
    /// at_next may be EOF.
    fn step(
        &mut self,
        nlist: &mut Threads,
        matches: &mut [bool],
        slots: &mut [Slot],
        thread_caps: &mut [Option<usize>],
        ip: usize,
        at: InputAt,
        at_next: InputAt,
    ) -> bool {
        use prog::Inst::*;
        match self.prog[ip] {
            Match(match_slot) => {
                if match_slot < matches.len() {
                    matches[match_slot] = true;
                }
                for (slot, val) in slots.iter_mut().zip(thread_caps.iter()) {
                    *slot = *val;
                }
                true
            }
            Char(ref inst) => {
                if inst.c == at.char() {
                    self.add(nlist, thread_caps, inst.goto, at_next);
                }
                false
            }
            Ranges(ref inst) => {
                if inst.matches(at.char()) {
                    self.add(nlist, thread_caps, inst.goto, at_next);
                }
                false
            }
            Bytes(ref inst) => {
                if let Some(b) = at.byte() {
                    if inst.matches(b) {
                        self.add(nlist, thread_caps, inst.goto, at_next);
                    }
                }
                false
            }
            EmptyLook(_) | Save(_) | Split(_) => false,
        }
    }

    /// Follows epsilon transitions and adds them for processing to nlist,
    /// starting at and including ip.
    fn add(
        &mut self,
        nlist: &mut Threads,
        thread_caps: &mut [Option<usize>],
        ip: usize,
        at: InputAt,
    ) {
        self.stack.push(FollowEpsilon::IP(ip));
        while let Some(frame) = self.stack.pop() {
            match frame {
                FollowEpsilon::IP(ip) => {
                    self.add_step(nlist, thread_caps, ip, at);
                }
                FollowEpsilon::Capture { slot, pos } => {
                    thread_caps[slot] = pos;
                }
            }
        }
    }

    /// A helper function for add that avoids excessive pushing to the stack.
    fn add_step(
        &mut self,
        nlist: &mut Threads,
        thread_caps: &mut [Option<usize>],
        mut ip: usize,
        at: InputAt,
    ) {
        // Instead of pushing and popping to the stack, we mutate ip as we
        // traverse the set of states. We only push to the stack when we
        // absolutely need recursion (restoring captures or following a
        // branch).
        use prog::Inst::*;
        loop {
            // Don't visit states we've already added.
            if nlist.set.contains(ip) {
                return;
            }
            nlist.set.insert(ip);
            match self.prog[ip] {
                EmptyLook(ref inst) => {
                    if self.input.is_empty_match(at, inst) {
                        ip = inst.goto;
                    }
                }
                Save(ref inst) => {
                    if inst.slot < thread_caps.len() {
                        self.stack.push(FollowEpsilon::Capture {
                            slot: inst.slot,
                            pos: thread_caps[inst.slot],
                        });
                        thread_caps[inst.slot] = Some(at.pos());
                    }
                    ip = inst.goto;
                }
                Split(ref inst) => {
                    self.stack.push(FollowEpsilon::IP(inst.goto2));
                    ip = inst.goto1;
                }
                Match(_) | Char(_) | Ranges(_) | Bytes(_) => {
                    let t = &mut nlist.caps(ip);
                    for (slot, val) in t.iter_mut().zip(thread_caps.iter()) {
                        *slot = *val;
                    }
                    return;
                }
            }
        }
    }
}

impl Threads {
    fn new() -> Self {
        Threads { set: SparseSet::new(0), caps: vec![], slots_per_thread: 0 }
    }

    fn resize(&mut self, num_insts: usize, ncaps: usize) {
        if num_insts == self.set.capacity() {
            return;
        }
        self.slots_per_thread = ncaps * 2;
        self.set = SparseSet::new(num_insts);
        self.caps = vec![None; self.slots_per_thread * num_insts];
    }

    fn caps(&mut self, pc: usize) -> &mut [Option<usize>] {
        let i = pc * self.slots_per_thread;
        &mut self.caps[i..i + self.slots_per_thread]
    }
}
<commit_msg>doc: fix internal typo<commit_after>// This module implements the Pike VM. That is, it guarantees linear time
// search of a regex on any text with memory use proportional to the size of
// the regex.
//
// It is equal in power to the backtracking engine in this crate, except the
// backtracking engine is typically faster on small regexes/texts at the
// expense of a bigger memory footprint.
//
// It can do more than the DFA can (specifically, record capture locations
// and execute Unicode word boundary assertions), but at a slower speed.
// Specifically, the Pike VM executes a DFA implicitly by repeatedly expanding
// epsilon transitions. That is, the Pike VM engine can be in multiple states
// at once where as the DFA is only ever in one state at a time.
//
// Therefore, the Pike VM is generally treated as the fallback when the other
// matching engines either aren't feasible to run or are insufficient.

use std::mem;

use exec::ProgramCache;
use input::{Input, InputAt};
use prog::{InstPtr, Program};
use re_trait::Slot;
use sparse::SparseSet;

/// An NFA simulation matching engine.
#[derive(Debug)]
pub struct Fsm<'r, I> {
    /// The sequence of opcodes (among other things) that is actually executed.
    ///
    /// The program may be byte oriented or Unicode codepoint oriented.
    prog: &'r Program,
    /// An explicit stack used for following epsilon transitions. (This is
    /// borrowed from the cache.)
    stack: &'r mut Vec<FollowEpsilon>,
    /// The input to search.
    input: I,
}

/// A cached allocation that can be reused on each execution.
#[derive(Clone, Debug)]
pub struct Cache {
    /// A pair of ordered sets for tracking NFA states.
    clist: Threads,
    nlist: Threads,
    /// An explicit stack used for following epsilon transitions.
    stack: Vec<FollowEpsilon>,
}

/// An ordered set of NFA states and their captures.
#[derive(Clone, Debug)]
struct Threads {
    /// An ordered set of opcodes (each opcode is an NFA state).
    set: SparseSet,
    /// Captures for every NFA state.
    ///
    /// It is stored in row-major order, where the columns are the capture
    /// slots and the rows are the states.
    caps: Vec<Slot>,
    /// The number of capture slots stored per thread. (Every capture has
    /// two slots.)
    slots_per_thread: usize,
}

/// A representation of an explicit stack frame when following epsilon
/// transitions. This is used to avoid recursion.
#[derive(Clone, Debug)]
enum FollowEpsilon {
    /// Follow transitions at the given instruction pointer.
    IP(InstPtr),
    /// Restore the capture slot with the given position in the input.
    Capture { slot: usize, pos: Slot },
}

impl Cache {
    /// Create a new allocation used by the NFA machine to record execution
    /// and captures.
    pub fn new(_prog: &Program) -> Self {
        Cache { clist: Threads::new(), nlist: Threads::new(), stack: vec![] }
    }
}

impl<'r, I: Input> Fsm<'r, I> {
    /// Execute the NFA matching engine.
    ///
    /// If there's a match, `exec` returns `true` and populates the given
    /// captures accordingly.
    pub fn exec(
        prog: &'r Program,
        cache: &ProgramCache,
        matches: &mut [bool],
        slots: &mut [Slot],
        quit_after_match: bool,
        input: I,
        start: usize,
        end: usize,
    ) -> bool {
        let mut cache = cache.borrow_mut();
        let cache = &mut cache.pikevm;
        cache.clist.resize(prog.len(), prog.captures.len());
        cache.nlist.resize(prog.len(), prog.captures.len());
        let at = input.at(start);
        Fsm { prog: prog, stack: &mut cache.stack, input: input }.exec_(
            &mut cache.clist,
            &mut cache.nlist,
            matches,
            slots,
            quit_after_match,
            at,
            end,
        )
    }

    fn exec_(
        &mut self,
        mut clist: &mut Threads,
        mut nlist: &mut Threads,
        matches: &mut [bool],
        slots: &mut [Slot],
        quit_after_match: bool,
        mut at: InputAt,
        end: usize,
    ) -> bool {
        let mut matched = false;
        let mut all_matched = false;
        clist.set.clear();
        nlist.set.clear();
        'LOOP: loop {
            if clist.set.is_empty() {
                // Three ways to bail out when our current set of threads is
                // empty.
                //
                // 1. We have a match---so we're done exploring any possible
                //    alternatives. Time to quit. (We can't do this if we're
                //    looking for matches for multiple regexes, unless we know
                //    they all matched.)
                //
                // 2. If the expression starts with a '^' we can terminate as
                //    soon as the last thread dies.
                if (matched && matches.len() <= 1)
                    || all_matched
                    || (!at.is_start() && self.prog.is_anchored_start)
                {
                    break;
                }

                // 3. If there's a literal prefix for the program, try to
                //    jump ahead quickly. If it can't be found, then we can
                //    bail out early.
                if !self.prog.prefixes.is_empty() {
                    at = match self.input.prefix_at(&self.prog.prefixes, at) {
                        None => break,
                        Some(at) => at,
                    };
                }
            }

            // This simulates a preceding '.*?' for every regex by adding
            // a state starting at the current position in the input for the
            // beginning of the program only if we don't already have a match.
            if clist.set.is_empty()
                || (!self.prog.is_anchored_start && !all_matched)
            {
                self.add(&mut clist, slots, 0, at);
            }
            // The previous call to "add" actually inspects the position just
            // before the current character. For stepping through the machine,
            // we can to look at the current character, so we advance the
            // input.
            let at_next = self.input.at(at.next_pos());
            for i in 0..clist.set.len() {
                let ip = clist.set[i];
                if self.step(
                    &mut nlist,
                    matches,
                    slots,
                    clist.caps(ip),
                    ip,
                    at,
                    at_next,
                ) {
                    matched = true;
                    all_matched = all_matched || matches.iter().all(|&b| b);
                    if quit_after_match {
                        // If we only care if a match occurs (not its
                        // position), then we can quit right now.
                        break 'LOOP;
                    }
                    if self.prog.matches.len() == 1 {
                        // We don't need to check the rest of the threads
                        // in this set because we've matched something
                        // ("leftmost-first"). However, we still need to check
                        // threads in the next set to support things like
                        // greedy matching.
                        //
                        // This is only true on normal regexes. For regex sets,
                        // we need to mush on to observe other matches.
                        break;
                    }
                }
            }
            if at.pos() >= end {
                break;
            }
            at = at_next;
            mem::swap(clist, nlist);
            nlist.set.clear();
        }
        matched
    }

    /// Step through the input, one token (byte or codepoint) at a time.
    ///
    /// nlist is the set of states that will be processed on the next token
    /// in the input.
    ///
    /// caps is the set of captures passed by the caller of the NFA. They are
    /// written to only when a match state is visited.
    ///
    /// thread_caps is the set of captures set for the current NFA state, ip.
    ///
    /// at and at_next are the current and next positions in the input. at or
    /// at_next may be EOF.
    fn step(
        &mut self,
        nlist: &mut Threads,
        matches: &mut [bool],
        slots: &mut [Slot],
        thread_caps: &mut [Option<usize>],
        ip: usize,
        at: InputAt,
        at_next: InputAt,
    ) -> bool {
        use prog::Inst::*;
        match self.prog[ip] {
            Match(match_slot) => {
                if match_slot < matches.len() {
                    matches[match_slot] = true;
                }
                for (slot, val) in slots.iter_mut().zip(thread_caps.iter()) {
                    *slot = *val;
                }
                true
            }
            Char(ref inst) => {
                if inst.c == at.char() {
                    self.add(nlist, thread_caps, inst.goto, at_next);
                }
                false
            }
            Ranges(ref inst) => {
                if inst.matches(at.char()) {
                    self.add(nlist, thread_caps, inst.goto, at_next);
                }
                false
            }
            Bytes(ref inst) => {
                if let Some(b) = at.byte() {
                    if inst.matches(b) {
                        self.add(nlist, thread_caps, inst.goto, at_next);
                    }
                }
                false
            }
            EmptyLook(_) | Save(_) | Split(_) => false,
        }
    }

    /// Follows epsilon transitions and adds them for processing to nlist,
    /// starting at and including ip.
    fn add(
        &mut self,
        nlist: &mut Threads,
        thread_caps: &mut [Option<usize>],
        ip: usize,
        at: InputAt,
    ) {
        self.stack.push(FollowEpsilon::IP(ip));
        while let Some(frame) = self.stack.pop() {
            match frame {
                FollowEpsilon::IP(ip) => {
                    self.add_step(nlist, thread_caps, ip, at);
                }
                FollowEpsilon::Capture { slot, pos } => {
                    thread_caps[slot] = pos;
                }
            }
        }
    }

    /// A helper function for add that avoids excessive pushing to the stack.
    fn add_step(
        &mut self,
        nlist: &mut Threads,
        thread_caps: &mut [Option<usize>],
        mut ip: usize,
        at: InputAt,
    ) {
        // Instead of pushing and popping to the stack, we mutate ip as we
        // traverse the set of states. We only push to the stack when we
        // absolutely need recursion (restoring captures or following a
        // branch).
        use prog::Inst::*;
        loop {
            // Don't visit states we've already added.
            if nlist.set.contains(ip) {
                return;
            }
            nlist.set.insert(ip);
            match self.prog[ip] {
                EmptyLook(ref inst) => {
                    if self.input.is_empty_match(at, inst) {
                        ip = inst.goto;
                    }
                }
                Save(ref inst) => {
                    if inst.slot < thread_caps.len() {
                        self.stack.push(FollowEpsilon::Capture {
                            slot: inst.slot,
                            pos: thread_caps[inst.slot],
                        });
                        thread_caps[inst.slot] = Some(at.pos());
                    }
                    ip = inst.goto;
                }
                Split(ref inst) => {
                    self.stack.push(FollowEpsilon::IP(inst.goto2));
                    ip = inst.goto1;
                }
                Match(_) | Char(_) | Ranges(_) | Bytes(_) => {
                    let t = &mut nlist.caps(ip);
                    for (slot, val) in t.iter_mut().zip(thread_caps.iter()) {
                        *slot = *val;
                    }
                    return;
                }
            }
        }
    }
}

impl Threads {
    fn new() -> Self {
        Threads { set: SparseSet::new(0), caps: vec![], slots_per_thread: 0 }
    }

    fn resize(&mut self, num_insts: usize, ncaps: usize) {
        if num_insts == self.set.capacity() {
            return;
        }
        self.slots_per_thread = ncaps * 2;
        self.set = SparseSet::new(num_insts);
        self.caps = vec![None; self.slots_per_thread * num_insts];
    }

    fn caps(&mut self, pc: usize) -> &mut [Option<usize>] {
        let i = pc * self.slots_per_thread;
        &mut self.caps[i..i + self.slots_per_thread]
    }
}
<|endoftext|>


<commit_before>use std::rand;
use std::rand::RngUtil;

pub mod ll {
    use std::libc::{c_int, uint8_t, uint32_t};

    //SDL_pixels.h
    pub struct SDL_Color {
        r: uint8_t,
        g: uint8_t,
        b: uint8_t,
        a: uint8_t,
    }

    pub struct SDL_Palette {
        ncolors: c_int,
        colors: *SDL_Color,
        version: uint32_t,
        refcount: c_int
    }

    pub struct SDL_PixelFormat {
        format: SDL_PixelFormatFlag,
        palette: *SDL_Palette,
        BitsPerPixel: uint8_t,
        BytesPerPixel: uint8_t,
        padding: [uint8_t, ..2],
        Rmask: uint8_t,
        Gmask: uint8_t,
        Bmask: uint8_t,
        Amask: uint8_t,
        Rloss: uint8_t,
        Gloss: uint8_t,
        Bloss: uint8_t,
        Aloss: uint8_t,
        Rshift: uint8_t,
        Gshift: uint8_t,
        Bshift: uint8_t,
        Ashift: uint8_t,
        refcount: c_int,
        next: *SDL_PixelFormat
    }

    pub type SDL_PixelFormatFlag = uint32_t;
    pub static SDL_PIXELFORMAT_UNKNOWN: SDL_PixelFormatFlag = 0x0;
    pub static SDL_PIXELFORMAT_INDEX1LSB: SDL_PixelFormatFlag = 0x11100100;
    pub static SDL_PIXELFORMAT_INDEX1MSB: SDL_PixelFormatFlag = 0x11200100;
    pub static SDL_PIXELFORMAT_INDEX4LSB: SDL_PixelFormatFlag = 0x12100400;
    pub static SDL_PIXELFORMAT_INDEX4MSB: SDL_PixelFormatFlag = 0x12200400;
    pub static SDL_PIXELFORMAT_INDEX8: SDL_PixelFormatFlag = 0x13000801;
    pub static SDL_PIXELFORMAT_RGB332: SDL_PixelFormatFlag = 0x14110801;
    pub static SDL_PIXELFORMAT_RGB444: SDL_PixelFormatFlag = 0x15120c02;
    pub static SDL_PIXELFORMAT_RGB555: SDL_PixelFormatFlag = 0x15130f02;
    pub static SDL_PIXELFORMAT_BGR555: SDL_PixelFormatFlag = 0x15530f02;
    pub static SDL_PIXELFORMAT_ARGB4444: SDL_PixelFormatFlag = 0x15321002;
    pub static SDL_PIXELFORMAT_RGBA4444: SDL_PixelFormatFlag = 0x15421002;
    pub static SDL_PIXELFORMAT_ABGR4444: SDL_PixelFormatFlag = 0x15721002;
    pub static SDL_PIXELFORMAT_BGRA4444: SDL_PixelFormatFlag = 0x15821002;
    pub static SDL_PIXELFORMAT_ARGB1555: SDL_PixelFormatFlag = 0x15331002;
    pub static SDL_PIXELFORMAT_RGBA5551: SDL_PixelFormatFlag = 0x15441002;
    pub static SDL_PIXELFORMAT_ABGR1555: SDL_PixelFormatFlag = 0x15731002;
    pub static SDL_PIXELFORMAT_BGRA5551: SDL_PixelFormatFlag = 0x15841002;
    pub static SDL_PIXELFORMAT_RGB565: SDL_PixelFormatFlag = 0x15151002;
    pub static SDL_PIXELFORMAT_BGR565: SDL_PixelFormatFlag = 0x15551002;
    pub static SDL_PIXELFORMAT_RGB24: SDL_PixelFormatFlag = 0x17101803;
    pub static SDL_PIXELFORMAT_BGR24: SDL_PixelFormatFlag = 0x17401803;
    pub static SDL_PIXELFORMAT_RGB888: SDL_PixelFormatFlag = 0x16161804;
    pub static SDL_PIXELFORMAT_RGBX8888: SDL_PixelFormatFlag = 0x16261804;
    pub static SDL_PIXELFORMAT_BGR888: SDL_PixelFormatFlag = 0x16561804;
    pub static SDL_PIXELFORMAT_BGRX8888: SDL_PixelFormatFlag = 0x16661804;
    pub static SDL_PIXELFORMAT_ARGB8888: SDL_PixelFormatFlag = 0x16362004;
    pub static SDL_PIXELFORMAT_RGBA8888: SDL_PixelFormatFlag = 0x16462004;
    pub static SDL_PIXELFORMAT_ABGR8888: SDL_PixelFormatFlag = 0x16762004;
    pub static SDL_PIXELFORMAT_BGRA8888: SDL_PixelFormatFlag = 0x16862004;
    pub static SDL_PIXELFORMAT_ARGB2101010: SDL_PixelFormatFlag = 0x16372004;
    pub static SDL_PIXELFORMAT_YV12: SDL_PixelFormatFlag = 0x32315659;
    pub static SDL_PIXELFORMAT_IYUV: SDL_PixelFormatFlag = 0x56555949;
    pub static SDL_PIXELFORMAT_YUY2: SDL_PixelFormatFlag = 0x32595559;
    pub static SDL_PIXELFORMAT_UYVY: SDL_PixelFormatFlag = 0x59565955;
    pub static SDL_PIXELFORMAT_YVYU: SDL_PixelFormatFlag = 0x55595659;
}
#[deriving(Eq)]
pub struct Palette {
    raw: *ll::SDL_Palette
}

#[deriving(Eq)]
pub enum Color {
    RGB(u8, u8, u8),
    RGBA(u8, u8, u8, u8)
}

impl rand::Rand for Color {
    fn rand<R: rand::Rng>(rng: &mut R) -> Color {
        if rng.gen() { RGBA(rng.gen(), rng.gen(), rng.gen(), rng.gen()) }
        else { RGB(rng.gen(), rng.gen(), rng.gen()) }
    }
}

#[deriving(Eq)]
pub enum PixelFormatFlag {
    Unknown = ll::SDL_PIXELFORMAT_UNKNOWN as int,
    Index1LSB = ll::SDL_PIXELFORMAT_INDEX1LSB as int,
    Index1MSB = ll::SDL_PIXELFORMAT_INDEX1MSB as int,
    Index4LSB = ll::SDL_PIXELFORMAT_INDEX4LSB as int,
    Index4MSB = ll::SDL_PIXELFORMAT_INDEX4MSB as int,
    Index8 = ll::SDL_PIXELFORMAT_INDEX8 as int,
    RGB332 = ll::SDL_PIXELFORMAT_RGB332 as int,
    RGB444 = ll::SDL_PIXELFORMAT_RGB444 as int,
    RGB555 = ll::SDL_PIXELFORMAT_RGB555 as int,
    BGR555 = ll::SDL_PIXELFORMAT_BGR555 as int,
    ARGB4444 = ll::SDL_PIXELFORMAT_ARGB4444 as int,
    RGBA4444 = ll::SDL_PIXELFORMAT_RGBA4444 as int,
    ABGR4444 = ll::SDL_PIXELFORMAT_ABGR4444 as int,
    BGRA4444 = ll::SDL_PIXELFORMAT_BGRA4444 as int,
    ARGB1555 = ll::SDL_PIXELFORMAT_ARGB1555 as int,
    RGBA5551 = ll::SDL_PIXELFORMAT_RGBA5551 as int,
    ABGR1555 = ll::SDL_PIXELFORMAT_ABGR1555 as int,
    BGRA5551 = ll::SDL_PIXELFORMAT_BGRA5551 as int,
    RGB565 = ll::SDL_PIXELFORMAT_RGB565 as int,
    BGR565 = ll::SDL_PIXELFORMAT_BGR565 as int,
    RGB24 = ll::SDL_PIXELFORMAT_RGB24 as int,
    BGR24 = ll::SDL_PIXELFORMAT_BGR24 as int,
    RGB888 = ll::SDL_PIXELFORMAT_RGB888 as int,
    RGBX8888 = ll::SDL_PIXELFORMAT_RGBX8888 as int,
    BGR888 = ll::SDL_PIXELFORMAT_BGR888 as int,
    BGRX8888 = ll::SDL_PIXELFORMAT_BGRX8888 as int,
    ARGB8888 = ll::SDL_PIXELFORMAT_ARGB8888 as int,
    RGBA8888 = ll::SDL_PIXELFORMAT_RGBA8888 as int,
    ABGR8888 = ll::SDL_PIXELFORMAT_ABGR8888 as int,
    BGRA8888 = ll::SDL_PIXELFORMAT_BGRA8888 as int,
    ARGB2101010 = ll::SDL_PIXELFORMAT_ARGB2101010 as int,
    YV12 = ll::SDL_PIXELFORMAT_YV12 as int,
    IYUV = ll::SDL_PIXELFORMAT_IYUV as int,
    YUY2 = ll::SDL_PIXELFORMAT_YUY2 as int,
    UYVY = ll::SDL_PIXELFORMAT_UYVY as int,
    YVYU = ll::SDL_PIXELFORMAT_YVYU as int
}
<commit_msg>Updated to latest build<commit_after>use std::rand;

pub mod ll {
    use std::libc::{c_int, uint8_t, uint32_t};

    //SDL_pixels.h
    pub struct SDL_Color {
        r: uint8_t,
        g: uint8_t,
        b: uint8_t,
        a: uint8_t,
    }

    pub struct SDL_Palette {
        ncolors: c_int,
        colors: *SDL_Color,
        version: uint32_t,
        refcount: c_int
    }

    pub struct SDL_PixelFormat {
        format: SDL_PixelFormatFlag,
        palette: *SDL_Palette,
        BitsPerPixel: uint8_t,
        BytesPerPixel: uint8_t,
        padding: [uint8_t, ..2],
        Rmask: uint8_t,
        Gmask: uint8_t,
        Bmask: uint8_t,
        Amask: uint8_t,
        Rloss: uint8_t,
        Gloss: uint8_t,
        Bloss: uint8_t,
        Aloss: uint8_t,
        Rshift: uint8_t,
        Gshift: uint8_t,
        Bshift: uint8_t,
        Ashift: uint8_t,
        refcount: c_int,
        next: *SDL_PixelFormat
    }

    pub type SDL_PixelFormatFlag = uint32_t;
    pub static SDL_PIXELFORMAT_UNKNOWN: SDL_PixelFormatFlag = 0x0;
    pub static SDL_PIXELFORMAT_INDEX1LSB: SDL_PixelFormatFlag = 0x11100100;
    pub static SDL_PIXELFORMAT_INDEX1MSB: SDL_PixelFormatFlag = 0x11200100;
    pub static SDL_PIXELFORMAT_INDEX4LSB: SDL_PixelFormatFlag = 0x12100400;
    pub static SDL_PIXELFORMAT_INDEX4MSB: SDL_PixelFormatFlag = 0x12200400;
    pub static SDL_PIXELFORMAT_INDEX8: SDL_PixelFormatFlag = 0x13000801;
    pub static SDL_PIXELFORMAT_RGB332: SDL_PixelFormatFlag = 0x14110801;
    pub static SDL_PIXELFORMAT_RGB444: SDL_PixelFormatFlag = 0x15120c02;
    pub static SDL_PIXELFORMAT_RGB555: SDL_PixelFormatFlag = 0x15130f02;
    pub static SDL_PIXELFORMAT_BGR555: SDL_PixelFormatFlag = 0x15530f02;
    pub static SDL_PIXELFORMAT_ARGB4444: SDL_PixelFormatFlag = 0x15321002;
    pub static SDL_PIXELFORMAT_RGBA4444: SDL_PixelFormatFlag = 0x15421002;
    pub static SDL_PIXELFORMAT_ABGR4444: SDL_PixelFormatFlag = 0x15721002;
    pub static SDL_PIXELFORMAT_BGRA4444: SDL_PixelFormatFlag = 0x15821002;
    pub static SDL_PIXELFORMAT_ARGB1555: SDL_PixelFormatFlag = 0x15331002;
    pub static SDL_PIXELFORMAT_RGBA5551: SDL_PixelFormatFlag = 0x15441002;
    pub static SDL_PIXELFORMAT_ABGR1555: SDL_PixelFormatFlag = 0x15731002;
    pub static SDL_PIXELFORMAT_BGRA5551: SDL_PixelFormatFlag = 0x15841002;
    pub static SDL_PIXELFORMAT_RGB565: SDL_PixelFormatFlag = 0x15151002;
    pub static SDL_PIXELFORMAT_BGR565: SDL_PixelFormatFlag = 0x15551002;
    pub static SDL_PIXELFORMAT_RGB24: SDL_PixelFormatFlag = 0x17101803;
    pub static SDL_PIXELFORMAT_BGR24: SDL_PixelFormatFlag = 0x17401803;
    pub static SDL_PIXELFORMAT_RGB888: SDL_PixelFormatFlag = 0x16161804;
    pub static SDL_PIXELFORMAT_RGBX8888: SDL_PixelFormatFlag = 0x16261804;
    pub static SDL_PIXELFORMAT_BGR888: SDL_PixelFormatFlag = 0x16561804;
    pub static SDL_PIXELFORMAT_BGRX8888: SDL_PixelFormatFlag = 0x16661804;
    pub static SDL_PIXELFORMAT_ARGB8888: SDL_PixelFormatFlag = 0x16362004;
    pub static SDL_PIXELFORMAT_RGBA8888: SDL_PixelFormatFlag = 0x16462004;
    pub static SDL_PIXELFORMAT_ABGR8888: SDL_PixelFormatFlag = 0x16762004;
    pub static SDL_PIXELFORMAT_BGRA8888: SDL_PixelFormatFlag = 0x16862004;
    pub static SDL_PIXELFORMAT_ARGB2101010: SDL_PixelFormatFlag = 0x16372004;
    pub static SDL_PIXELFORMAT_YV12: SDL_PixelFormatFlag = 0x32315659;
    pub static SDL_PIXELFORMAT_IYUV: SDL_PixelFormatFlag = 0x56555949;
    pub static SDL_PIXELFORMAT_YUY2: SDL_PixelFormatFlag = 0x32595559;
    pub static SDL_PIXELFORMAT_UYVY: SDL_PixelFormatFlag = 0x59565955;
    pub static SDL_PIXELFORMAT_YVYU: SDL_PixelFormatFlag = 0x55595659;
}
#[deriving(Eq)]
pub struct Palette {
    raw: *ll::SDL_Palette
}

#[deriving(Eq)]
pub enum Color {
    RGB(u8, u8, u8),
    RGBA(u8, u8, u8, u8)
}

impl rand::Rand for Color {
    fn rand<R: rand::Rng>(rng: &mut R) -> Color {
        if rng.gen() { RGBA(rng.gen(), rng.gen(), rng.gen(), rng.gen()) }
        else { RGB(rng.gen(), rng.gen(), rng.gen()) }
    }
}

#[deriving(Eq)]
pub enum PixelFormatFlag {
    Unknown = ll::SDL_PIXELFORMAT_UNKNOWN as int,
    Index1LSB = ll::SDL_PIXELFORMAT_INDEX1LSB as int,
    Index1MSB = ll::SDL_PIXELFORMAT_INDEX1MSB as int,
    Index4LSB = ll::SDL_PIXELFORMAT_INDEX4LSB as int,
    Index4MSB = ll::SDL_PIXELFORMAT_INDEX4MSB as int,
    Index8 = ll::SDL_PIXELFORMAT_INDEX8 as int,
    RGB332 = ll::SDL_PIXELFORMAT_RGB332 as int,
    RGB444 = ll::SDL_PIXELFORMAT_RGB444 as int,
    RGB555 = ll::SDL_PIXELFORMAT_RGB555 as int,
    BGR555 = ll::SDL_PIXELFORMAT_BGR555 as int,
    ARGB4444 = ll::SDL_PIXELFORMAT_ARGB4444 as int,
    RGBA4444 = ll::SDL_PIXELFORMAT_RGBA4444 as int,
    ABGR4444 = ll::SDL_PIXELFORMAT_ABGR4444 as int,
    BGRA4444 = ll::SDL_PIXELFORMAT_BGRA4444 as int,
    ARGB1555 = ll::SDL_PIXELFORMAT_ARGB1555 as int,
    RGBA5551 = ll::SDL_PIXELFORMAT_RGBA5551 as int,
    ABGR1555 = ll::SDL_PIXELFORMAT_ABGR1555 as int,
    BGRA5551 = ll::SDL_PIXELFORMAT_BGRA5551 as int,
    RGB565 = ll::SDL_PIXELFORMAT_RGB565 as int,
    BGR565 = ll::SDL_PIXELFORMAT_BGR565 as int,
    RGB24 = ll::SDL_PIXELFORMAT_RGB24 as int,
    BGR24 = ll::SDL_PIXELFORMAT_BGR24 as int,
    RGB888 = ll::SDL_PIXELFORMAT_RGB888 as int,
    RGBX8888 = ll::SDL_PIXELFORMAT_RGBX8888 as int,
    BGR888 = ll::SDL_PIXELFORMAT_BGR888 as int,
    BGRX8888 = ll::SDL_PIXELFORMAT_BGRX8888 as int,
    ARGB8888 = ll::SDL_PIXELFORMAT_ARGB8888 as int,
    RGBA8888 = ll::SDL_PIXELFORMAT_RGBA8888 as int,
    ABGR8888 = ll::SDL_PIXELFORMAT_ABGR8888 as int,
    BGRA8888 = ll::SDL_PIXELFORMAT_BGRA8888 as int,
    ARGB2101010 = ll::SDL_PIXELFORMAT_ARGB2101010 as int,
    YV12 = ll::SDL_PIXELFORMAT_YV12 as int,
    IYUV = ll::SDL_PIXELFORMAT_IYUV as int,
    YUY2 = ll::SDL_PIXELFORMAT_YUY2 as int,
    UYVY = ll::SDL_PIXELFORMAT_UYVY as int,
    YVYU = ll::SDL_PIXELFORMAT_YVYU as int
}
<|endoftext|>