#![no_std]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod iterators;
use alloc::vec::Vec;
use core::{mem, slice};
mod serde;
#[cfg(feature = "std")]
pub use serde::ReadAdapter;
pub use serde::{ByteReader, ByteWriter, Deserializable, Serializable, SliceReader};
mod errors;
pub use errors::DeserializationError;
#[cfg(test)]
mod tests;
#[cfg(feature = "concurrent")]
use iterators::*;
#[cfg(feature = "concurrent")]
pub use rayon;
pub trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl<const N: usize, const M: usize> AsBytes for [[u8; N]; M] {
fn as_bytes(&self) -> &[u8] {
let p = self.as_ptr();
let len = N * M;
unsafe { slice::from_raw_parts(p as *const u8, len) }
}
}
impl<const N: usize> AsBytes for [[u8; N]] {
fn as_bytes(&self) -> &[u8] {
let p = self.as_ptr();
let len = self.len() * N;
unsafe { slice::from_raw_parts(p as *const u8, len) }
}
}
#[allow(clippy::uninit_vec)]
pub unsafe fn uninit_vector<T>(length: usize) -> Vec<T> {
let mut vector = Vec::with_capacity(length);
vector.set_len(length);
vector
}
pub fn group_slice_elements<T, const N: usize>(source: &[T]) -> &[[T; N]] {
assert_eq!(source.len() % N, 0, "source length must be divisible by {N}");
let p = source.as_ptr();
let len = source.len() / N;
unsafe { slice::from_raw_parts(p as *const [T; N], len) }
}
pub fn flatten_slice_elements<T, const N: usize>(source: &[[T; N]]) -> &[T] {
let p = source.as_ptr();
let len = source.len() * N;
unsafe { slice::from_raw_parts(p as *const T, len) }
}
pub fn flatten_vector_elements<T, const N: usize>(source: Vec<[T; N]>) -> Vec<T> {
let v = mem::ManuallyDrop::new(source);
let p = v.as_ptr();
let len = v.len() * N;
let cap = v.capacity() * N;
unsafe { Vec::from_raw_parts(p as *mut T, len, cap) }
}
pub fn transpose_slice<T: Copy + Send + Sync, const N: usize>(source: &[T]) -> Vec<[T; N]> {
let row_count = source.len() / N;
assert_eq!(
row_count * N,
source.len(),
"source length must be divisible by {}, but was {}",
N,
source.len()
);
let mut result: Vec<[T; N]> = unsafe { uninit_vector(row_count) };
iter_mut!(result, 1024).enumerate().for_each(|(i, element)| {
for j in 0..N {
element[j] = source[i + j * row_count]
}
});
result
}
pub trait Randomizable: Sized {
const VALUE_SIZE: usize;
fn from_random_bytes(source: &[u8]) -> Option<Self>;
}
impl Randomizable for u128 {
const VALUE_SIZE: usize = 16;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u128::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u64 {
const VALUE_SIZE: usize = 8;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u64::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u32 {
const VALUE_SIZE: usize = 4;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u32::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u16 {
const VALUE_SIZE: usize = 2;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u16::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u8 {
const VALUE_SIZE: usize = 1;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
Some(source[0])
}
}