use hitbox_core::{Cacheable, Raw};
use thiserror::Error;
use hitbox_core::BoxContext;
use crate::context::Context;
#[cfg(feature = "rkyv_format")]
use ::rkyv::{api::high::to_bytes_in, from_bytes, rancor, util::AlignedVec};
use ::bincode::config::Configuration;
use ::bincode::de::DecoderImpl;
use ::bincode::de::read::SliceReader;
use ::bincode::enc::EncoderImpl;
use ::bincode::serde::Compat;
use ::bincode::{Decode, Encode};
use self::bincode::BincodeVecWriter;
pub struct BincodeEncoder<'a>(pub(crate) &'a mut EncoderImpl<BincodeVecWriter, Configuration>);
pub struct BincodeDecoder<'a>(pub(crate) &'a mut DecoderImpl<SliceReader<'a>, Configuration, ()>);
mod bincode;
mod json;
#[cfg(feature = "rkyv_format")]
mod rkyv;
mod ron;
pub use bincode::BincodeFormat;
pub use json::JsonFormat;
#[cfg(feature = "rkyv_format")]
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv_format")))]
pub use rkyv::RkyvFormat;
pub use ron::RonFormat;
#[derive(Error, Debug)]
pub enum FormatError {
#[error(transparent)]
Serialize(Box<dyn std::error::Error + Send>),
#[error(transparent)]
Deserialize(Box<dyn std::error::Error + Send>),
}
#[cfg(feature = "rkyv_format")]
#[derive(Error, Debug)]
#[error("rkyv serialization failed: {message}")]
struct RkyvSerializeError {
message: String,
}
#[cfg(feature = "rkyv_format")]
impl RkyvSerializeError {
fn new(error: impl std::fmt::Debug) -> Self {
Self {
message: format!("{:?}", error),
}
}
}
#[cfg(feature = "rkyv_format")]
#[derive(Error, Debug)]
#[error("rkyv validation failed: {message}")]
struct RkyvValidationError {
message: String,
}
#[cfg(feature = "rkyv_format")]
impl RkyvValidationError {
fn new(error: impl std::fmt::Display) -> Self {
Self {
message: error.to_string(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FormatTypeId {
Json,
Bincode,
Ron,
Rkyv,
Custom(&'static str),
}
pub enum FormatSerializer<'a> {
Serde(&'a mut dyn erased_serde::Serializer),
#[cfg(feature = "rkyv_format")]
Rkyv(&'a mut AlignedVec),
Bincode(BincodeEncoder<'a>),
}
impl<'a> FormatSerializer<'a> {
pub fn serialize<T>(&mut self, value: &T) -> Result<(), FormatError>
where
T: Cacheable,
{
match self {
FormatSerializer::Serde(ser) => {
let erased_value = value as &dyn erased_serde::Serialize;
erased_value
.erased_serialize(*ser)
.map_err(|e| FormatError::Serialize(Box::new(e)))
}
#[cfg(feature = "rkyv_format")]
FormatSerializer::Rkyv(buffer) => {
let mut owned_buffer = std::mem::take(*buffer);
owned_buffer.clear();
let result_buffer = to_bytes_in::<_, rancor::Error>(value, owned_buffer)
.map_err(|e| FormatError::Serialize(Box::new(RkyvSerializeError::new(e))))?;
**buffer = result_buffer;
Ok(())
}
FormatSerializer::Bincode(enc) => {
let compat = Compat(value);
Encode::encode(&compat, enc.0).map_err(|e| FormatError::Serialize(Box::new(e)))
}
}
}
}
pub enum FormatDeserializer<'a> {
Serde(&'a mut dyn erased_serde::Deserializer<'a>),
#[cfg(feature = "rkyv_format")]
Rkyv(&'a [u8]),
Bincode(BincodeDecoder<'a>),
}
impl<'a> FormatDeserializer<'a> {
pub fn deserialize<T>(&mut self) -> Result<T, FormatError>
where
T: Cacheable,
{
match self {
FormatDeserializer::Serde(deser) => {
erased_serde::deserialize(*deser).map_err(|e| FormatError::Deserialize(Box::new(e)))
}
#[cfg(feature = "rkyv_format")]
FormatDeserializer::Rkyv(data) => {
let value: T = from_bytes::<T, rancor::Error>(data)
.map_err(|e| FormatError::Deserialize(Box::new(RkyvValidationError::new(e))))?;
Ok(value)
}
FormatDeserializer::Bincode(dec) => {
let compat: Compat<T> =
Decode::decode(dec.0).map_err(|e| FormatError::Deserialize(Box::new(e)))?;
Ok(compat.0)
}
}
}
}
pub trait Format: std::fmt::Debug + Send + Sync {
fn with_serializer(
&self,
f: &mut dyn FnMut(&mut FormatSerializer) -> Result<(), FormatError>,
context: &dyn Context,
) -> Result<Raw, FormatError>;
fn with_deserializer(
&self,
data: &[u8],
f: &mut dyn FnMut(&mut FormatDeserializer) -> Result<(), FormatError>,
ctx: &mut BoxContext,
) -> Result<(), FormatError>;
fn clone_box(&self) -> Box<dyn Format>;
fn format_type_id(&self) -> FormatTypeId;
}
pub trait FormatExt: Format {
fn serialize<T>(&self, value: &T, context: &dyn Context) -> Result<Raw, FormatError>
where
T: Cacheable,
{
self.with_serializer(&mut |serializer| serializer.serialize(value), context)
}
fn deserialize<T>(&self, data: &Raw, ctx: &mut BoxContext) -> Result<T, FormatError>
where
T: Cacheable,
{
let mut result: Option<T> = None;
self.with_deserializer(
data,
&mut |deserializer| {
let value: T = deserializer.deserialize()?;
result = Some(value);
Ok(())
},
ctx,
)?;
result.ok_or_else(|| {
FormatError::Deserialize(Box::new(std::io::Error::other(
"deserialization produced no result",
)))
})
}
}
impl<T: Format + ?Sized> FormatExt for T {}
impl Clone for Box<dyn Format> {
fn clone(&self) -> Self {
self.clone_box()
}
}
impl Format for Box<dyn Format> {
fn with_serializer(
&self,
f: &mut dyn FnMut(&mut FormatSerializer) -> Result<(), FormatError>,
context: &dyn Context,
) -> Result<Raw, FormatError> {
(**self).with_serializer(f, context)
}
fn with_deserializer(
&self,
data: &[u8],
f: &mut dyn FnMut(&mut FormatDeserializer) -> Result<(), FormatError>,
ctx: &mut BoxContext,
) -> Result<(), FormatError> {
(**self).with_deserializer(data, f, ctx)
}
fn clone_box(&self) -> Box<dyn Format> {
(**self).clone_box()
}
fn format_type_id(&self) -> FormatTypeId {
(**self).format_type_id()
}
}
impl Format for std::sync::Arc<dyn Format> {
fn with_serializer(
&self,
f: &mut dyn FnMut(&mut FormatSerializer) -> Result<(), FormatError>,
context: &dyn Context,
) -> Result<Raw, FormatError> {
(**self).with_serializer(f, context)
}
fn with_deserializer(
&self,
data: &[u8],
f: &mut dyn FnMut(&mut FormatDeserializer) -> Result<(), FormatError>,
ctx: &mut BoxContext,
) -> Result<(), FormatError> {
(**self).with_deserializer(data, f, ctx)
}
fn clone_box(&self) -> Box<dyn Format> {
(**self).clone_box()
}
fn format_type_id(&self) -> FormatTypeId {
(**self).format_type_id()
}
}