use crate::parsers::helpers::not_found_restore;
use crate::parsers::Quantifier;
use crate::result::{ParserResult, ParserResultError};
use crate::Reader;
#[cfg(feature = "alloc")]
pub fn repeat<'a, P, C, R, Err>(
quantifier: impl Into<Quantifier>,
mut parser: P,
) -> impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<Vec<R>, Err>
where
P: FnMut(&mut Reader<'a, Err, C>) -> ParserResult<R, Err>,
{
let quantifier = quantifier.into();
not_found_restore(move |reader| {
let mut result = Vec::new();
while !quantifier.is_finished(result.len()) {
result.push(match parser(reader) {
Ok(v) => v,
Err(ParserResultError::NotFound) => break,
Err(e) => return Err(e),
});
}
if quantifier.contains(result.len()) {
Ok(result)
} else {
Err(ParserResultError::NotFound)
}
})
}
#[cfg(feature = "alloc")]
pub fn repeat_separated<'a, P, S, C, R, RSep, Err>(
quantifier: impl Into<Quantifier>,
mut parser: P,
mut separator: S,
) -> impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<Vec<R>, Err>
where
P: FnMut(&mut Reader<'a, Err, C>) -> ParserResult<R, Err>,
S: FnMut(&mut Reader<'a, Err, C>) -> ParserResult<RSep, Err>,
{
let quantifier = quantifier.into();
not_found_restore(move |reader| {
let mut result = Vec::new();
while !quantifier.is_finished(result.len()) {
let init_loop_cursor = reader.save_cursor();
if result.len() > 0 {
match separator(reader) {
Ok(_) => {}
Err(ParserResultError::NotFound) => break,
Err(e) => return Err(e),
}
}
result.push(match parser(reader) {
Ok(v) => v,
Err(ParserResultError::NotFound) => {
reader.restore(init_loop_cursor);
break;
}
Err(e) => return Err(e),
});
}
if quantifier.contains(result.len()) {
Ok(result)
} else {
Err(ParserResultError::NotFound)
}
})
}
pub fn repeat_and_count<'a, C, R, Err>(
quantifier: impl Into<Quantifier>,
mut parser: impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<R, Err>,
) -> impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<usize, Err> {
let quantifier = quantifier.into();
not_found_restore(move |reader| {
let mut result = 0;
while !quantifier.is_finished(result) {
match parser(reader) {
Ok(_) => {}
Err(ParserResultError::NotFound) => break,
Err(e) => return Err(e),
}
result += 1;
}
if quantifier.contains(result) {
Ok(result)
} else {
Err(ParserResultError::NotFound)
}
})
}
pub fn repeat_to_fill<'a, C, R, Err>(
buffer: &'a mut [R],
mut parser: impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<R, Err>,
) -> impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<(), Err> {
not_found_restore(move |reader| {
for item in buffer.iter_mut() {
match parser(reader) {
Ok(v) => {
*item = v;
}
Err(e) => return Err(e),
}
}
Ok(())
})
}
pub fn repeat_and_fold<'a, P, F, C, R: Clone, Rp, Err>(
quantifier: impl Into<Quantifier>,
init: R,
fold: F,
mut parser: P,
) -> impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<R, Err>
where
P: FnMut(&mut Reader<'a, Err, C>) -> ParserResult<Rp, Err>,
F: Fn(R, Rp) -> R,
{
let quantifier = quantifier.into();
not_found_restore(move |reader| {
let mut result = init.clone();
let mut iteration = 0;
while !quantifier.is_finished(iteration) {
let res = match parser(reader) {
Ok(v) => v,
Err(ParserResultError::NotFound) => break,
Err(e) => return Err(e),
};
result = fold(result, res);
iteration += 1;
}
if quantifier.contains(iteration) {
Ok(result)
} else {
Err(ParserResultError::NotFound)
}
})
}
#[cfg(feature = "alloc")]
pub fn count_and_repeat<'a, Rep, P, C, R, Err>(
mut repetitions: Rep,
mut parser: P,
) -> impl FnMut(&mut Reader<'a, Err, C>) -> ParserResult<Vec<R>, Err>
where
Rep: FnMut(&mut Reader<'a, Err, C>) -> ParserResult<usize, Err>,
P: FnMut(&mut Reader<'a, Err, C>) -> ParserResult<R, Err>,
{
not_found_restore(move |reader| {
let repetitions = repetitions(reader)?;
let mut result = Vec::with_capacity(repetitions);
for _ in 0..repetitions {
result.push(parser(reader)?);
}
Ok(result)
})
}
#[cfg(test)]
mod test {
use crate::parsers::characters::{ascii_alpha_quantified, read_any};
use super::*;
#[test]
fn test_repeat_and_count() {
let mut reader = Reader::new("Test");
let mut parser = repeat_and_count(1.., ascii_alpha_quantified(1));
let result = parser(&mut reader);
assert_eq!(result, Ok(4));
let result = parser(&mut reader);
assert_eq!(result, Err(ParserResultError::NotFound));
}
#[test]
fn test_repeat_to_fill() {
let mut reader = Reader::new("This is a test");
let mut buffer = [0; 5];
let result = {
let mut parser = repeat_to_fill(&mut buffer, |_| Ok(3));
parser(&mut reader)
};
assert_eq!(result, Ok(()));
assert_eq!(buffer, [3; 5]);
}
#[test]
fn test_repeat_to_fill_not_found() {
let mut reader = Reader::new("This is a test");
let mut buffer = [0; 5];
let result = {
let mut parser = repeat_to_fill(&mut buffer, |_| Err(ParserResultError::NotFound));
parser(&mut reader)
};
assert_eq!(result, Err(ParserResultError::NotFound));
assert_eq!(buffer, [0; 5]);
}
#[test]
fn test_repeat_and_fold() {
let mut reader = Reader::new("This is a test");
let result = {
let mut parser =
repeat_and_fold(..=4, String::new(), |a, b| format!("{}{}", a, b), read_any);
parser(&mut reader)
};
assert_eq!(result, Ok("This".to_string()));
}
}
#[cfg(test)]
#[cfg(feature = "alloc")]
mod test_alloc {
use crate::parsers::characters::{ascii_alpha, read_text};
use crate::parsers::helpers::value;
use super::*;
#[test]
fn test_repeat() {
let mut reader = Reader::new("Test");
let mut parser = repeat(3, ascii_alpha);
let result = parser(&mut reader);
assert_eq!(result, Ok(vec!['T', 'e', 's']));
let result = parser(&mut reader);
assert_eq!(result, Err(ParserResultError::NotFound));
}
#[test]
fn test_repeat_separated() {
let mut reader = Reader::new("T|e|s|t");
let mut parser = repeat_separated(3, ascii_alpha, read_text("|"));
let result = parser(&mut reader);
assert_eq!(result, Ok(vec!['T', 'e', 's']));
assert_eq!(reader.byte_offset(), 5);
let result = parser(&mut reader);
assert_eq!(result, Err(ParserResultError::NotFound));
assert_eq!(reader.byte_offset(), 5);
let mut reader = Reader::new("T|e|");
let mut parser = repeat_separated(.., ascii_alpha, read_text("|"));
let result = parser(&mut reader);
assert_eq!(result, Ok(vec!['T', 'e']));
assert_eq!(reader.byte_offset(), 3);
}
#[test]
fn test_count_and_repeat() {
let mut reader = Reader::new("Test");
let mut parser = count_and_repeat(value(3), ascii_alpha);
let result = parser(&mut reader);
assert_eq!(result, Ok(vec!['T', 'e', 's']));
let result = parser(&mut reader);
assert_eq!(result, Err(ParserResultError::NotFound));
}
}