use crate::SerializationError;
pub use crate::io::{Read, Write};
use serde::de::{self, DeserializeOwned, Deserializer};
pub trait Flags: Default + Clone + Copy + Sized {
const BIT_SIZE: usize;
fn u8_bitmask(&self) -> u8;
fn from_u8(value: u8) -> Option<Self>;
fn from_u8_remove_flags(value: &mut u8) -> Option<Self> {
let flags = Self::from_u8(*value);
if let Some(f) = flags {
*value &= !f.u8_bitmask();
}
flags
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Compress {
Yes,
No,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Validate {
Yes,
No,
}
pub trait Valid: Sized + Sync {
fn check(&self) -> Result<(), SerializationError>;
fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
where
Self: 'a,
{
#[cfg(not(feature = "serial"))]
{
use rayon::{iter::ParallelBridge, prelude::ParallelIterator};
batch.par_bridge().try_for_each(|e| e.check())?;
}
#[cfg(feature = "serial")]
{
for item in batch {
item.check()?;
}
}
Ok(())
}
}
pub trait CanonicalSerialize {
fn serialize_with_mode<W: Write>(&self, writer: W, compress: Compress) -> Result<(), SerializationError>;
fn serialized_size(&self, compress: Compress) -> usize;
fn serialize_compressed<W: Write>(&self, writer: W) -> Result<(), SerializationError> {
self.serialize_with_mode(writer, Compress::Yes)
}
fn compressed_size(&self) -> usize {
self.serialized_size(Compress::Yes)
}
fn serialize_uncompressed<W: Write>(&self, writer: W) -> Result<(), SerializationError> {
self.serialize_with_mode(writer, Compress::No)
}
fn uncompressed_size(&self) -> usize {
self.serialized_size(Compress::No)
}
}
pub trait CanonicalDeserialize: Valid {
fn deserialize_with_mode<R: Read>(
reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError>;
fn deserialize_compressed<R: Read>(reader: R) -> Result<Self, SerializationError> {
Self::deserialize_with_mode(reader, Compress::Yes, Validate::Yes)
}
fn deserialize_compressed_unchecked<R: Read>(reader: R) -> Result<Self, SerializationError> {
Self::deserialize_with_mode(reader, Compress::Yes, Validate::No)
}
fn deserialize_uncompressed<R: Read>(reader: R) -> Result<Self, SerializationError> {
Self::deserialize_with_mode(reader, Compress::No, Validate::Yes)
}
fn deserialize_uncompressed_unchecked<R: Read>(reader: R) -> Result<Self, SerializationError> {
Self::deserialize_with_mode(reader, Compress::No, Validate::No)
}
}
pub trait CanonicalSerializeWithFlags: CanonicalSerialize {
fn serialize_with_flags<W: Write, F: Flags>(&self, writer: W, flags: F) -> Result<(), SerializationError>;
fn serialized_size_with_flags<F: Flags>(&self) -> usize;
}
pub trait CanonicalDeserializeWithFlags: Sized {
fn deserialize_with_flags<R: Read, F: Flags>(reader: R) -> Result<(Self, F), SerializationError>;
}
pub trait DeserializeExt<'de>
where
Self: DeserializeOwned,
{
fn take_from_value<D: Deserializer<'de>>(value: &mut serde_json::Value, field: &str) -> Result<Self, D::Error>;
}
impl<'de, T> DeserializeExt<'de> for T
where
T: DeserializeOwned,
{
fn take_from_value<D: Deserializer<'de>>(value: &mut serde_json::Value, field: &str) -> Result<Self, D::Error> {
serde_json::from_value(
value.get_mut(field).ok_or_else(|| de::Error::custom(format!("The \"{field}\" field is missing")))?.take(),
)
.map_err(de::Error::custom)
}
}