use core::num::NonZeroUsize; use crate::error::Needed; #[cfg(feature = "unstable-recover")] #[cfg(feature = "std")] use crate::stream::Recover; use crate::stream::{Checkpoint, Offset, Stream, StreamIsPartial}; /// Bit-level stream state over a byte stream. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Bits(pub I, pub usize); impl Stream for Bits where I: Stream + Clone, { type Token = bool; type Slice = (I::Slice, usize, usize); type IterOffsets = BitOffsets; type Checkpoint = Checkpoint, Self>; #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { BitOffsets { i: self.clone(), o: 0, } } #[inline(always)] fn eof_offset(&self) -> usize { let offset = self.0.eof_offset() * 8; if offset == 0 { 0 } else { offset - self.1 } } #[inline(always)] fn next_token(&mut self) -> Option { next_bit(self) } #[inline(always)] fn peek_token(&self) -> Option { peek_bit(self) } #[inline(always)] fn offset_for

(&self, predicate: P) -> Option where P: Fn(Self::Token) -> bool, { self.iter_offsets() .find_map(|(o, b)| predicate(b).then_some(o)) } #[inline(always)] fn offset_at(&self, tokens: usize) -> Result { if let Some(needed) = tokens .checked_sub(self.eof_offset()) .and_then(NonZeroUsize::new) { Err(Needed::Size(needed)) } else { Ok(tokens) } } #[inline(always)] fn next_slice(&mut self, offset: usize) -> Self::Slice { let byte_offset = (offset + self.1) / 8; let end_offset = (offset + self.1) % 8; let s = self.0.next_slice(byte_offset); let start_offset = self.1; self.1 = end_offset; (s, start_offset, end_offset) } #[inline(always)] fn peek_slice(&self, offset: usize) -> Self::Slice { let byte_offset = (offset + self.1) / 8; let end_offset = (offset + self.1) % 8; let s = self.0.peek_slice(byte_offset); let start_offset = self.1; (s, start_offset, end_offset) } #[inline(always)] fn checkpoint(&self) -> Self::Checkpoint { Checkpoint::<_, Self>::new(Bits(self.0.checkpoint(), self.1)) } #[inline(always)] fn reset(&mut self, checkpoint: &Self::Checkpoint) { self.0.reset(&checkpoint.inner.0); self.1 = checkpoint.inner.1; } fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{self:#?}") } } /// Iterator for [bit][crate::binary::bits] stream ([`Bits`]) pub struct BitOffsets { i: Bits, o: usize, } impl Iterator for BitOffsets where I: Stream + Clone, { type Item = (usize, bool); fn next(&mut self) -> Option { let b = next_bit(&mut self.i)?; let o = self.o; self.o += 1; Some((o, b)) } } fn next_bit(i: &mut Bits) -> Option where I: Stream + Clone, { if i.eof_offset() == 0 { return None; } let offset = i.1; let mut next_i = i.0.clone(); let byte = next_i.next_token()?; let bit = (byte >> offset) & 0x1 == 0x1; let next_offset = offset + 1; if next_offset == 8 { i.0 = next_i; i.1 = 0; } else { i.1 = next_offset; } Some(bit) } fn peek_bit(i: &Bits) -> Option where I: Stream + Clone, { if i.eof_offset() == 0 { return None; } let offset = i.1; let mut next_i = i.0.clone(); let byte = next_i.next_token()?; Some((byte >> offset) & 0x1 == 0x1) } #[cfg(feature = "unstable-recover")] #[cfg(feature = "std")] impl Recover for Bits where I: Recover, I: Stream + Clone, { #[inline(always)] fn record_err( &mut self, _token_start: &Self::Checkpoint, _err_start: &Self::Checkpoint, err: E, ) -> Result<(), E> { Err(err) } #[inline(always)] fn is_recovery_supported() -> bool { false } } impl StreamIsPartial for Bits where I: StreamIsPartial, { type PartialState = I::PartialState; #[inline] fn complete(&mut self) -> Self::PartialState { self.0.complete() } #[inline] fn restore_partial(&mut self, state: Self::PartialState) { self.0.restore_partial(state); } #[inline(always)] fn is_partial_supported() -> bool { I::is_partial_supported() } #[inline(always)] fn is_partial(&self) -> bool { self.0.is_partial() } } impl Offset for Bits where I: Offset, { #[inline(always)] fn offset_from(&self, start: &Self) -> usize { self.0.offset_from(&start.0) * 8 + self.1 - start.1 } } impl Offset< as Stream>::Checkpoint> for Bits where I: Stream + Clone, { #[inline(always)] fn offset_from(&self, other: & as Stream>::Checkpoint) -> usize { self.checkpoint().offset_from(other) } } impl crate::error::ErrorConvert>> for crate::error::InputError { #[inline] fn convert(self) -> crate::error::InputError> { self.map_input(|i| Bits(i, 0)) } } impl crate::error::ErrorConvert> for crate::error::InputError> { #[inline] fn convert(self) -> crate::error::InputError { self.map_input(|Bits(i, _o)| i) } }