use core::fmt::Debug;
use pretty_hex::*;
use anyhow::{Result, anyhow, Context};
pub struct Payload {
bytes: Vec<u8>
}
impl Payload {
pub fn pad_byte(&mut self) -> Result<u8> {
if let Some(byte) = self.bytes.pop() {
Ok(byte)
} else {
Err(anyhow!("You are out of bytes to pop"))
}
}
pub fn pad_bytes(&mut self, num : usize) -> Result<()> {
for _ in 0..num {
self.pad_byte()
.with_context(|| "Could not pad byte")?;
}
Ok(())
}
pub fn pop_head(&mut self) -> Result<bool> {
self.pad_bytes(3)
.with_context(|| "Could not pop 3 bytes header")?;
Ok(true)
}
pub fn pop_u16(&mut self) -> Result<u16> {
let mut value_bytes : [u8; 2] = [0, 0];
value_bytes[0] = self.pad_byte()?;
value_bytes[1] = self.pad_byte()?;
let value = u16::from_le_bytes(value_bytes);
Ok(value)
}
pub fn pop_bool(&mut self) -> Result<bool> {
let val = self.pop_u16()
.with_context(|| "Could not read bool")?;
Ok(val == 1)
}
pub fn pop_i16(&mut self) -> Result<i16> {
let mut value_bytes : [u8; 2] = [0, 0];
value_bytes[0] = self.pad_byte()?;
value_bytes[1] = self.pad_byte()?;
let value = i16::from_le_bytes(value_bytes);
Ok(value)
}
pub fn pop_u32(&mut self) -> Result<u32> {
let mut value_bytes : [u8; 4] = [0, 0, 0, 0];
value_bytes[0] = self.pad_byte()?;
value_bytes[1] = self.pad_byte()?;
value_bytes[2] = self.pad_byte()?;
value_bytes[3] = self.pad_byte()?;
let value = u32::from_le_bytes(value_bytes);
Ok(value)
}
pub fn pop_i32(&mut self) -> Result<i32> {
let mut value_bytes : [u8; 4] = [0, 0, 0, 0];
value_bytes[0] = self.pad_byte()?;
value_bytes[1] = self.pad_byte()?;
value_bytes[2] = self.pad_byte()?;
value_bytes[3] = self.pad_byte()?;
let value = i32::from_le_bytes(value_bytes);
Ok(value)
}
pub fn pop_string_utf8(&mut self, characters: usize) -> Result<String> {
let mut string_bytes : Vec<u8> = Vec::new();
for _ in 0..characters {
let byte = self.pad_byte()?;
string_bytes.push(byte);
}
let string = String::from_utf8_lossy(&string_bytes);
Ok(string.into_owned())
}
}
impl From<Vec<u8>> for Payload {
fn from(bytes: Vec<u8>) -> Self {
let mut bytes = bytes.clone();
bytes.reverse();
Self {
bytes
}
}
}
impl From<&[u8]> for Payload {
fn from(bytes: &[u8]) -> Self {
let mut vec : Vec<u8> = Vec::new();
vec.extend_from_slice(bytes);
vec.reverse();
Self {
bytes: vec
}
}
}
impl Debug for Payload {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
let message = format!("Payload: {:?}", self.bytes.hex_dump());
fmt.write_str(&message).unwrap();
Ok(())
}
}