#![cfg_attr(docsrs, feature(doc_cfg))]
pub mod position;
mod parse_iterator;
mod expect_byte;
pub mod ignore_byte;
pub mod while_byte_fn;
pub mod split_on_byte;
pub mod recorder;
pub mod stop;
pub mod pit;
#[cfg(feature = "unstable-parse-iter")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-parse-iter")))]
pub mod parse_iter;
pub use parse_iterator::ParseIterator;
pub use expect_byte::ExpectByte;
use recorder::Recorder;
use position::Position;
use pit::ParserPointInTime;
#[derive(Debug)]
pub struct Parser<'s> {
slice: &'s [u8],
pit: ParserPointInTime
}
impl<'s> Parser<'s> {
pub fn new(slice: &'s [u8]) -> Self {
Self {
slice,
pit: ParserPointInTime {
pos: Position::null()
}
}
}
}
impl<'s> ParseIterator<'s> for Parser<'s> {
type PointInTime = ParserPointInTime;
fn slice(&self) -> &'s [u8] {
self.slice
}
fn pit(&self) -> Self::PointInTime {
self.pit
}
fn restore_pit(&mut self, pit: Self::PointInTime) {
self.pit = pit;
}
fn advance(&mut self) -> Option<()> {
let n = self.pit.pos + 1;
if n < self.slice.len() {
self.pit.pos = n.into();
Some(())
} else {
None
}
}
fn recorder(&self) -> Option<&Recorder> {
None
}
#[inline]
unsafe fn is_valid_utf8() -> bool {
false
}
}
#[derive(Debug)]
pub struct StrParser<'s> {
inner: &'s str,
pit: ParserPointInTime
}
impl<'s> StrParser<'s> {
pub fn new(inner: &'s str) -> Self {
Self {
inner,
pit: ParserPointInTime::new()
}
}
}
impl<'s> ParseIterator<'s> for StrParser<'s> {
type PointInTime = ParserPointInTime;
fn slice(&self) -> &'s [u8] {
self.inner.as_bytes()
}
fn pit(&self) -> Self::PointInTime {
self.pit
}
fn restore_pit(&mut self, pit: Self::PointInTime) {
self.pit = pit;
}
fn advance(&mut self) -> Option<()> {
let n = self.pit.pos + 1;
if n < self.inner.len() {
self.pit.pos = n.into();
Some(())
} else {
None
}
}
fn recorder(&self) -> Option<&Recorder> {
None
}
#[inline]
unsafe fn is_valid_utf8() -> bool {
true
}
}
#[cfg(feature = "unstable-parse-iter")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-parse-iter")))]
pub fn parse_iter<'s, I, F, O>(i: I, f: F) -> parse_iter::ParseIter<I, F>
where
I: ParseIterator<'s>,
F: FnMut(&mut I) -> Option<O> {
parse_iter::ParseIter::new(i, f)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parser_advance() {
let s = b"my byte str";
let mut parser = Parser::new(s);
for b in s.iter() {
assert_eq!(*b, parser.next().unwrap());
}
assert_eq!(None, parser.next());
}
#[test]
fn str_parser_advance() {
let s = "my byte str";
let mut parser = StrParser::new(s);
for b in s.as_bytes().iter() {
assert_eq!(*b, parser.next().unwrap());
}
assert_eq!(None, parser.next());
}
#[test]
fn str_parser_to_str() {
let s = "my byte str";
let mut parser = StrParser::new(s);
parser.consume_len(3).unwrap();
let mut parser = parser.record();
assert_eq!("byte str", parser.consume_to_str());
}
#[test]
fn create_an_iterator() {
fn make_iter(s: &str) -> impl Iterator<Item=&str> {
let mut parser = StrParser::new(s);
std::iter::from_fn(move || {
let mut split = parser.split_on_byte(b' ');
let n = split.next()?; Some(n.record().consume_to_str())
})
}
let mut iter = make_iter("my byte str");
assert_eq!(iter.next().unwrap(), "my");
assert_eq!(iter.next().unwrap(), "byte");
assert_eq!(iter.next().unwrap(), "str");
assert!(iter.next().is_none());
}
#[cfg(feature = "unstable-parse-iter")]
#[test]
fn test_parse_iter() {
let mut iter = parse_iter(
StrParser::new("my str"),
|parser| {
let mut split = parser.split_on_byte(b' ');
split.next()
.map(|n| n.record().consume_to_str())
}
);
assert_eq!(iter.next().unwrap(), "my");
assert_eq!(iter.next().unwrap(), "str");
assert!(iter.next().is_none());
}
}