mod stream;
#[cfg(test)]
mod tests;
pub use self::stream::BitOffsets;
pub use self::stream::Bits;
use crate::combinator::trace;
use crate::error::{ErrorConvert, Needed, ParserError};
use crate::stream::{Stream, StreamIsPartial, ToUsize};
use crate::{Parser, Result};
use core::ops::{AddAssign, Div, Shl, Shr};
const BYTE: usize = u8::BITS as usize;
pub fn bits<Input, Output, BitError, ByteError, ParseNext>(
mut parser: ParseNext,
) -> impl Parser<Input, Output, ByteError>
where
BitError: ParserError<Bits<Input>> + ErrorConvert<ByteError>,
ByteError: ParserError<Input>,
Bits<Input>: Stream,
Input: Stream + Clone,
ParseNext: Parser<Bits<Input>, Output, BitError>,
{
trace("bits", move |input: &mut Input| {
let mut bit_input = Bits(input.clone(), 0);
match parser.parse_next(&mut bit_input) {
Ok(result) => {
let Bits(mut rest, offset) = bit_input;
let remaining_bytes_index = offset / BYTE + if offset % BYTE == 0 { 0 } else { 1 };
let _ = rest.next_slice(remaining_bytes_index);
*input = rest;
Ok(result)
}
Err(e) => match e.needed() {
Some(n) => Err(ParserError::incomplete(
input,
n.map(|u| u.get() / BYTE + 1),
)),
None => Err(ErrorConvert::convert(e)),
},
}
})
}
pub fn bytes<Input, Output, ByteError, BitError, ParseNext>(
mut parser: ParseNext,
) -> impl Parser<Bits<Input>, Output, BitError>
where
ByteError: ParserError<Input> + ErrorConvert<BitError>,
BitError: ParserError<Bits<Input>>,
Input: Stream<Token = u8> + Clone,
ParseNext: Parser<Input, Output, ByteError>,
{
trace("bytes", move |bit_input: &mut Bits<Input>| {
let Bits(mut input, offset) = bit_input.clone();
let _ = if offset % BYTE != 0 {
input.next_slice(1 + offset / BYTE)
} else {
input.next_slice(offset / BYTE)
};
match parser.parse_next(&mut input) {
Ok(res) => {
*bit_input = Bits(input, 0);
Ok(res)
}
Err(e) => match e.needed() {
Some(Needed::Unknown) => Err(ParserError::incomplete(bit_input, Needed::Unknown)),
Some(Needed::Size(sz)) => Err(match sz.get().checked_mul(BYTE) {
Some(v) => ParserError::incomplete(bit_input, Needed::new(v)),
None => ParserError::assert(
bit_input,
"overflow in turning needed bytes into needed bits",
),
}),
None => Err(ErrorConvert::convert(e)),
},
}
})
}
#[inline(always)]
pub fn take<Input, Output, Count, Error>(count: Count) -> impl Parser<Bits<Input>, Output, Error>
where
Input: Stream<Token = u8> + StreamIsPartial + Clone,
Output: From<u8> + AddAssign + Shl<usize, Output = Output> + Shr<usize, Output = Output>,
Count: ToUsize,
Error: ParserError<Bits<Input>>,
{
let count = count.to_usize();
trace("take", move |input: &mut Bits<Input>| {
if <Input as StreamIsPartial>::is_partial_supported() {
take_::<_, _, _, true>(input, count)
} else {
take_::<_, _, _, false>(input, count)
}
})
}
fn take_<I, O, E: ParserError<Bits<I>>, const PARTIAL: bool>(
bit_input: &mut Bits<I>,
count: usize,
) -> Result<O, E>
where
I: StreamIsPartial,
I: Stream<Token = u8> + Clone,
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
{
if count == 0 {
Ok(0u8.into())
} else {
let Bits(mut input, bit_offset) = bit_input.clone();
if input.eof_offset() * BYTE < count + bit_offset {
if PARTIAL && input.is_partial() {
Err(ParserError::incomplete(bit_input, Needed::new(count)))
} else {
Err(ParserError::from_input(&Bits(input, bit_offset)))
}
} else {
let cnt = (count + bit_offset).div(BYTE);
let mut acc: O = 0_u8.into();
let mut offset: usize = bit_offset;
let mut remaining: usize = count;
let mut end_offset: usize = 0;
for (_, byte) in input.iter_offsets().take(cnt + 1) {
if remaining == 0 {
break;
}
let val: O = if offset == 0 {
byte.into()
} else {
(byte << offset >> offset).into()
};
if remaining < BYTE - offset {
acc += val >> (BYTE - offset - remaining);
end_offset = remaining + offset;
break;
} else {
acc += val << (remaining - (BYTE - offset));
remaining -= BYTE - offset;
offset = 0;
}
}
let _ = input.next_slice(cnt);
*bit_input = Bits(input, end_offset);
Ok(acc)
}
}
}
#[inline(always)]
#[doc(alias = "literal")]
#[doc(alias = "just")]
#[doc(alias = "tag")]
pub fn pattern<Input, Output, Count, Error: ParserError<Bits<Input>>>(
pattern: Output,
count: Count,
) -> impl Parser<Bits<Input>, Output, Error>
where
Input: Stream<Token = u8> + StreamIsPartial + Clone,
Count: ToUsize,
Output: From<u8>
+ AddAssign
+ Shl<usize, Output = Output>
+ Shr<usize, Output = Output>
+ PartialEq,
{
let count = count.to_usize();
trace("pattern", move |input: &mut Bits<Input>| {
let start = input.checkpoint();
take(count).parse_next(input).and_then(|o| {
if pattern == o {
Ok(o)
} else {
input.reset(&start);
Err(ParserError::from_input(input))
}
})
})
}
#[doc(alias = "any")]
pub fn bool<Input, Error: ParserError<Bits<Input>>>(input: &mut Bits<Input>) -> Result<bool, Error>
where
Input: Stream<Token = u8> + StreamIsPartial + Clone,
{
trace("bool", |input: &mut Bits<Input>| {
let bit: u32 = take(1usize).parse_next(input)?;
Ok(bit != 0)
})
.parse_next(input)
}