use crate::errors::{ParseError, ParseResult};
use crate::matcher::Match;
use crate::scanner::Scanner;
use crate::visitor::Visitor;
use std::fmt::Debug;
use std::marker::PhantomData;
pub trait Peekable<'a, T> {
fn peek(&self, data: &Scanner<'a, T>) -> ParseResult<PeekResult>;
}
#[derive(Debug, PartialEq)]
pub struct Peeking<'a, T> {
pub start_element_size: usize,
pub end_element_size: usize,
pub end_slice: usize,
pub data: &'a [T],
}
impl<'a, T> Peeking<'a, T> {
pub fn peeked_slice(&self) -> &'a [T] {
&self.data[self.start_element_size..self.end_slice - self.end_element_size]
}
}
#[derive(PartialEq, Debug)]
pub enum PeekResult {
Found {
end_slice: usize,
start_element_size: usize,
end_element_size: usize,
},
NotFound,
}
impl<'a, T> From<Option<Peeking<'a, T>>> for PeekResult {
fn from(peeking: Option<Peeking<'a, T>>) -> PeekResult {
match peeking {
None => PeekResult::NotFound,
Some(peeking) => PeekResult::Found {
end_slice: peeking.end_slice,
start_element_size: peeking.start_element_size,
end_element_size: peeking.end_element_size,
},
}
}
}
pub trait PeekSize<T> {
fn peek_size(&self) -> usize {
0
}
}
impl<T, M: Match<T>> PeekSize<T> for M {
fn peek_size(&self) -> usize {
self.size()
}
}
pub struct DefaultPeekableImplementation;
pub struct CustomizedPeekableImplementation;
pub trait PeekableImplementation {
type Type;
}
pub fn peek<'a, T, P: Peekable<'a, T>>(
peekable: P,
scanner: &Scanner<'a, T>,
) -> ParseResult<Option<Peeking<'a, T>>> {
let source_cursor = scanner.current_position();
match peekable.peek(scanner)? {
PeekResult::Found {
end_slice,
start_element_size: start,
end_element_size: end,
} => {
let data = &scanner.data()[source_cursor..source_cursor + end_slice];
Ok(Some(Peeking {
start_element_size: start,
end_element_size: end,
end_slice,
data,
}))
}
PeekResult::NotFound => Ok(None),
}
}
impl<'a, T, V> Peekable<'a, T> for V
where
V: Visitor<'a, T> + PeekSize<T> + PeekableImplementation<Type = DefaultPeekableImplementation>,
{
fn peek(&self, data: &Scanner<'a, T>) -> ParseResult<PeekResult> {
let mut scanner = Scanner::new(data.remaining());
while !scanner.is_empty() {
match V::accept(&mut scanner) {
Ok(element) => {
return Ok(PeekResult::Found {
end_slice: scanner.current_position(),
start_element_size: 0,
end_element_size: element.peek_size(),
});
}
Err(_err) => {
scanner.bump_by(1);
continue;
}
}
}
Ok(PeekResult::NotFound)
}
}
#[derive(Default)]
pub struct UntilEnd<T>(PhantomData<T>);
#[derive(Clone)]
pub struct Last<'a, T, V> {
pub element: V,
_marker: PhantomData<&'a T>,
}
impl<'a, T, V: Peekable<'a, T>> Last<'a, T, V> {
pub fn new(element: V) -> Last<'a, T, V> {
Last {
element,
_marker: PhantomData,
}
}
}
impl<'a, T, V: Peekable<'a, T>> Peekable<'a, T> for Last<'a, T, V> {
fn peek(&self, scanner: &Scanner<'a, T>) -> ParseResult<PeekResult> {
let mut state = PeekResult::NotFound;
let mut inner_scanner = Scanner::new(scanner.remaining());
let mut positions = vec![];
loop {
if inner_scanner.is_empty() {
break;
}
let peeked = self.element.peek(&inner_scanner);
let peeked = match peeked {
Ok(peeked) => peeked,
Err(ParseError::UnexpectedToken) => {
inner_scanner.bump_by(1);
continue;
}
Err(err) => {
return Err(err);
}
};
if let PeekResult::Found { end_slice, .. } = &peeked {
positions.push(*end_slice);
inner_scanner.bump_by(*end_slice);
state = peeked;
} else {
if PeekResult::NotFound == state {
return Ok(PeekResult::NotFound);
}
break;
}
}
if let PeekResult::Found { end_slice, .. } = &mut state {
if positions.is_empty() {
return Ok(PeekResult::NotFound);
}
if positions.len() == 1 {
*end_slice = positions[0];
return Ok(state);
}
let previous_end_slice = &positions[..positions.len() - 1].iter().sum();
*end_slice += previous_end_slice;
}
Ok(state)
}
}
#[cfg(test)]
mod tests {
use crate::bytes::token::Token;
use crate::peek::{peek, Last, UntilEnd};
#[test]
fn test_until() {
let data = b"abc|fdgf";
let mut scanner = crate::scanner::Scanner::new(data);
let peeked = peek(Token::Pipe, &mut scanner)
.expect("failed to parse")
.expect("failed to peek");
assert_eq!(peeked.peeked_slice(), "abc".as_bytes());
}
#[test]
fn test_until_end() {
let data = b"abc|fdgf";
let mut scanner = crate::scanner::Scanner::new(data);
let token = UntilEnd::default();
let peeked = peek(token, &mut scanner)
.expect("failed to parse")
.expect("failed to peek");
assert_eq!(peeked.peeked_slice(), "abc|fdgf".as_bytes());
}
#[test]
fn test_last() {
let data = b"abc|def|ghi|";
let mut scanner = crate::scanner::Scanner::new(data);
let token = Last::new(Token::Pipe);
let peeked = peek(token, &mut scanner)
.expect("failed to parse")
.expect("failed to peek");
assert_eq!(peeked.peeked_slice(), "abc|def|ghi".as_bytes());
let data = b"abc|def|";
let mut scanner = crate::scanner::Scanner::new(data);
let token = Last::new(Token::Pipe);
let peeked = peek(token, &mut scanner)
.expect("failed to parse")
.expect("failed to peek");
assert_eq!(peeked.peeked_slice(), "abc|def".as_bytes());
let data = b"abc|";
let mut scanner = crate::scanner::Scanner::new(data);
let token = Last::new(Token::Pipe);
let peeked = peek(token, &mut scanner)
.expect("failed to parse")
.expect("failed to peek");
assert_eq!(peeked.peeked_slice(), "abc".as_bytes());
let data = b"abc";
let mut scanner = crate::scanner::Scanner::new(data);
let token = Last::new(Token::Pipe);
let peeked = peek(token, &mut scanner).expect("failed to parse");
assert_eq!(peeked, None);
}
}