mirror of
https://github.com/zaphar/abortable_parser.git
synced 2025-07-21 20:29:49 -04:00
FEATURE: must_string Result mapper and until! matcher.
This commit is contained in:
parent
40c89a5cb3
commit
29b5d71bb1
@ -27,3 +27,52 @@ macro_rules! text_token {
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! until {
|
||||
($i:expr, $term:ident!( $( $args:tt )* ) ) => {{
|
||||
use $crate::{Result, Offsetable};
|
||||
let mut acc = Vec::new();
|
||||
let mut _i = $i.clone();
|
||||
let pfn = || {
|
||||
loop {
|
||||
match $term!(_i.clone(), $($args)*) {
|
||||
Result::Complete(_, _) => return Result::Complete(_i, acc),
|
||||
Result::Abort(e) => return Result::Abort(e),
|
||||
Result::Incomplete(offset) => return Result::Incomplete(offset),
|
||||
Result::Fail(_) => {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
let item = match _i.next() {
|
||||
Some(it) => it,
|
||||
None => return Result::Incomplete(_i.get_offset()),
|
||||
};
|
||||
acc.push(item);
|
||||
}
|
||||
};
|
||||
pfn()
|
||||
}};
|
||||
|
||||
($i:expr, $term:ident) => {
|
||||
consume_until!($i, run!($term))
|
||||
};
|
||||
}
|
||||
|
||||
pub fn must_string<'a, I, E>(matched: Result<I, Vec<&'a u8>, E>, msg: E) -> Result<I, String, E>
|
||||
where
|
||||
I: InputIter<Item=&'a u8>,
|
||||
E: Debug + Display,
|
||||
{
|
||||
match matched {
|
||||
Result::Complete(i, mut o) => {
|
||||
let new_string = String::from_utf8(o.drain(0..).map(|b| *b).collect());
|
||||
match new_string {
|
||||
Ok(s) => Result::Complete(i, s),
|
||||
Err(_) => Result::Abort(Error::new(msg, &i)),
|
||||
}
|
||||
},
|
||||
Result::Incomplete(offset) => Result::Incomplete(offset),
|
||||
Result::Abort(e) => Result::Abort(e),
|
||||
Result::Fail(e) => Result::Fail(e),
|
||||
}
|
||||
}
|
30
src/test.rs
30
src/test.rs
@ -2,6 +2,7 @@ use std::fmt::{Debug, Display};
|
||||
|
||||
use super::{InputIter, Offsetable, Result};
|
||||
use iter::SliceIter;
|
||||
use matchers::must_string;
|
||||
|
||||
#[test]
|
||||
fn test_slice_iter() {
|
||||
@ -349,3 +350,32 @@ fn test_repeat_abort() {
|
||||
let result = repeat!(iter, must!(will_fail));
|
||||
assert!(result.is_abort());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_until() {
|
||||
let input_str = "foo; ";
|
||||
let iter = SliceIter::new(input_str.as_bytes());
|
||||
let result = must_string(until!(iter, text_token!("; ")), "AAAHHH!".to_string());
|
||||
assert!(result.is_complete());
|
||||
if let Result::Complete(i, o) = result {
|
||||
assert_eq!(i.get_offset(), 3);
|
||||
assert_eq!(o.len(), 3);
|
||||
assert_eq!(&o, "foo");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_until_abort() {
|
||||
let input_str = "foo ";
|
||||
let iter = SliceIter::new(input_str.as_bytes());
|
||||
let result = until!(iter, must!(will_fail));
|
||||
assert!(result.is_abort());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_until_incomplete() {
|
||||
let input_str = "foo;";
|
||||
let iter = SliceIter::new(input_str.as_bytes());
|
||||
let result = until!(iter, text_token!("; "));
|
||||
assert!(result.is_incomplete());
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user