use std::cmp::min;
pub struct ByteReader<'a> {
bytes: &'a [u8],
offset: usize,
}
impl<'a> Iterator for ByteReader<'a> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
if self.offset >= self.bytes.len() {
return None;
}
let byte = self.bytes[self.offset];
self.offset += 1;
Some(byte)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.bytes.len() - self.offset;
(remaining, Some(remaining))
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.offset += n;
self.next()
}
}
impl<'a> ByteReader<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
Self { bytes, offset: 0 }
}
fn _is_end(&self) -> bool {
self.offset >= self.bytes.len()
}
pub fn offset(&mut self, offset: usize) {
self.offset += offset;
}
fn read_bytes(&mut self, size: usize) -> &'a [u8] {
let start = self.offset;
let max_size = self.bytes.len() - start;
let end = self.offset + min(max_size, size);
self.offset = end;
&self.bytes[start..end]
}
pub fn read_int(&mut self, size: usize, le: bool) -> i64 {
let bytes = self.read_bytes(size);
if le {
bytes
.iter()
.fold(0, |acc, &x| acc | (x as i64) << (size - 1) * 8)
} else {
bytes
.iter()
.rev()
.fold(0, |acc, &x| acc | (x as i64) << (size - 1) * 8)
}
}
pub fn read_int16(&mut self, le: bool) -> i16 {
let bytes = self.read_bytes(2);
if le {
i16::from_le_bytes(bytes.try_into().unwrap())
} else {
i16::from_be_bytes(bytes.try_into().unwrap())
}
}
pub fn read_int8(&mut self, le: bool) -> i8 {
let bytes = self.read_bytes(1);
if le {
i8::from_le_bytes(bytes.try_into().unwrap())
} else {
i8::from_be_bytes(bytes.try_into().unwrap())
}
}
pub fn read_int32(&mut self, le: bool) -> i32 {
let bytes = self.read_bytes(4);
if le {
i32::from_le_bytes(bytes.try_into().unwrap())
} else {
i32::from_be_bytes(bytes.try_into().unwrap())
}
}
pub fn read_int64(&mut self, le: bool) -> i64 {
let bytes = self.read_bytes(8);
if le {
i64::from_le_bytes(bytes.try_into().unwrap())
} else {
i64::from_be_bytes(bytes.try_into().unwrap())
}
}
pub fn read_hex_int(&mut self, size: usize, le: bool) -> String {
let bytes = self.read_bytes(size);
if le {
bytes
.iter()
.rev()
.map(|x| format!("{:02X}", x))
.collect::<String>()
} else {
bytes
.iter()
.map(|x| format!("{:02X}", x))
.collect::<String>()
}
}
pub fn read_float32(&mut self, le: bool) -> f32 {
let bytes = self.read_bytes(4);
if le {
f32::from_le_bytes(bytes.try_into().unwrap())
} else {
f32::from_be_bytes(bytes.try_into().unwrap())
}
}
pub fn read_float64(&mut self, le: bool) -> f64 {
let bytes = self.read_bytes(8);
if le {
f64::from_le_bytes(bytes.try_into().unwrap())
} else {
f64::from_be_bytes(bytes.try_into().unwrap())
}
}
pub fn read_utf8(&mut self) -> String {
let mut bytes: Vec<u8> = Vec::new();
while let Some(byte) = self.next() {
if byte == 0 {
break;
}
bytes.push(byte);
}
String::from_utf8(bytes).unwrap()
}
}