use crate::{
byte_buffer::ByteBuffer,
byte_buffer_read::ByteBufferRead,
error::{ByteBufferError, Result},
};
use std::{
any::TypeId,
mem::{self, MaybeUninit},
};
struct Guard<'a, T, const N: usize> {
array_mut: &'a mut [MaybeUninit<T>; N],
initialized: usize,
}
impl<T, const N: usize> Drop for Guard<'_, T, N> {
fn drop(&mut self) {
debug_assert!(self.initialized <= N);
unsafe {
std::ptr::drop_in_place(
&mut *(self.array_mut.get_unchecked_mut(..self.initialized)
as *mut [MaybeUninit<T>] as *mut [T]),
);
}
}
}
impl<T: ByteBufferRead + 'static, const N: usize> ByteBufferRead for [T; N] {
#[inline]
fn read_from_bytey_buffer(buffer: &mut ByteBuffer) -> Result<Self> {
if N == 0 {
return Err(ByteBufferError::OtherError {
error: "Can not read to an [T;0]. The array must have a size.".to_owned(),
});
}
let size = buffer.read::<u64>()? as usize;
if size != N {
return Err(ByteBufferError::OtherError {
error: format!(
"Invalid size in buffer for [T; {}]. Should be [T; {}]?",
N, size
),
});
}
if TypeId::of::<u8>() == TypeId::of::<T>() {
let mut buf = [0u8; N];
buf[..N].copy_from_slice(buffer.read_slice(N)?);
let ptr = &mut buf as *mut _ as *mut [T; N];
Ok(unsafe { ptr.read() })
} else {
let mut array = unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
let mut guard = Guard {
array_mut: &mut array,
initialized: 0,
};
for _ in 0..N {
let item = buffer.read::<T>()?;
unsafe {
guard
.array_mut
.get_unchecked_mut(guard.initialized)
.write(item);
}
guard.initialized += 1;
}
if guard.initialized == N {
mem::forget(guard);
let out = unsafe { (&array as *const _ as *const [T; N]).read() };
Ok(out)
} else {
Err(ByteBufferError::OtherError {
error: "Not all of the array was initialized".to_owned(),
})
}
}
}
#[inline]
fn read_from_bytey_buffer_le(buffer: &mut ByteBuffer) -> Result<Self> {
if N == 0 {
return Err(ByteBufferError::OtherError {
error: "Can not read to an [T;0]. The array must have a size.".to_owned(),
});
}
let size = buffer.read_le::<u64>()? as usize;
if size != N {
return Err(ByteBufferError::OtherError {
error: format!(
"Invalid size in buffer for [T; {}]. Should be [T; {}]?",
N, size
),
});
}
if TypeId::of::<u8>() == TypeId::of::<T>() {
let mut buf = [0u8; N];
buf[..N].copy_from_slice(buffer.read_slice(N)?);
let ptr = &mut buf as *mut _ as *mut [T; N];
Ok(unsafe { ptr.read() })
} else {
let mut array = unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
let mut guard = Guard {
array_mut: &mut array,
initialized: 0,
};
for _ in 0..N {
let item = buffer.read_le::<T>()?;
unsafe {
guard
.array_mut
.get_unchecked_mut(guard.initialized)
.write(item);
}
guard.initialized += 1;
}
if guard.initialized == N {
mem::forget(guard);
let out = unsafe { (&array as *const _ as *const [T; N]).read() };
Ok(out)
} else {
Err(ByteBufferError::OtherError {
error: "Not all of the array was initialized".to_owned(),
})
}
}
}
#[inline]
fn read_from_bytey_buffer_be(buffer: &mut ByteBuffer) -> Result<Self> {
if N == 0 {
return Err(ByteBufferError::OtherError {
error: "Can not read to an [T;0]. The array must have a size.".to_owned(),
});
}
let size = buffer.read_be::<u64>()? as usize;
if size != N {
return Err(ByteBufferError::OtherError {
error: format!(
"Invalid size in buffer for [T; {}]. Should be [T; {}]?",
N, size
),
});
}
if TypeId::of::<u8>() == TypeId::of::<T>() {
let mut buf = [0u8; N];
buf[..N].copy_from_slice(buffer.read_slice(N)?);
let ptr = &mut buf as *mut _ as *mut [T; N];
Ok(unsafe { ptr.read() })
} else {
let mut array = unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
let mut guard = Guard {
array_mut: &mut array,
initialized: 0,
};
for _ in 0..N {
let item = buffer.read_be::<T>()?;
unsafe {
guard
.array_mut
.get_unchecked_mut(guard.initialized)
.write(item);
}
guard.initialized += 1;
}
if guard.initialized == N {
mem::forget(guard);
let out = unsafe { (&array as *const _ as *const [T; N]).read() };
Ok(out)
} else {
Err(ByteBufferError::OtherError {
error: "Not all of the array was initialized".to_owned(),
})
}
}
}
}
impl<T: ByteBufferRead> ByteBufferRead for Vec<T> {
#[inline]
fn read_from_bytey_buffer(buffer: &mut ByteBuffer) -> Result<Self> {
let size = buffer.read::<u64>()? as usize;
if size == 0 {
return Ok(Vec::new());
}
let mut vec = Vec::with_capacity(size);
for _ in 0..size {
vec.push(buffer.read::<T>()?);
}
Ok(vec)
}
#[inline]
fn read_from_bytey_buffer_le(buffer: &mut ByteBuffer) -> Result<Self> {
let size = buffer.read_le::<u64>()? as usize;
if size == 0 {
return Ok(Vec::new());
}
let mut vec = Vec::with_capacity(size);
for _ in 0..size {
vec.push(buffer.read_le::<T>()?);
}
Ok(vec)
}
#[inline]
fn read_from_bytey_buffer_be(buffer: &mut ByteBuffer) -> Result<Self> {
let size = buffer.read_be::<u64>()? as usize;
if size == 0 {
return Ok(Vec::new());
}
let mut vec = Vec::with_capacity(size);
for _ in 0..size {
vec.push(buffer.read_be::<T>()?);
}
Ok(vec)
}
}