use std::fmt::{Debug, Formatter, Display};
use std::fmt;
pub use marshall_derive;
#[derive(PartialEq, Eq)]
pub struct ReadError {
pub size: usize,
pub overflow: usize,
}
impl ReadError {
fn new(size: usize, overflow: usize) -> Self {
Self {
size,
overflow,
}
}
}
impl Debug for ReadError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str(&*format!("attempt to read with overflow, size wos {}, you tried to access {}", self.size, self.overflow))
}
}
impl Display for ReadError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str(&*format!("attempt to read with overflow, size wos {}, you tried to access {}", self.size, self.overflow))
}
}
pub trait Interface<T> {
fn write(&mut self, data: T);
fn read(&mut self) -> Result<T, ReadError>;
}
pub trait Marshall<T> {
fn marshall(&self, buff: &mut ByteBuff);
fn unmarshall(buff: &mut ByteBuff) -> Result<T, ReadError>;
}
#[derive(Debug)]
pub struct ByteBuff {
vec: Vec<u8>,
cursor: usize,
has_len: bool,
write: bool,
}
macro_rules! implement {
($tp: ty, $size: literal) => {
impl Interface<$tp> for ByteBuff {
#[inline]
fn write(&mut self, data: $tp) {
self.vec.extend(&data.to_be_bytes());
}
#[inline]
fn read(&mut self) -> Result<$tp, ReadError> {
self.cursor += $size;
if self.cursor > self.vec.len() {
return Err(ReadError::new(self.vec.len(), self.cursor));
}
let mut buff = [0; $size];
buff.copy_from_slice(&self.vec[self.cursor - $size..self.cursor]);
Ok(<$tp>::from_be_bytes(buff))
}
}
};
}
implement!(usize, 8);
implement!(u128, 16);
implement!(u64, 8);
implement!(u32, 4);
implement!(u16, 2);
implement!(u8, 1);
implement!(i128, 16);
implement!(i64, 8);
implement!(i32, 4);
implement!(i16, 2);
implement!(i8, 1);
implement!(f64, 8);
implement!(f32, 4);
impl Interface<bool> for ByteBuff {
#[inline]
fn write(&mut self, data: bool) {
self.vec.push(data as u8);
}
#[inline]
fn read(&mut self) -> Result<bool, ReadError> {
self.cursor += 1;
if self.cursor > self.vec.len() {
return Err(ReadError::new(self.vec.len(), self.cursor))
}
Ok(self.vec[self.cursor - 1] != 0)
}
}
impl Interface<Vec<u8>> for ByteBuff {
fn write(&mut self, data: Vec<u8>) {
self.write(data.len());
self.vec.extend(&data);
}
fn read(&mut self) -> Result<Vec<u8>, ReadError> {
let len: usize = self.read()?;
self.cursor += len;
if self.cursor > self.vec.len() {
return Err(ReadError::new(self.vec.len(), self.cursor))
}
Ok(Vec::from(&self.vec[self.cursor - len..self.cursor]))
}
}
impl Interface<String> for ByteBuff {
fn write(&mut self, data: String) {
self.write(data.len());
self.vec.extend(data.as_bytes());
}
fn read(&mut self) -> Result<String, ReadError> {
let len: usize = self.read()?;
self.cursor += len;
if self.cursor > self.vec.len() {
return Err(ReadError::new(self.vec.len(), self.cursor))
}
Ok(unsafe {String::from_utf8_unchecked(Vec::from(&self.vec[self.cursor - len..self.cursor]))})
}
}
impl ByteBuff {
#[inline]
pub fn new() -> Self {
Self {
vec: vec![],
cursor: 0,
has_len: false,
write: true,
}
}
#[inline]
pub fn with_capacity(cap: usize) -> Self {
Self {
vec: Vec::with_capacity(cap),
cursor: 0,
has_len: false,
write: true,
}
}
pub fn from_bytes(data: &[u8]) -> Self {
Self {
vec: Vec::from(data),
cursor: 0,
has_len: true,
write: false,
}
}
#[inline]
pub fn len(&self) -> usize {
self.vec.len()
}
fn add_len_if_missing(&mut self) {
if !self.has_len {
let mut len = Vec::from(self.vec.len().to_be_bytes());
len.extend(&self.vec);
self.vec = len;
self.has_len = true
}
}
pub fn clear(&mut self) {
self.vec.clear();
self.cursor = 0;
self.has_len = false;
}
pub fn is_finished(&self) -> bool {
self.cursor == self.vec.len()
}
pub fn data(&self) -> &[u8] {
return &self.vec
}
pub fn extend(&mut self, other: &Self) {
self.add_len_if_missing();
if !other.has_len {
self.write(other.vec.len());
}
self.vec.extend(&other.vec);
}
pub fn split(mut self, reminder: Option<Self>, reminding_size: usize, mut reminding_data: Vec<u8>, collector: &mut Vec<Self>) -> (Option<Self>, usize, Vec<u8>) {
if let Some(mut prev) = reminder {
let supposed = reminding_size - prev.vec.len();
if self.vec.len() < supposed {
prev.vec.extend(&self.vec);
return (Some(prev), reminding_size, vec![]);
}
self.cursor += supposed;
prev.vec.extend(&self.vec[..supposed]);
collector.push(prev);
} else if !reminding_data.is_empty() {
reminding_data.extend(&self.vec);
self.vec = reminding_data;
}
while !self.is_finished() {
let length: usize = match self.read() {
Ok(val) => val,
Err(_) => return (None, 0, self.vec),
};
self.cursor += length;
if self.vec.len() < self.cursor {
self.vec.drain(..self.cursor - length);
return (Some(self), length, Vec::new());
}
collector.push(Self::from_bytes(&self.vec[self.cursor - length..self.cursor]));
}
(None, 0, vec![])
}
}
pub trait HelloMacro {
fn hello_macro(&self);
}
mod tests {
use crate::{ByteBuff, Interface};
use crate::Marshall;
use marshall_derive::Marshall;
#[test]
fn write_read_test() {
let mut buff = ByteBuff {
vec: vec![],
cursor: 0,
has_len: false,
write: false
};
buff.write(10f64);
buff.write(15i128);
assert_eq!(Ok(10f64), buff.read());
assert_eq!(Ok(15i128), buff.read());
}
#[test]
fn split_test() {
let mut b = ByteBuff::new();
let mut c = ByteBuff::new();
b.write(10);
b.write(10f32);
c.write(10);
b.extend(&c);
let a = ByteBuff::from_bytes(&b.vec[..12]);
let d = ByteBuff::from_bytes(&b.vec[12..]);
let mut coll = vec![];
let (rem, len, r) = a.split(None, 0, vec![], &mut coll);
d.split(rem, len, r, &mut coll);
println!("{:?}", coll);
}
}