bytes-kman 0.3.1

serialize and deserialize bytes, a simple way to comunicate to other computer or to save state!
Documentation
use crate::{TBuffer, TBytes};

pub mod num;
pub mod option;
pub mod primitive;
pub mod result;
pub mod tuple;

impl<T: TBytes, const LEN: usize> TBytes for [T; LEN] {
    fn size(&self) -> usize {
        let mut size = 0;
        for p in self.iter() {
            size += p.size();
        }
        size
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut buffer = Vec::with_capacity(self.size());

        for p in self.iter() {
            buffer.append(&mut p.to_bytes())
        }

        buffer
    }

    fn from_bytes(buffer: &mut TBuffer) -> Option<Self>
    where
        Self: Sized,
    {
        let mut array = core::mem::MaybeUninit::<[T; LEN]>::uninit();

        for index in 0..LEN {
            if let Some(value) = T::from_bytes(buffer) {
                unsafe { std::ptr::write(&mut array.assume_init_mut()[index], value) };
            } else {
                for i in 0..index {
                    let index = (index - 1) - i;
                    buffer.reverse();
                    unsafe {
                        let item = &mut array.assume_init_mut()[index];
                        buffer.extend(item.to_bytes().iter().rev());
                        core::ptr::drop_in_place(item);
                    }
                    buffer.reverse();
                }
                return None;
            }
        }

        Some(unsafe { array.assume_init() })
    }
}

#[cfg(test)]
mod test {
    use crate::TBytes;

    #[test]
    fn array_i32() {
        let a = [32, 543, 61, 21215, -4236, 32];

        let mut bytes = a.to_bytes();

        let other = <[i32; 6]>::from_bytes(&mut bytes).unwrap();

        assert_eq!(a, other);
    }

    #[test]
    fn array_string() {
        let a = [
            "Hello World!".to_string(),
            "This is working???".into(),
            "Is working as is supposed!".into(),
        ];

        let mut bytes = a.to_bytes();

        let other = <[String; 3]>::from_bytes(&mut bytes).unwrap();

        assert_eq!(a, other);
    }

    #[test]
    fn array_incomplete() {
        let mut buffer = Vec::new();
        let strings = ["Where", "Are", "You", "From"].map(|w| w.to_string());
        for string in &strings[0..3] {
            buffer.append(&mut string.to_bytes());
        }
        let clone_buffer = buffer.clone();

        let other_buffer = <[String; 4]>::from_bytes(&mut buffer);
        if let Some(other_buffer) = other_buffer {
            panic!("This should be possible! Other buffer: {other_buffer:?}");
        }

        assert_eq!(buffer, clone_buffer);
        buffer.append(&mut strings[3].to_bytes());

        let value = <[String; 4]>::from_bytes(&mut buffer).unwrap();
        assert_eq!(value, strings)
    }

    #[test]
    fn array_drop_and_incomplete_drop() {
        use crate::prelude::*;

        thread_local! { static LAST_DROPED: core::cell::Cell<u32> = const {core::cell::Cell::<u32>::new(0)}};

        #[derive(Bytes)]
        struct ToDrop {
            id: u32,
        }

        impl Drop for ToDrop {
            fn drop(&mut self) {
                LAST_DROPED.set(self.id);
            }
        }

        let mut buffer = Vec::new();
        {
            buffer.append(&mut ToDrop { id: 1 }.to_bytes());
        }
        assert_eq!(LAST_DROPED.get(), 1);
        {
            buffer.append(&mut ToDrop { id: 2 }.to_bytes());
        }
        assert_eq!(LAST_DROPED.get(), 2);
        let buffer_clone = buffer.clone();

        LAST_DROPED.set(0);

        let other_buffer = <[ToDrop; 2]>::from_bytes(&mut buffer).unwrap();
        assert_eq!(LAST_DROPED.get(), 0);
        assert_eq!(other_buffer.to_bytes(), buffer_clone);

        buffer = buffer_clone.clone();
        assert!(<[ToDrop; 3]>::from_bytes(&mut buffer).is_none());
        assert_eq!(LAST_DROPED.get(), 1);
        assert_eq!(other_buffer.to_bytes(), buffer_clone);
    }

    #[test]
    fn array_1mb() {
        const MB: usize = 1024 * 1024;
        const STACK_SIZE: usize = (MB * 3) // needed for slices
                                + if cfg!(debug_assertions) { MB * 3 } else { 0 } // debug
                                + (1024 * 10); // 10KB code stack

        std::thread::Builder::new()
            .stack_size(STACK_SIZE)
            .name(format!("{}MB stack", STACK_SIZE / MB))
            .spawn(|| {
                let mut buffer = {
                    let a = [0u8; MB];
                    a.to_bytes()
                };
                let buffer_clone = buffer.clone();
                let res = <[u8; MB]>::from_bytes(&mut buffer).unwrap();
                assert_eq!(res.to_bytes(), buffer_clone);
            })
            .unwrap()
            .join()
            .unwrap();
    }
}