use std::convert::TryInto;
pub struct BinaryWriter {
data: Vec<u8>,
}
impl BinaryWriter {
pub fn new() -> Self {
BinaryWriter { data: Vec::new() }
}
pub fn get_data(&self) -> &Vec<u8> {
&self.data
}
pub fn write_u8(&mut self, value: u8) {
self.data.push(value);
}
pub fn write_u16(&mut self, value: u16) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_u32(&mut self, value: u32) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_u64(&mut self, value: u64) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_i8(&mut self, value: i8) {
self.data.push(value as u8);
}
pub fn write_i16(&mut self, value: i16) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_i32(&mut self, value: i32) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_i64(&mut self, value: i64) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_f32(&mut self, value: f32) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_f64(&mut self, value: f64) {
self.data.extend(&value.to_le_bytes());
}
pub fn write_bool(&mut self, value: bool) {
self.data.push(if value { 1 } else { 0 });
}
pub fn write_string(&mut self, value: &str) {
let bytes = value.as_bytes();
self.write_u32(bytes.len() as u32);
self.data.extend(bytes);
}
pub fn write_vec_u8(&mut self, value: &[u8]) {
self.write_u32(value.len() as u32);
self.data.extend(value);
}
pub fn write_vec_u16(&mut self, value: &[u16]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_u16(v);
}
}
pub fn write_vec_u32(&mut self, value: &[u32]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_u32(v);
}
}
pub fn write_vec_u64(&mut self, value: &[u64]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_u64(v);
}
}
pub fn write_vec_i8(&mut self, value: &[i8]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_i8(v);
}
}
pub fn write_vec_i16(&mut self, value: &[i16]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_i16(v);
}
}
pub fn write_vec_i32(&mut self, value: &[i32]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_i32(v);
}
}
pub fn write_vec_i64(&mut self, value: &[i64]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_i64(v);
}
}
pub fn write_vec_f32(&mut self, value: &[f32]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_f32(v);
}
}
pub fn write_vec_f64(&mut self, value: &[f64]) {
self.write_u32(value.len() as u32);
for &v in value {
self.write_f64(v);
}
}
pub fn write_vec_string(&mut self, value: &[String]) {
self.write_u32(value.len() as u32);
for s in value {
self.write_string(s);
}
}
}
pub struct BinaryReader<'a> {
data: &'a [u8],
cursor: usize,
}
impl<'a> BinaryReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
BinaryReader { data, cursor: 0 }
}
pub fn read_u8(&mut self) -> Result<u8, String> {
self.ensure_available(1)?;
let value = self.data[self.cursor];
self.cursor += 1;
Ok(value)
}
pub fn read_u16(&mut self) -> Result<u16, String> {
self.ensure_available(2)?;
let bytes = &self.data[self.cursor..self.cursor + 2];
self.cursor += 2;
Ok(u16::from_le_bytes(bytes.try_into().unwrap()))
}
pub fn read_u32(&mut self) -> Result<u32, String> {
self.ensure_available(4)?;
let bytes = &self.data[self.cursor..self.cursor + 4];
self.cursor += 4;
Ok(u32::from_le_bytes(bytes.try_into().unwrap()))
}
pub fn read_u64(&mut self) -> Result<u64, String> {
self.ensure_available(8)?;
let bytes = &self.data[self.cursor..self.cursor + 8];
self.cursor += 8;
Ok(u64::from_le_bytes(bytes.try_into().unwrap()))
}
pub fn read_i8(&mut self) -> Result<i8, String> {
self.ensure_available(1)?;
let value = self.data[self.cursor] as i8;
self.cursor += 1;
Ok(value)
}
pub fn read_i16(&mut self) -> Result<i16, String> {
self.read_u16().map(|v| v as i16)
}
pub fn read_i32(&mut self) -> Result<i32, String> {
self.read_u32().map(|v| v as i32)
}
pub fn read_i64(&mut self) -> Result<i64, String> {
self.read_u64().map(|v| v as i64)
}
pub fn read_f32(&mut self) -> Result<f32, String> {
self.ensure_available(4)?;
let bytes = &self.data[self.cursor..self.cursor + 4];
self.cursor += 4;
Ok(f32::from_le_bytes(bytes.try_into().unwrap()))
}
pub fn read_f64(&mut self) -> Result<f64, String> {
self.ensure_available(8)?;
let bytes = &self.data[self.cursor..self.cursor + 8];
self.cursor += 8;
Ok(f64::from_le_bytes(bytes.try_into().unwrap()))
}
pub fn read_bool(&mut self) -> Result<bool, String> {
self.read_u8().map(|v| match v {
0 => false,
1 => true,
_ => panic!("Invalid boolean value: {}", v),
})
}
pub fn read_string(&mut self) -> Result<String, String> {
let length = self.read_u32()? as usize;
self.ensure_available(length)?;
let bytes = &self.data[self.cursor..self.cursor + length];
self.cursor += length;
String::from_utf8(bytes.to_vec()).map_err(|e| e.to_string())
}
pub fn read_vec_u8(&mut self) -> Result<Vec<u8>, String> {
let length = self.read_u32()? as usize;
self.ensure_available(length)?;
let vec = self.data[self.cursor..self.cursor + length].to_vec();
self.cursor += length;
Ok(vec)
}
pub fn read_vec_u16(&mut self) -> Result<Vec<u16>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_u16()?);
}
Ok(vec)
}
pub fn read_vec_u32(&mut self) -> Result<Vec<u32>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_u32()?);
}
Ok(vec)
}
pub fn read_vec_u64(&mut self) -> Result<Vec<u64>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_u64()?);
}
Ok(vec)
}
pub fn read_vec_i8(&mut self) -> Result<Vec<i8>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_i8()?);
}
Ok(vec)
}
pub fn read_vec_i16(&mut self) -> Result<Vec<i16>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_i16()?);
}
Ok(vec)
}
pub fn read_vec_i32(&mut self) -> Result<Vec<i32>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_i32()?);
}
Ok(vec)
}
pub fn read_vec_i64(&mut self) -> Result<Vec<i64>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_i64()?);
}
Ok(vec)
}
pub fn read_vec_f32(&mut self) -> Result<Vec<f32>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_f32()?);
}
Ok(vec)
}
pub fn read_vec_f64(&mut self) -> Result<Vec<f64>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_f64()?);
}
Ok(vec)
}
pub fn read_vec_string(&mut self) -> Result<Vec<String>, String> {
let length = self.read_u32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(self.read_string()?);
}
Ok(vec)
}
fn ensure_available(&self, size: usize) -> Result<(), String> {
if self.cursor + size > self.data.len() {
Err("Unexpected end of data".to_string())
} else {
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_binary_writer_reader() {
let mut writer = BinaryWriter::new();
writer.write_u8(255);
writer.write_i8(-128);
writer.write_u16(65535);
writer.write_i16(-32768);
writer.write_u32(4294967295);
writer.write_i32(-2147483648);
writer.write_u64(18446744073709551615);
writer.write_i64(-9223372036854775808);
writer.write_f32(3.1415927);
writer.write_f64(2.718281828459045);
writer.write_bool(true);
writer.write_string("Hello, World!");
let data = writer.get_data().clone();
let mut reader = BinaryReader::new(&data);
assert_eq!(reader.read_u8().unwrap(), 255);
assert_eq!(reader.read_i8().unwrap(), -128);
assert_eq!(reader.read_u16().unwrap(), 65535);
assert_eq!(reader.read_i16().unwrap(), -32768);
assert_eq!(reader.read_u32().unwrap(), 4294967295);
assert_eq!(reader.read_i32().unwrap(), -2147483648);
assert_eq!(reader.read_u64().unwrap(), 18446744073709551615);
assert_eq!(reader.read_i64().unwrap(), -9223372036854775808);
assert!((reader.read_f32().unwrap() - 3.1415927).abs() < 1e-6);
assert!((reader.read_f64().unwrap() - 2.718281828459045).abs() < 1e-12);
assert_eq!(reader.read_bool().unwrap(), true);
assert_eq!(reader.read_string().unwrap(), "Hello, World!");
}
#[test]
fn test_binary_writer_reader_vectors() {
let mut writer = BinaryWriter::new();
writer.write_vec_u8(&[1, 2, 3, 4, 5]);
writer.write_vec_i16(&[-1, -2, -3]);
writer.write_vec_f64(&[1.1, 2.2, 3.3]);
let data = writer.get_data().clone();
let mut reader = BinaryReader::new(&data);
assert_eq!(reader.read_vec_u8().unwrap(), vec![1, 2, 3, 4, 5]);
assert_eq!(reader.read_vec_i16().unwrap(), vec![-1, -2, -3]);
let read_f64 = reader.read_vec_f64().unwrap();
assert_eq!(read_f64.len(), 3);
assert!((read_f64[0] - 1.1).abs() < 1e-10);
assert!((read_f64[1] - 2.2).abs() < 1e-10);
assert!((read_f64[2] - 3.3).abs() < 1e-10);
}
#[test]
fn test_binary_writer_reader_vec_string() {
let mut writer = BinaryWriter::new();
let strings = vec![
"Hello".to_string(),
"Bin-It".to_string(),
"Serialization".to_string(),
"".to_string(),
"🚀✨".to_string(),
];
writer.write_vec_string(&strings);
let data = writer.get_data().clone();
let mut reader = BinaryReader::new(&data);
let read_strings = reader.read_vec_string().unwrap();
assert_eq!(read_strings, strings);
}
#[test]
fn test_binary_reader_error() {
let data = vec![1, 2];
let mut reader = BinaryReader::new(&data);
assert!(reader.read_u32().is_err());
}
}