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 super::{InputIter, Offsetable, Result};
|
||||||
use iter::SliceIter;
|
use iter::SliceIter;
|
||||||
|
use matchers::must_string;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_iter() {
|
fn test_slice_iter() {
|
||||||
@ -349,3 +350,32 @@ fn test_repeat_abort() {
|
|||||||
let result = repeat!(iter, must!(will_fail));
|
let result = repeat!(iter, must!(will_fail));
|
||||||
assert!(result.is_abort());
|
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