pub struct Combine7BitChunks<'a> {
bytes: &'a [u8],
offset: usize,
remains: u64,
remains_bits: usize,
}
impl<'a> Combine7BitChunks<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
Self {
bytes,
offset: 0,
remains: 0,
remains_bits: 0,
}
}
}
impl Iterator for Combine7BitChunks<'_> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
while self.offset < self.bytes.len() && self.remains_bits < 8 {
self.remains <<= 7;
self.remains |= (self.bytes[self.offset] >> 1) as u64;
self.remains_bits += 7;
self.offset += 1;
}
if self.remains_bits >= 8 {
let ret = (self.remains >> (self.remains_bits - 8)) as u8;
self.remains_bits -= 8;
Some(ret)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty() {
let mut iter = Combine7BitChunks::new(&[]);
assert_eq!(None, iter.next());
}
#[test]
fn one_byte() {
let mut iter = Combine7BitChunks::new(&[0b00000001, 0b00000000]);
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b00000001, 0b10000000]);
assert_eq!(Some(1), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b00000011, 0b00000000]);
assert_eq!(Some(2), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b00000011, 0b10000000]);
assert_eq!(Some(3), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b00000101, 0b00000000]);
assert_eq!(Some(4), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b11111111, 0b00000000]);
assert_eq!(Some(254), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b11111111, 0b10000000]);
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn two_bytes() {
let mut iter = Combine7BitChunks::new(&[0b00000001, 0b00000001, 0b00000000]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b11111111, 0b11111111, 0b11000000]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn three_bytes() {
let mut iter = Combine7BitChunks::new(&[0b00000001, 0b00000001, 0b00000001, 0b00000000]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[0b11111111, 0b11111111, 0b11111111, 0b11100000]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn four_bytes() {
let mut iter =
Combine7BitChunks::new(&[0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter =
Combine7BitChunks::new(&[0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11110000]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn five_bytes() {
let mut iter = Combine7BitChunks::new(&[
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000,
]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111000,
]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn six_bytes() {
let mut iter = Combine7BitChunks::new(&[
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000,
]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111100,
]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn seven_bytes() {
let mut iter = Combine7BitChunks::new(&[
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000000,
]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111110,
]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn eight_bytes() {
let mut iter = Combine7BitChunks::new(&[
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000001, 0b00000001, 0b00000000,
]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b10000000,
]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn nine_bytes() {
let mut iter = Combine7BitChunks::new(&[
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000001, 0b00000001, 0b00000001, 0b00000000,
]);
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(Some(0), iter.next());
assert_eq!(None, iter.next());
let mut iter = Combine7BitChunks::new(&[
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11000000,
]);
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(Some(255), iter.next());
assert_eq!(None, iter.next());
}
}