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) + if cfg!(debug_assertions) { MB * 3 } else { 0 } + (1024 * 10);
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();
}
}