use std::io;
use std::slice;
pub trait Read7BitEncodedI32Ext {
fn read_7_bit_encoded_i32(&mut self) -> io::Result<i32>;
}
impl<T: io::Read> Read7BitEncodedI32Ext for T {
fn read_7_bit_encoded_i32(&mut self) -> io::Result<i32> {
let mut buf = 0u8;
let mut result = 0u64;
for i in 0..5 {
self.read_exact(slice::from_mut(&mut buf))?;
result |= ((buf & 127) as u64) << (i * 7);
if buf & 128 == 0 {
break;
}
}
if result > u32::MAX as u64 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Input data can't fit into i32",
));
}
Ok(result as u32 as i32)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read_byte_arr::ReadByteArr;
#[test]
fn reading_ints() {
let encoded_7_bit_ints: [u8; 40] = [
0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x08, 0x01, 0xff, 0xff, 0xff,
0xff, 0x07, 0x00, 0x02, 0x05, 0x80, 0xa4, 0xe8, 0x03, 0x80, 0xd0, 0xa5, 0x4c, 0xb0,
0xea, 0x01, 0xe0, 0x99, 0xf2, 0xfe, 0x0f, 0xc0, 0xca, 0xfe, 0xff, 0x0f,
];
let mut reader = ReadByteArr::new(&encoded_7_bit_ints);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -1);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -2147483648);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 1);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 2147483647);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 0);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 2);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 5);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 8000000);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 160000000);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 30000);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -2323232);
assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -23232);
}
#[test]
fn too_short() {
let encoded_7_bit_int: [u8; 1] = [0xFF];
let mut reader = ReadByteArr::new(&encoded_7_bit_int);
assert_eq!(
reader.read_7_bit_encoded_i32().map_err(|e| e.kind()),
Err(io::ErrorKind::UnexpectedEof)
);
}
#[test]
fn invalid_data() {
let encoded_7_bit_int: [u8; 5] = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let mut reader = ReadByteArr::new(&encoded_7_bit_int);
assert_eq!(
reader.read_7_bit_encoded_i32().map_err(|e| e.kind()),
Err(io::ErrorKind::InvalidData)
);
}
}