bytebuff 0.1.1

Crate provides usefull derive macro for serializing data to send ower network.
//! This crate is purely for marshalling and unmarshalling a data to send over a network,
//! main deal is ByteBuff witch is used for serilizing and deserilizing. There is also Marshal
//! trait that can be derivated on structs.
//!
//! # example
//!
//! ```
//! extern crate bytebuff;
//! use bytebuff::marshall_derive::Marshall;
//! use bytebuff::Marshall;
//! use bytebuff::ByteBuff;
//!
//! #[derive(Marshall)]
//! struct Point {
//!     x: f32,
//!     y: f32,
//! }
//!
//! #[derive(Marshall)]
//! struct Dummy {
//!     #[marshall(nested)]
//!     position: Point,
//!     name: String,
//!     #[marshall(ignore)]
//!     useless_stuff: i128,
//! }
//!
//! fn main() {
//!     let mut buff = ByteBuff::new();
//!
//!     let dummy = Dummy {
//!         useless_stuff: 10,
//!         position: Point { x: 10.0, y: 70.0 },
//!         name: String::from("Mlokogrgel"),
//!     };
//!
//!     //dummy can write it self to ByteBuff
//!     dummy.marshall(&mut buff);
//!
//!     //now imagine we sent buffer with dummy over the network
//!     let mut buff = ByteBuff::from_bytes(buff.data());
//!
//!     //and dummy can also read its self from buffer
//!     let de_dummy = Dummy::unmarshall(&mut buff).unwrap();
//!
//!     //ignored data don't ewen get written to buffer in first place and is replaced
//!     //by default, in any case you can always implement Default trait to your types
//!     assert_eq!(de_dummy.useless_stuff, Default::default());
//!
//!     //you can nest how match you want as long as you annotate so
//!     assert_eq!(10.0, de_dummy.position.x);
//!     assert_eq!(70.0, de_dummy.position.y);
//!
//!     // other then all numbers, strings, booleans and bite vectors are supported
//!     assert_eq!(String::from("Mlokogrgel"), de_dummy.name);
//! }
//! ```

use std::fmt::{Debug, Formatter, Display};
use std::fmt;

pub use marshall_derive;


/// ReadError informs about the read overflow, this happens when you for example try to read usize
/// from buffer where is only one bool. In this case you would get ReadError { size: 1, overflow: 8 }
#[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>;
}

/// ByteBuff is a convenient helper for game networking. Using this is similar to using ThreadRng
/// from rand package. Example speaks for it self.
///
/// # Example
/// ```
/// use bytebuff::{ByteBuff, ReadError, Interface};
/// let mut buff = ByteBuff::new();
///
/// buff.write(10f32); // supports float types
/// buff.write(30); // all integer types
/// buff.write(vec![10u8, 5u8, 8u8]); // as well as strings and byte vectors
///
/// assert_eq!(Ok(10f32), buff.read());
/// assert_eq!(Ok(30), buff.read());
/// assert_eq!(Ok(vec![10u8, 5u8, 8u8]), buff.read());
/// let bool: Result<bool, ReadError> = buff.read(); // unable to infer type in this case
/// assert!(bool.is_err());
/// ```
#[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,
        }
    }

    /// works like Vec::with_capacity
    #[inline]
    pub fn with_capacity(cap: usize) -> Self {
        Self {
            vec: Vec::with_capacity(cap),
            cursor: 0,
            has_len: false,
            write: true,
        }
    }

    /// read creates buffer for reading
    pub fn from_bytes(data: &[u8]) -> Self {
        Self {
            vec: Vec::from(data),
            cursor: 0,
            has_len: true,
            write: false,
        }
    }

    /// len returns length of buffer
    #[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
        }
    }

    /// clear restarts the buffer, its useful when reusing buffers
    pub fn clear(&mut self) {
        self.vec.clear();
        self.cursor = 0;
        self.has_len = false;
    }

    /// is_finished returns whether buffer is completely red
    pub fn is_finished(&self) -> bool {
        self.cursor == self.vec.len()
    }

    /// data returns slice of buffers data
    pub fn data(&self) -> &[u8] {
        return &self.vec
    }

    /// extend works almost as Vec::extend with slight difference.
    /// it also appends size of appended data and if the self length is missing as well
    /// it will add it too.
    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);
    }

    /// split works on previously merged buffers. It splits them to original smaller parts
    /// and also some garbage that you are supposed to feed into next split call.
    /// NOW you may be asking why is there so match garbage arguments and return values, well as we
    /// know your byte buffer witch you are passing to packet sender can be only so big and packages
    /// can arrive incomplete. Function simply takes and returns these reminders so all packages get
    /// completed.
    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 { // handle leftover
            let supposed = reminding_size - prev.vec.len();
            if self.vec.len() < supposed { // the packet is bigger then 2 or more buffer sizes
                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() {
            // append remain so it is possible to read the length of packet properly
            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);
    }

    /*#[derive(Marshall)]
    pub struct Test {
        #[marshall(nested)]
        test: u32,
        fest: f32,
    }*/
}