mod error;
pub use error::{Error, ErrorKind, ValidateError};
pub use afastdata_macro::*;
#[cfg(feature = "len-u64")]
pub type LenInt = u64;
#[cfg(not(feature = "len-u64"))]
pub type LenInt = u32;
pub const LEN_INT_SIZE: usize = std::mem::size_of::<LenInt>();
pub trait AFastSerialize {
fn to_bytes(&self) -> Vec<u8>;
}
pub trait AFastDeserialize: Sized {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error>;
}
fn read_exact(data: &[u8], offset: usize, n: usize) -> Result<&[u8], Error> {
if offset + n > data.len() {
Err(Error::deserialize(format!(
"Not enough bytes: need {} at offset {}, have {}",
n,
offset,
data.len()
)))
} else {
Ok(&data[offset..offset + n])
}
}
macro_rules! impl_serialize_int {
($t:ty, $size:expr) => {
impl AFastSerialize for $t {
fn to_bytes(&self) -> Vec<u8> {
self.to_le_bytes().to_vec()
}
}
impl AFastDeserialize for $t {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let bytes = read_exact(data, 0, $size)?;
let arr: [u8; $size] = bytes.try_into().unwrap();
Ok((Self::from_le_bytes(arr), $size))
}
}
};
}
impl_serialize_int!(i8, 1);
impl_serialize_int!(u8, 1);
impl_serialize_int!(i16, 2);
impl_serialize_int!(u16, 2);
impl_serialize_int!(i32, 4);
impl_serialize_int!(u32, 4);
impl_serialize_int!(i64, 8);
impl_serialize_int!(u64, 8);
impl_serialize_int!(i128, 16);
impl_serialize_int!(u128, 16);
impl_serialize_int!(f32, 4);
impl_serialize_int!(f64, 8);
impl AFastSerialize for bool {
fn to_bytes(&self) -> Vec<u8> {
vec![if *self { 1 } else { 0 }]
}
}
impl AFastDeserialize for bool {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let bytes = read_exact(data, 0, 1)?;
match bytes[0] {
0 => Ok((false, 1)),
1 => Ok((true, 1)),
v => Err(Error::deserialize(format!("Invalid bool value: {}", v))),
}
}
}
fn write_len(buf: &mut Vec<u8>, len: usize) {
let v = len as LenInt;
buf.extend(v.to_le_bytes());
}
fn read_len(data: &[u8], offset: usize) -> Result<(usize, usize), Error> {
let bytes = read_exact(data, offset, LEN_INT_SIZE)?;
let arr: [u8; LEN_INT_SIZE] = bytes.try_into().unwrap();
let len = LenInt::from_le_bytes(arr) as usize;
Ok((len, offset + LEN_INT_SIZE))
}
impl AFastSerialize for String {
fn to_bytes(&self) -> Vec<u8> {
let bytes = self.as_bytes();
let mut result = Vec::with_capacity(LEN_INT_SIZE + bytes.len());
write_len(&mut result, bytes.len());
result.extend_from_slice(bytes);
result
}
}
impl AFastDeserialize for String {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (len, offset) = read_len(data, 0)?;
let bytes = read_exact(data, offset, len)?;
let s = std::str::from_utf8(bytes)
.map_err(|e| Error::deserialize(format!("Invalid UTF-8: {}", e)))?;
Ok((s.to_owned(), offset + len))
}
}
impl<T: AFastSerialize> AFastSerialize for Vec<T> {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(LEN_INT_SIZE + self.len());
write_len(&mut result, self.len());
for item in self {
result.extend(item.to_bytes());
}
result
}
}
impl<T: AFastDeserialize> AFastDeserialize for Vec<T> {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (len, mut offset) = read_len(data, 0)?;
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
let (item, new_offset) = T::from_bytes(&data[offset..])?;
vec.push(item);
offset += new_offset;
}
Ok((vec, offset))
}
}
impl<T: AFastSerialize> AFastSerialize for Option<T> {
fn to_bytes(&self) -> Vec<u8> {
match self {
Some(val) => {
let mut result = vec![1u8];
result.extend(val.to_bytes());
result
}
None => vec![0u8],
}
}
}
impl<T: AFastDeserialize> AFastDeserialize for Option<T> {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let bytes = read_exact(data, 0, 1)?;
match bytes[0] {
0 => Ok((None, 1)),
1 => {
let (val, new_offset) = T::from_bytes(&data[1..])?;
Ok((Some(val), 1 + new_offset))
}
v => Err(Error::deserialize(format!("Invalid Option tag: {}", v))),
}
}
}
impl<T: AFastSerialize, const N: usize> AFastSerialize for [T; N] {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(LEN_INT_SIZE + N);
for item in self {
result.extend(item.to_bytes());
}
result
}
}
impl<T: AFastDeserialize + Default + Copy, const N: usize> AFastDeserialize for [T; N] {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let mut arr = [T::default(); N];
let mut offset = 0;
for item in arr.iter_mut() {
let (val, new_offset) = T::from_bytes(&data[offset..])?;
*item = val;
offset += new_offset;
}
Ok((arr, offset))
}
}
impl AFastSerialize for &str {
fn to_bytes(&self) -> Vec<u8> {
let bytes = self.as_bytes();
let len = bytes.len() as LenInt;
let mut result = len.to_le_bytes().to_vec();
result.extend_from_slice(bytes);
result
}
}
impl<K: AFastSerialize, V: AFastSerialize> AFastSerialize for std::collections::HashMap<K, V> {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(LEN_INT_SIZE);
write_len(&mut result, self.len());
for (k, v) in self {
result.extend(k.to_bytes());
result.extend(v.to_bytes());
}
result
}
}
impl<K: AFastDeserialize + Eq + std::hash::Hash, V: AFastDeserialize> AFastDeserialize
for std::collections::HashMap<K, V>
{
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (len, mut offset) = read_len(data, 0)?;
let mut map = std::collections::HashMap::with_capacity(len);
for _ in 0..len {
let (key, new_offset) = K::from_bytes(&data[offset..])?;
offset += new_offset;
let (val, new_offset) = V::from_bytes(&data[offset..])?;
offset += new_offset;
map.insert(key, val);
}
Ok((map, offset))
}
}
impl<T: AFastSerialize> AFastSerialize for std::collections::HashSet<T> {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(LEN_INT_SIZE);
write_len(&mut result, self.len());
for item in self {
result.extend(item.to_bytes());
}
result
}
}
impl<T: AFastDeserialize + Eq + std::hash::Hash> AFastDeserialize for std::collections::HashSet<T> {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (len, mut offset) = read_len(data, 0)?;
let mut set = std::collections::HashSet::with_capacity(len);
for _ in 0..len {
let (item, new_offset) = T::from_bytes(&data[offset..])?;
offset += new_offset;
set.insert(item);
}
Ok((set, offset))
}
}
impl<K: AFastSerialize, V: AFastSerialize> AFastSerialize for std::collections::BTreeMap<K, V> {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(LEN_INT_SIZE);
write_len(&mut result, self.len());
for (k, v) in self {
result.extend(k.to_bytes());
result.extend(v.to_bytes());
}
result
}
}
impl<K: AFastDeserialize + Ord, V: AFastDeserialize> AFastDeserialize
for std::collections::BTreeMap<K, V>
{
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (len, mut offset) = read_len(data, 0)?;
let mut map = std::collections::BTreeMap::new();
for _ in 0..len {
let (key, new_offset) = K::from_bytes(&data[offset..])?;
offset += new_offset;
let (val, new_offset) = V::from_bytes(&data[offset..])?;
offset += new_offset;
map.insert(key, val);
}
Ok((map, offset))
}
}
impl<T: AFastSerialize> AFastSerialize for std::collections::BTreeSet<T> {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(LEN_INT_SIZE);
write_len(&mut result, self.len());
for item in self {
result.extend(item.to_bytes());
}
result
}
}
impl<T: AFastDeserialize + Ord> AFastDeserialize for std::collections::BTreeSet<T> {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (len, mut offset) = read_len(data, 0)?;
let mut set = std::collections::BTreeSet::new();
for _ in 0..len {
let (item, new_offset) = T::from_bytes(&data[offset..])?;
offset += new_offset;
set.insert(item);
}
Ok((set, offset))
}
}
macro_rules! impl_tuple {
() => {};
($first:ident $(, $rest:ident)*) => {
#[allow(non_snake_case)]
impl<$first: AFastSerialize $(, $rest: AFastSerialize)*> AFastSerialize for ($first, $($rest,)*) {
fn to_bytes(&self) -> Vec<u8> {
let ($first, $($rest,)*) = self;
let mut result = Vec::new();
result.extend($first.to_bytes());
$(result.extend($rest.to_bytes());)*
result
}
}
#[allow(non_snake_case)]
impl<$first: AFastDeserialize $(, $rest: AFastDeserialize)*> AFastDeserialize for ($first, $($rest,)*) {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let mut offset = 0;
let ($first, new_offset) = <$first as AFastDeserialize>::from_bytes(&data[offset..])?;
offset += new_offset;
$(
let ($rest, new_offset) = <$rest as AFastDeserialize>::from_bytes(&data[offset..])?;
offset += new_offset;
)*
Ok((($first, $($rest,)*), offset))
}
}
impl_tuple!($($rest),*);
};
}
impl<T: AFastSerialize> AFastSerialize for Box<T> {
fn to_bytes(&self) -> Vec<u8> {
(**self).to_bytes()
}
}
impl<T: AFastDeserialize> AFastDeserialize for Box<T> {
fn from_bytes(data: &[u8]) -> Result<(Self, usize), Error> {
let (val, offset) = T::from_bytes(data)?;
Ok((Box::new(val), offset))
}
}
#[cfg(all(feature = "tuple-8", not(any(feature = "tuple-16", feature = "tuple-32"))))]
impl_tuple!(A, B, C, D, E, F, G, H);
#[cfg(all(feature = "tuple-16", not(feature = "tuple-32")))]
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
#[cfg(feature = "tuple-32")]
impl_tuple!(
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
Q, R, S, T, U, V, W, X, Y, Z, AA, AB, AC, AD, AE, AF
);