mirror of
https://gitee.com/openharmony/third_party_rust_nom
synced 2024-11-23 07:29:54 +00:00
add the length_value macro
This commit is contained in:
parent
03f6ccf971
commit
d01a00bca9
125
src/macros.rs
125
src/macros.rs
@ -669,6 +669,99 @@ macro_rules! take_until_either_and_leave(
|
||||
)
|
||||
);
|
||||
|
||||
/// returns a result without consuming the input
|
||||
///
|
||||
/// the embedded parser may return Incomplete
|
||||
///
|
||||
/// ```ignore
|
||||
/// tag!(x "abcd");
|
||||
/// peek!(ptag<&[u8], &[u8]> x);
|
||||
/// let r = ptag(b"abcdefgh"));
|
||||
/// assert_eq!(r, Done(b"abcdefgh", b"abcd"));
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! length_value(
|
||||
($name:ident<$i:ty,$o:ty> $f:ident $g:ident) => (
|
||||
fn $name(input:$i) -> IResult<$i, Vec<$o>> {
|
||||
match $f(input) {
|
||||
Error(a) => Error(a),
|
||||
Incomplete(i) => Incomplete(i),
|
||||
Done(i1,nb) => {
|
||||
let length_token = input.len() - i1.len();
|
||||
let mut begin = 0;
|
||||
let mut remaining = i1.len();
|
||||
let mut res: Vec<$o> = Vec::new();
|
||||
|
||||
loop {
|
||||
if res.len() == nb as usize {
|
||||
return Done(&i1[begin..], res);
|
||||
}
|
||||
|
||||
match $g(&i1[begin..]) {
|
||||
Done(i2,o2) => {
|
||||
res.push(o2);
|
||||
let parsed = remaining - i2.len();
|
||||
begin += parsed;
|
||||
remaining = i2.len();
|
||||
if begin >= i1.len() {
|
||||
return Incomplete(Needed::Size((length_token + nb as usize * parsed) as u32));
|
||||
}
|
||||
},
|
||||
Error(a) => return Error(a),
|
||||
Incomplete(Needed::Unknown) => {
|
||||
return Incomplete(Needed::Unknown)
|
||||
},
|
||||
Incomplete(Needed::Size(a)) => {
|
||||
return Incomplete(Needed::Size(length_token as u32 + a * nb as u32))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
($name:ident<$i:ty,$o:ty> $f:ident $g:ident $length:expr) => (
|
||||
fn $name(input:$i) -> IResult<$i, Vec<$o>> {
|
||||
match $f(input) {
|
||||
Error(a) => Error(a),
|
||||
Incomplete(i) => Incomplete(i),
|
||||
Done(i1,nb) => {
|
||||
let length_token = input.len() - i1.len();
|
||||
let mut begin = 0;
|
||||
let mut remaining = i1.len();
|
||||
let mut res: Vec<$o> = Vec::new();
|
||||
|
||||
loop {
|
||||
if res.len() == nb as usize {
|
||||
return Done(&i1[begin..], res);
|
||||
}
|
||||
|
||||
match $g(&i1[begin..]) {
|
||||
Done(i2,o2) => {
|
||||
res.push(o2);
|
||||
let parsed = remaining - i2.len();
|
||||
begin += parsed;
|
||||
remaining = i2.len();
|
||||
if begin >= i1.len() {
|
||||
return Incomplete(Needed::Size((length_token + nb as usize * $length) as u32));
|
||||
}
|
||||
},
|
||||
Error(a) => return Error(a),
|
||||
Incomplete(Needed::Unknown) => {
|
||||
return Incomplete(Needed::Unknown)
|
||||
},
|
||||
Incomplete(Needed::Size(a)) => {
|
||||
return Incomplete(Needed::Size(length_token as u32 + $length * nb as u32))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -877,4 +970,36 @@ mod tests {
|
||||
let r3 = x(b"abcefg");
|
||||
assert_eq!(r3, Incomplete(Needed::Size(7)));
|
||||
}
|
||||
|
||||
use nom::{be_u8,be_u16};
|
||||
#[test]
|
||||
fn length_value_test() {
|
||||
length_value!(tst1<&[u8], u16 > be_u8 be_u16);
|
||||
length_value!(tst2<&[u8], u16 > be_u8 be_u16 2);
|
||||
|
||||
let i1 = vec![0, 5, 6];
|
||||
let i2 = vec![1, 5, 6, 3];
|
||||
let i3 = vec![2, 5, 6, 3];
|
||||
let i4 = vec![2, 5, 6, 3, 4, 5, 7];
|
||||
let i5 = vec![3, 5, 6, 3, 4, 5];
|
||||
|
||||
let r1: Vec<u16> = Vec::new();
|
||||
let r2: Vec<u16> = vec![1286];
|
||||
let r4: Vec<u16> = vec![1286, 772];
|
||||
assert_eq!(tst1(&i1), IResult::Done(&i1[1..], r1));
|
||||
assert_eq!(tst1(&i2), IResult::Done(&i2[3..], r2));
|
||||
assert_eq!(tst1(&i3), IResult::Incomplete(Needed::Size(5)));
|
||||
assert_eq!(tst1(&i4), IResult::Done(&i4[5..], r4));
|
||||
assert_eq!(tst1(&i5), IResult::Incomplete(Needed::Size(7)));
|
||||
|
||||
let r6: Vec<u16> = Vec::new();
|
||||
let r7: Vec<u16> = vec![1286];
|
||||
let r9: Vec<u16> = vec![1286, 772];
|
||||
assert_eq!(tst2(&i1), IResult::Done(&i1[1..], r6));
|
||||
assert_eq!(tst2(&i2), IResult::Done(&i2[3..], r7));
|
||||
assert_eq!(tst2(&i3), IResult::Incomplete(Needed::Size(5)));
|
||||
assert_eq!(tst2(&i4), IResult::Done(&i4[5..], r9));
|
||||
assert_eq!(tst1(&i5), IResult::Incomplete(Needed::Size(7)));
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user