Skip to content

Commit

Permalink
Merge pull request #779 from khernyo/issue-768-bitvec-parser
Browse files Browse the repository at this point in the history
Fixes #768: Generalize bits.rs to handle inputs other than &[u8]
  • Loading branch information
Geal committed Mar 4, 2019
2 parents c543bc1 + ed91507 commit 0761cca
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 15 deletions.
45 changes: 30 additions & 15 deletions src/bits.rs
Expand Up @@ -47,23 +47,24 @@ macro_rules! bits_impl (
{
use $crate::lib::std::result::Result::*;
use $crate::{Context,Err,Needed};
use $crate::Slice;

let input = ($i, 0usize);
match $submac!(input, $($args)*) {
Err(Err::Error(e)) => {
let err = match e {
Context::Code((i,b), kind) => Context::Code(&i[b/8..], kind),
Context::Code((i,b), kind) => Context::Code(i.slice(b/8..), kind),
Context::List(mut v) => {
Context::List(v.drain(..).map(|((i,b), kind)| (&i[b/8..], kind)).collect())
Context::List(v.drain(..).map(|((i,b), kind)| (i.slice(b/8..), kind)).collect())
}
};
Err(Err::Error(err))
},
Err(Err::Failure(e)) => {
let err = match e {
Context::Code((i,b), kind) => Context::Code(&i[b/8..], kind),
Context::Code((i,b), kind) => Context::Code(i.slice(b/8..), kind),
Context::List(mut v) => {
Context::List(v.drain(..).map(|((i,b), kind)| (&i[b/8..], kind)).collect())
Context::List(v.drain(..).map(|((i,b), kind)| (i.slice(b/8..), kind)).collect())
}
};
Err(Err::Failure(err))
Expand All @@ -76,7 +77,7 @@ macro_rules! bits_impl (
Ok(((i, bit_index), o)) => {
let byte_index = bit_index / 8 + if bit_index % 8 == 0 { 0 } else { 1 } ;
//println!("bit index=={} => byte index=={}", bit_index, byte_index);
Ok((&i[byte_index..], o))
Ok((i.slice(byte_index..), o))
}
}
}
Expand All @@ -92,6 +93,7 @@ macro_rules! bits_impl (
{
use $crate::lib::std::result::Result::*;
use $crate::{Err,Needed,Context};
use $crate::Slice;

let input = ($i, 0usize);
match $submac!(input, $($args)*) {
Expand All @@ -111,7 +113,7 @@ macro_rules! bits_impl (
Ok(((i, bit_index), o)) => {
let byte_index = bit_index / 8 + if bit_index % 8 == 0 { 0 } else { 1 } ;
//println!("bit index=={} => byte index=={}", bit_index, byte_index);
Ok((&i[byte_index..], o))
Ok((i.slice(byte_index..), o))
}
}
}
Expand Down Expand Up @@ -159,14 +161,14 @@ macro_rules! bytes_impl (
($macro_i:expr, $submac:ident!( $($args:tt)* )) => (
{
use $crate::lib::std::result::Result::*;
use $crate::{Err,Needed,Context,ErrorKind};
use $crate::{Err,Needed,Context,Slice,ErrorKind};

let inp;
if $macro_i.1 % 8 != 0 {
inp = & $macro_i.0[1 + $macro_i.1 / 8 ..];
inp = $macro_i.0.slice(1 + $macro_i.1 / 8 ..);
}
else {
inp = & $macro_i.0[$macro_i.1 / 8 ..];
inp = $macro_i.0.slice($macro_i.1 / 8 ..);
}

let sub = $submac!(inp, $($args)*);
Expand Down Expand Up @@ -221,14 +223,14 @@ macro_rules! bytes_impl (
($macro_i:expr, $submac:ident!( $($args:tt)* )) => (
{
use $crate::lib::std::result::Result::*;
use $crate::{Err,Needed,Context,ErrorKind};
use $crate::{Err,Needed,Context,Slice,ErrorKind};

let inp;
if $macro_i.1 % 8 != 0 {
inp = & $macro_i.0[1 + $macro_i.1 / 8 ..];
inp = $macro_i.0.slice(1 + $macro_i.1 / 8 ..);
}
else {
inp = & $macro_i.0[$macro_i.1 / 8 ..];
inp = $macro_i.0.slice($macro_i.1 / 8 ..);
}

let sub = $submac!(inp, $($args)*);
Expand Down Expand Up @@ -281,9 +283,10 @@ macro_rules! take_bits (

use $crate::lib::std::ops::Div;
use $crate::lib::std::convert::Into;
use $crate::Slice;
//println!("taking {} bits from {:?}", $count, $i);
let (input, bit_offset) = $i;
let res : IResult<(&[u8],usize), $t> = if $count == 0 {
let res : IResult<_, $t> = if $count == 0 {
Ok(( (input, bit_offset), (0 as u8).into()))
} else {
let cnt = ($count as usize + bit_offset).div(8);
Expand Down Expand Up @@ -316,7 +319,7 @@ macro_rules! take_bits (
offset = 0;
}
}
Ok(( (&input[cnt..], end_offset) , acc))
Ok(( (input.slice(cnt..), end_offset) , acc))
}
};
res
Expand Down Expand Up @@ -354,7 +357,7 @@ macro_rules! tag_bits (
Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
Ok((i, o)) => {
if let $p = o {
let res: IResult<(&[u8],usize),$t> = Ok((i, o));
let res: IResult<_,$t> = Ok((i, o));
res
} else {
let e: $crate::ErrorKind<u32> = $crate::ErrorKind::TagBits;
Expand All @@ -375,6 +378,7 @@ mod tests {
use lib::std::ops::{AddAssign, Shl, Shr};
use internal::{Err, Needed};
use util::ErrorKind;
use types::CompleteByteSlice;

#[test]
fn take_bits() {
Expand All @@ -395,6 +399,7 @@ mod tests {
assert_eq!(take_bits!((sl, 6), u16, 11), Ok(((&sl[2..], 1), 1504)));
assert_eq!(take_bits!((sl, 0), u32, 20), Ok(((&sl[2..], 4), 700_163)));
assert_eq!(take_bits!((sl, 4), u32, 20), Ok(((&sl[3..], 0), 716_851)));
assert_eq!(take_bits!((CompleteByteSlice(sl), 4), u32, 20), Ok(((sl[3..].into(), 0), 716_851)));
assert_eq!(
take_bits!((sl, 4), u32, 22),
Err(Err::Incomplete(Needed::Size(22)))
Expand All @@ -408,6 +413,7 @@ mod tests {

assert_eq!(tag_bits!((sl, 0), u8, 3, 0b101), Ok(((&sl[0..], 3), 5)));
assert_eq!(tag_bits!((sl, 0), u8, 4, 0b1010), Ok(((&sl[0..], 4), 10)));
assert_eq!(tag_bits!((CompleteByteSlice(sl), 0), u8, 4, 0b1010), Ok(((sl[0..].into(), 4), 10)));
}

named!(ch<(&[u8],usize),(u8,u8)>,
Expand Down Expand Up @@ -440,6 +446,15 @@ mod tests {
);
}

named!(bits_bytes_bs, bits!(bytes!(::rest)));
named!(bits_bytes_cbs<CompleteByteSlice, CompleteByteSlice>, bits!(bytes!(::rest)));
#[test]
fn bits_bytes() {
let input = [0b10_10_10_10];
assert_eq!(bits_bytes_bs(&input[..]), Ok((&[][..], &[0b10_10_10_10][..])));
assert_eq!(bits_bytes_cbs(CompleteByteSlice(&input[..])), Ok(([][..].into(), [0b10_10_10_10][..].into())));
}

#[derive(PartialEq, Debug)]
struct FakeUint(u32);

Expand Down
26 changes: 26 additions & 0 deletions tests/issues.rs
Expand Up @@ -280,6 +280,32 @@ named_args!(issue_771(count: usize)<Vec<u32>>,
length_count!(value!(count), call!(nom::be_u32))
);

#[test]
fn issue_768() {
named!(bit_vec8<CompleteByteSlice, Vec<u16>>, bits!(many0!(take_bits!(u16, 8))));
named!(bit_vec4<CompleteByteSlice, Vec<u16>>, bits!(many0!(take_bits!(u16, 4))));
named!(bit_vec3<CompleteByteSlice, Vec<u16>>, bits!(many0!(take_bits!(u16, 3))));
named!(bit_vec11<CompleteByteSlice, Vec<u16>>, bits!(many0!(take_bits!(u16, 11))));

let m: Vec<u8> = vec![70, 97, 106, 121, 86, 66, 105, 98, 86, 106, 101];
assert_eq!(
bit_vec8(CompleteByteSlice(m.as_slice())),
Ok((CompleteByteSlice(&[]), vec![70, 97, 106, 121, 86, 66, 105, 98, 86, 106, 101]))
);
assert_eq!(
bit_vec4(CompleteByteSlice(m.as_slice())),
Ok((CompleteByteSlice(&[]), vec![4, 6, 6, 1, 6, 10, 7, 9, 5, 6, 4, 2, 6, 9, 6, 2, 5, 6, 6, 10, 6, 5]))
);
assert_eq!(
bit_vec3(CompleteByteSlice(m.as_slice())),
Ok((CompleteByteSlice(&[]), vec![2, 1, 4, 6, 0, 5, 5, 2, 3, 6, 2, 5, 3, 1, 0, 2, 3, 2, 2, 6, 1, 1, 2, 6, 3, 2, 4, 6, 2]))
);
assert_eq!(
bit_vec11(CompleteByteSlice(m.as_slice())),
Ok((CompleteByteSlice(&[]), vec![563, 90, 1266, 1380, 308, 1417, 717, 613]))
);
}

/// This test is in a separate module to check that all required symbols are imported in
/// `escaped_transform!()`. Without the module, the `use`-es of the current module would
/// mask the error ('"Use of undeclared type or module `Needed`" in escaped_transform!').
Expand Down

0 comments on commit 0761cca

Please sign in to comment.