use core::{
mem::size_of,
ops::{
BitAnd,
Shl,
},
};
use binator_core::{
SplitError,
SplitFirst,
UtilsStream,
};
use num_traits::One;
const fn bits_of<Item>() -> usize {
size_of::<Item>() * u8::BITS as usize
}
#[derive(Clone, PartialEq, Eq)]
pub struct BitStream<Stream: UtilsStream, Item = <Stream as UtilsStream>::Item> {
stream: Stream,
i: usize,
cur: Item,
}
impl<Stream> From<Stream> for BitStream<Stream>
where
Stream: UtilsStream,
<Stream as UtilsStream>::Item: Default,
{
fn from(stream: Stream) -> Self {
Self::new(stream)
}
}
impl<Stream: UtilsStream> BitStream<Stream> {
pub fn new(stream: Stream) -> Self
where
<Stream as UtilsStream>::Item: Default,
{
Self {
stream,
i: bits_of::<<Stream as UtilsStream>::Item>(),
cur: Default::default(),
}
}
fn next(self) -> (bool, Self)
where
for<'a> &'a <Stream as UtilsStream>::Item: BitAnd<Token = <Stream as UtilsStream>::Item>,
<Stream as UtilsStream>::Item: Shl<usize, Token = <Stream as UtilsStream>::Item>,
<Stream as UtilsStream>::Item: PartialEq,
<Stream as UtilsStream>::Item: One,
{
let flag = <Stream as UtilsStream>::Item::one() << self.i;
(
&self.cur & &flag == flag,
Self {
stream: self.stream,
i: self.i + 1,
cur: self.cur,
},
)
}
pub fn into_stream(self) -> Stream {
self.stream
}
}
impl<Stream: UtilsStream> UtilsStream for BitStream<Stream> {
type Error = <Stream as UtilsStream>::Error;
type Item = bool;
}
impl<Stream: SplitFirst> SplitFirst for BitStream<Stream>
where
for<'a> &'a <Stream as UtilsStream>::Item: BitAnd<Token = <Stream as UtilsStream>::Item>,
<Stream as UtilsStream>::Item: Shl<usize, Token = <Stream as UtilsStream>::Item>,
<Stream as UtilsStream>::Item: PartialEq,
<Stream as UtilsStream>::Item: One,
{
fn split_first(self) -> Result<(Self::Item, Self), SplitError<Self, Self::Error>> {
if self.i == bits_of::<<Stream as UtilsStream>::Item>() {
let (cur, stream) = self.stream.split_first().map_err(|e| {
e.map(|stream| {
Self {
stream,
i: self.i,
cur: self.cur,
}
})
})?;
Ok(
Self {
stream,
i: 0,
cur,
}
.next(),
)
} else {
Ok(self.next())
}
}
}