nom/bits/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
//! Bit level parsers
//!
pub mod complete;
pub mod streaming;
use crate::error::{ErrorKind, ParseError};
use crate::internal::{Err, IResult, Needed, Parser};
use crate::lib::std::ops::RangeFrom;
use crate::traits::{ErrorConvert, Slice};
/// Converts a byte-level input to a bit-level input, for consumption by a parser that uses bits.
///
/// Afterwards, the input is converted back to a byte-level parser, with any remaining bits thrown
/// away.
///
/// # Example
/// ```
/// use nom::bits::{bits, streaming::take};
/// use nom::error::Error;
/// use nom::sequence::tuple;
/// use nom::IResult;
///
/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input)
/// }
///
/// let input = &[0x12, 0x34, 0xff, 0xff];
///
/// let output = parse(input).expect("We take 1.5 bytes and the input is longer than 2 bytes");
///
/// // The first byte is consumed, the second byte is partially consumed and dropped.
/// let remaining = output.0;
/// assert_eq!(remaining, [0xff, 0xff]);
///
/// let parsed = output.1;
/// assert_eq!(parsed.0, 0x01);
/// assert_eq!(parsed.1, 0x23);
/// ```
pub fn bits<I, O, E1, E2, P>(mut parser: P) -> impl FnMut(I) -> IResult<I, O, E2>
where
E1: ParseError<(I, usize)> + ErrorConvert<E2>,
E2: ParseError<I>,
I: Slice<RangeFrom<usize>>,
P: Parser<(I, usize), O, E1>,
{
move |input: I| match parser.parse((input, 0)) {
Ok(((rest, offset), result)) => {
// If the next byte has been partially read, it will be sliced away as well.
// The parser functions might already slice away all fully read bytes.
// That's why `offset / 8` isn't necessarily needed at all times.
let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 };
Ok((rest.slice(remaining_bytes_index..), result))
}
Err(Err::Incomplete(n)) => Err(Err::Incomplete(n.map(|u| u.get() / 8 + 1))),
Err(Err::Error(e)) => Err(Err::Error(e.convert())),
Err(Err::Failure(e)) => Err(Err::Failure(e.convert())),
}
}
/// Counterpart to `bits`, `bytes` transforms its bit stream input into a byte slice for the underlying
/// parser, allowing byte-slice parsers to work on bit streams.
///
/// A partial byte remaining in the input will be ignored and the given parser will start parsing
/// at the next full byte.
///
/// ```
/// use nom::bits::{bits, bytes, streaming::take};
/// use nom::combinator::rest;
/// use nom::error::Error;
/// use nom::sequence::tuple;
/// use nom::IResult;
///
/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8, &[u8])> {
/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((
/// take(4usize),
/// take(8usize),
/// bytes::<_, _, Error<&[u8]>, _, _>(rest)
/// )))(input)
/// }
///
/// let input = &[0x12, 0x34, 0xff, 0xff];
///
/// assert_eq!(parse( input ), Ok(( &[][..], (0x01, 0x23, &[0xff, 0xff][..]) )));
/// ```
pub fn bytes<I, O, E1, E2, P>(mut parser: P) -> impl FnMut((I, usize)) -> IResult<(I, usize), O, E2>
where
E1: ParseError<I> + ErrorConvert<E2>,
E2: ParseError<(I, usize)>,
I: Slice<RangeFrom<usize>> + Clone,
P: Parser<I, O, E1>,
{
move |(input, offset): (I, usize)| {
let inner = if offset % 8 != 0 {
input.slice((1 + offset / 8)..)
} else {
input.slice((offset / 8)..)
};
let i = (input, offset);
match parser.parse(inner) {
Ok((rest, res)) => Ok(((rest, 0), res)),
Err(Err::Incomplete(Needed::Unknown)) => Err(Err::Incomplete(Needed::Unknown)),
Err(Err::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) {
Some(v) => Err::Incomplete(Needed::new(v)),
None => Err::Failure(E2::from_error_kind(i, ErrorKind::TooLarge)),
}),
Err(Err::Error(e)) => Err(Err::Error(e.convert())),
Err(Err::Failure(e)) => Err(Err::Failure(e.convert())),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::bits::streaming::take;
use crate::error::Error;
use crate::sequence::tuple;
#[test]
/// Take the `bits` function and assert that remaining bytes are correctly returned, if the
/// previous bytes are fully consumed
fn test_complete_byte_consumption_bits() {
let input = &[0x12, 0x34, 0x56, 0x78];
// Take 3 bit slices with sizes [4, 8, 4].
let result: IResult<&[u8], (u8, u8, u8)> =
bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize), take(4usize))))(
input,
);
let output = result.expect("We take 2 bytes and the input is longer than 2 bytes");
let remaining = output.0;
assert_eq!(remaining, [0x56, 0x78]);
let parsed = output.1;
assert_eq!(parsed.0, 0x01);
assert_eq!(parsed.1, 0x23);
assert_eq!(parsed.2, 0x04);
}
#[test]
/// Take the `bits` function and assert that remaining bytes are correctly returned, if the
/// previous bytes are NOT fully consumed. Partially consumed bytes are supposed to be dropped.
/// I.e. if we consume 1.5 bytes of 4 bytes, 2 bytes will be returned, bits 13-16 will be
/// dropped.
fn test_partial_byte_consumption_bits() {
let input = &[0x12, 0x34, 0x56, 0x78];
// Take bit slices with sizes [4, 8].
let result: IResult<&[u8], (u8, u8)> =
bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input);
let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes");
let remaining = output.0;
assert_eq!(remaining, [0x56, 0x78]);
let parsed = output.1;
assert_eq!(parsed.0, 0x01);
assert_eq!(parsed.1, 0x23);
}
#[test]
#[cfg(feature = "std")]
/// Ensure that in Incomplete error is thrown, if too few bytes are passed for a given parser.
fn test_incomplete_bits() {
let input = &[0x12];
// Take bit slices with sizes [4, 8].
let result: IResult<&[u8], (u8, u8)> =
bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input);
assert!(result.is_err());
let error = result.err().unwrap();
assert_eq!("Parsing requires 2 bytes/chars", error.to_string());
}
}