use alloc::borrow::Cow;
use alloc::format;
use alloc::vec::Vec;
use core::marker::PhantomData;
use crate::BytesFormat;
use crate::State;
use crate::adapters::bytes::BytesEncoding;
use crate::de::{Deserialize, Sink, SinkHandle, default_atom};
use crate::error::{Error, ErrorKind};
use crate::event::{Atom, Bytes, ContainerShape};
use crate::ser::{Begin, Emit, Serialize};
mod sealed {
use super::*;
pub trait BytesBufImpl: Sized + Send + Sync {
fn bytes(&self) -> &[u8];
fn from_vec(bytes: Vec<u8>) -> Result<Self, Error>;
fn deserialize_into<'a, 'de>(
out: &'a mut Option<Self>,
state: &mut State,
) -> SinkHandle<'a, 'de>;
fn expecting() -> Cow<'static, str>;
}
pub trait BytesFallbackFormatImpl: Send + Sync + 'static {
const FORMAT: BytesFormat;
fn deserialize_into<'a, 'de, T: BytesBufImpl>(
out: &'a mut Option<T>,
state: &mut State,
) -> SinkHandle<'a, 'de>;
fn expecting<T: BytesBufImpl>() -> Cow<'static, str>;
}
}
pub(crate) use self::sealed::BytesBufImpl;
use self::sealed::BytesFallbackFormatImpl;
pub trait BytesBuf: BytesBufImpl {}
impl<T: BytesBufImpl> BytesBuf for T {}
impl BytesBufImpl for Vec<u8> {
#[inline]
fn bytes(&self) -> &[u8] {
self
}
#[inline]
fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
Ok(bytes)
}
#[inline]
fn deserialize_into<'a, 'de>(
out: &'a mut Option<Self>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
<Self as Deserialize<'de>>::deserialize_into(out, state)
}
fn expecting() -> Cow<'static, str> {
<Self as Deserialize<'static>>::expecting()
}
}
impl<const N: usize> BytesBufImpl for [u8; N] {
#[inline]
fn bytes(&self) -> &[u8] {
self
}
fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
bytes
.try_into()
.map_err(|_| Error::new(ErrorKind::WrongLength, "byte array of wrong length"))
}
#[inline]
fn deserialize_into<'a, 'de>(
out: &'a mut Option<Self>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
<Self as Deserialize<'de>>::deserialize_into(out, state)
}
fn expecting() -> Cow<'static, str> {
<Self as Deserialize<'static>>::expecting()
}
}
impl<'c> BytesBufImpl for Cow<'c, [u8]> {
#[inline]
fn bytes(&self) -> &[u8] {
self
}
#[inline]
fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
Ok(Cow::Owned(bytes))
}
#[inline]
fn deserialize_into<'a, 'de>(
out: &'a mut Option<Self>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
<Self as Deserialize<'de>>::deserialize_into(out, state)
}
fn expecting() -> Cow<'static, str> {
<Self as Deserialize<'static>>::expecting()
}
}
pub trait BytesFallbackFormat: BytesFallbackFormatImpl {}
impl<F: BytesFallbackFormatImpl> BytesFallbackFormat for F {}
impl<E: BytesEncoding> BytesFallbackFormatImpl for E {
const FORMAT: BytesFormat = BytesFormat::encoded::<E>();
#[inline]
fn deserialize_into<'a, 'de, T: BytesBufImpl>(
out: &'a mut Option<T>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
encoded_handle::<T, E>(out, state)
}
fn expecting<T: BytesBufImpl>() -> Cow<'static, str> {
encoded_expecting::<E>()
}
}
pub struct IntSeq;
impl BytesFallbackFormatImpl for IntSeq {
const FORMAT: BytesFormat = BytesFormat::SEQ;
#[inline]
fn deserialize_into<'a, 'de, T: BytesBufImpl>(
out: &'a mut Option<T>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
T::deserialize_into(out, state)
}
fn expecting<T: BytesBufImpl>() -> Cow<'static, str> {
T::expecting()
}
}
pub(crate) fn encoded_expecting<E: BytesEncoding>() -> Cow<'static, str> {
Cow::Owned(format!("bytes or {} string", E::NAME))
}
struct EncodedSink<'a, T, E> {
out: &'a mut Option<T>,
_marker: PhantomData<fn() -> E>,
}
impl<'a, 'de, T: BytesBufImpl, E: BytesEncoding> Sink<'de> for EncodedSink<'a, T, E> {
fn expecting(&self) -> Cow<'_, str> {
encoded_expecting::<E>()
}
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
let bytes = match atom {
Atom::Bytes(value) => value.into_data().into_owned(),
Atom::Str(value) => E::decode(&value)?,
other => return default_atom(self, other, state),
};
*self.out = Some(T::from_vec(bytes)?);
Ok(())
}
}
#[inline]
pub(crate) fn encoded_handle<'a, 'de, T: BytesBufImpl, E: BytesEncoding>(
out: &'a mut Option<T>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
SinkHandle::arena(
EncodedSink::<T, E> {
out,
_marker: PhantomData,
},
state,
)
}
macro_rules! encoding_adapter {
($([$($gen:tt)*] $ty:ty),* $(,)?) => {
$(
impl<$($gen)* E: $crate::adapters::BytesEncoding> $crate::ser::Serialize<$ty> for E {
fn serialize<'a>(
value: &'a $ty,
_state: &mut $crate::State,
) -> Result<$crate::ser::Emit<'a>, $crate::Error> {
let mut rv = alloc::string::String::new();
E::encode(
$crate::adapters::bytes::BytesBufImpl::bytes(value),
&mut rv,
);
Ok($crate::ser::Emit::Atom($crate::Atom::Str($crate::Text::owned(rv))))
}
#[doc(hidden)]
#[inline]
fn __private_begin<'a>(
value: &'a $ty,
state: &mut $crate::State,
) -> Result<$crate::ser::Begin<'a>, $crate::Error> {
Ok($crate::ser::Begin::emit(
Self::serialize(value, state)?,
$crate::ContainerShape::new(),
false,
))
}
}
impl<'de, $($gen)* E: $crate::adapters::BytesEncoding>
$crate::de::Deserialize<'de, $ty> for E
{
#[inline]
fn deserialize_into<'a>(
out: &'a mut Option<$ty>, state: &mut $crate::State) -> $crate::de::SinkHandle<'a, 'de> {
$crate::adapters::bytes::encoded_handle::<$ty, E>(out, state)
}
fn expecting() -> alloc::borrow::Cow<'static, str> {
$crate::adapters::bytes::encoded_expecting::<E>()
}
}
)*
};
}
#[allow(unused_imports)]
pub(crate) use encoding_adapter;
encoding_adapter!(
[] Vec<u8>,
[const N: usize,] [u8; N],
['c,] Cow<'c, [u8]>,
);
pub struct BytesFallback<F>(PhantomData<fn() -> F>);
impl<T: BytesBuf, F: BytesFallbackFormat> Serialize<T> for BytesFallback<F> {
#[inline]
fn serialize<'a>(value: &'a T, _state: &mut State) -> Result<Emit<'a>, Error> {
let mut bytes = Bytes::borrowed(value.bytes());
bytes.fallback = Some(const { &F::FORMAT });
Ok(Emit::Atom(Atom::Bytes(bytes)))
}
#[inline]
fn __private_begin<'a>(value: &'a T, state: &mut State) -> Result<Begin<'a>, Error> {
Ok(Begin::emit(
Self::serialize(value, state)?,
ContainerShape::new(),
false,
))
}
}
impl<'de, T: BytesBuf, F: BytesFallbackFormat> Deserialize<'de, T> for BytesFallback<F> {
#[inline]
fn deserialize_into<'out>(
out: &'out mut Option<T>,
state: &mut State,
) -> SinkHandle<'out, 'de> {
F::deserialize_into(out, state)
}
fn expecting() -> Cow<'static, str> {
F::expecting::<T>()
}
}