use alloc::borrow::Cow;
use alloc::vec::Vec;
use core::any::Any;
use core::fmt;
use core::marker::PhantomData;
use crate::State;
use crate::adapters::Borrowed;
use crate::de::recording::Capture;
use crate::de::{Deserialize, DeserializeDriver, RecordBuf, Sink, SinkHandle};
use crate::error::{Error, ErrorKind};
use crate::event::Atom;
use crate::ext::{BorrowedExtension, ExtValue};
use crate::ser::{Emit, Serialize, SerializeHandle, SerializeRef};
pub trait RawFormat: 'static {
fn info() -> &'static RawFormatInfo;
}
pub unsafe trait TextRawFormat: RawFormat {}
pub struct RawFormatId {
name: &'static str,
is_text: bool,
}
impl RawFormatId {
pub const fn new(name: &'static str, is_text: bool) -> RawFormatId {
RawFormatId { name, is_text }
}
pub fn name(&self) -> &'static str {
self.name
}
pub fn is_text(&self) -> bool {
self.is_text
}
}
impl fmt::Debug for RawFormatId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("RawFormatId").field(&self.name).finish()
}
}
pub struct RawFormatInfo {
id: &'static RawFormatId,
replay: for<'de> fn(&'de [u8], &mut DeserializeDriver<'_, 'de>) -> Result<(), Error>,
encode: fn(SerializeRef<'_>) -> Result<Vec<u8>, Error>,
fallback: for<'v> fn(&'v [u8]) -> Atom<'v>,
data: Option<&'static (dyn Any + Send + Sync)>,
}
impl RawFormatInfo {
pub const fn new(
id: &'static RawFormatId,
replay: for<'de> fn(&'de [u8], &mut DeserializeDriver<'_, 'de>) -> Result<(), Error>,
encode: fn(SerializeRef<'_>) -> Result<Vec<u8>, Error>,
fallback: for<'v> fn(&'v [u8]) -> Atom<'v>,
) -> RawFormatInfo {
RawFormatInfo {
id,
replay,
encode,
fallback,
data: None,
}
}
pub const fn set_data(&mut self, data: &'static (dyn Any + Send + Sync)) {
self.data = Some(data);
}
pub fn data(&self) -> Option<&'static (dyn Any + Send + Sync)> {
self.data
}
pub fn id(&self) -> &'static RawFormatId {
self.id
}
pub fn name(&self) -> &'static str {
self.id.name
}
pub fn is_text(&self) -> bool {
self.id.is_text
}
fn record<'a>(&self, bytes: &'a [u8]) -> Result<RecordBuf<'a>, Error> {
let mut recording = RecordBuf::new();
{
let mut driver = DeserializeDriver::from_fn(|state| recording.recorder(state));
(self.replay)(bytes, &mut driver)?;
}
Ok(recording)
}
}
impl fmt::Debug for RawFormatInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("RawFormatInfo").field(&self.id.name).finish()
}
}
#[inline(always)]
fn same_format(a: &'static RawFormatInfo, b: &'static RawFormatInfo) -> bool {
core::ptr::eq(a.id, b.id)
}
#[derive(Clone)]
pub struct RawInput<'a> {
bytes: Cow<'a, [u8]>,
format: &'static RawFormatInfo,
}
impl<'a> RawInput<'a> {
pub unsafe fn new<B: Into<Cow<'a, [u8]>>>(
bytes: B,
format: &'static RawFormatInfo,
) -> RawInput<'a> {
let bytes = bytes.into();
debug_assert!(!format.is_text() || core::str::from_utf8(&bytes).is_ok());
RawInput { bytes, format }
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn as_str(&self) -> Option<&str> {
self.format
.is_text()
.then(|| unsafe { core::str::from_utf8_unchecked(&self.bytes) })
}
pub fn format(&self) -> &'static RawFormatInfo {
self.format
}
pub fn is<F: RawFormat>(&self) -> bool {
same_format(self.format, F::info())
}
pub fn is_format(&self, id: &'static RawFormatId) -> bool {
core::ptr::eq(self.format.id, id)
}
pub fn into_owned(self) -> RawInput<'static> {
RawInput {
bytes: Cow::Owned(self.bytes.into_owned()),
format: self.format,
}
}
pub fn record(&self) -> Result<RecordBuf<'_>, Error> {
self.format.record(&self.bytes)
}
pub fn replay<'x>(&'x self, sink: SinkHandle<'_, 'x>, state: &mut State) -> Result<(), Error> {
self.replay_raw(sink, None, state)
}
fn replay_raw<'x>(
&'x self,
sink: SinkHandle<'_, 'x>,
raw: Option<&'static RawFormatInfo>,
state: &mut State,
) -> Result<(), Error> {
DeserializeDriver::nested(state, sink, false, |driver| {
driver.state_mut().raw_requested = raw;
(self.format.replay)(&self.bytes, driver)
})
}
pub fn deserialize<'x, T: Deserialize<'x>>(&'x self) -> Result<T, Error> {
crate::de::deserialize_value(|driver| (self.format.replay)(&self.bytes, driver))
}
}
pub(crate) fn parse_into<'de>(
input: &RawInput<'_>,
sink: &mut (dyn Sink<'de> + '_),
state: &mut State,
) -> Result<(), Error> {
let mut sink = NoFinish(sink);
DeserializeDriver::nested(state, SinkHandle::to(&mut sink), false, |driver| {
driver.state_mut().raw_requested = None;
driver.transient(|driver| (input.format.replay)(&input.bytes, driver))
})
}
struct NoFinish<'a, 'b, 'de>(&'a mut (dyn Sink<'de> + 'b));
impl<'de> Sink<'de> for NoFinish<'_, '_, 'de> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.0.atom(atom, state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
self.0.borrowed_atom(atom, state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.0.map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
self.0.seq(state)
}
fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.0.next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.0.next_value(state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
self.0.value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
self.0.recover(err, state)
}
fn expecting(&self) -> Cow<'_, str> {
self.0.expecting()
}
fn finish(&mut self, _state: &mut State) -> Result<(), Error> {
Ok(())
}
}
impl fmt::Debug for RawInput<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut debug = f.debug_struct("RawInput");
debug.field("format", &self.format.id.name);
match self.as_str() {
Some(text) => debug.field("text", &text),
None => debug.field("bytes", &self.bytes),
};
debug.finish()
}
}
impl PartialEq for RawInput<'_> {
fn eq(&self, other: &Self) -> bool {
same_format(self.format, other.format) && self.bytes == other.bytes
}
}
impl BorrowedExtension for RawInput<'static> {
type Value<'a> = RawInput<'a>;
fn name<'v>(_value: &'v RawInput<'_>) -> &'v str {
"raw value"
}
fn fallback<'v>(value: &'v RawInput<'_>) -> Atom<'v> {
(value.format.fallback)(&value.bytes)
}
fn to_static(value: &RawInput<'_>) -> RawInput<'static> {
value.clone().into_owned()
}
fn shorten<'s, 'l: 's>(value: &'s RawInput<'l>) -> &'s RawInput<'s> {
value
}
}
fn serialize_input<'a>(input: &'a RawInput<'_>, state: &mut State) -> Result<Emit<'a>, Error> {
if state.accepts_raw(input.format) {
return Ok(Emit::Atom(Atom::Ext(ExtValue::borrowed_value::<RawInput>(
input,
))));
}
Ok(Emit::Forward(SerializeHandle::arena(
input.record()?,
state,
)))
}
pub(crate) fn serialize_recorded_atom<'a>(
atom: &'a Atom<'_>,
state: &mut State,
) -> Result<Emit<'a>, Error> {
if let Atom::Ext(ext) = atom
&& let Some(input) = ext.downcast_value_ref::<RawInput>()
{
return serialize_input(input, state);
}
Ok(Emit::Atom(atom.as_borrowed()))
}
pub struct Raw<'a, F: RawFormat> {
input: RawInput<'a>,
_format: PhantomData<fn() -> F>,
}
impl<'a, F: RawFormat> Raw<'a, F> {
pub fn new<B: Into<Cow<'a, [u8]>>>(bytes: B) -> Result<Raw<'a, F>, Error> {
let bytes = bytes.into();
let info = F::info();
if info.is_text() && core::str::from_utf8(&bytes).is_err() {
return Err(Error::new(ErrorKind::Syntax, "invalid utf-8"));
}
{
let mut driver = DeserializeDriver::from_fn(|_| SinkHandle::null());
(info.replay)(&bytes, &mut driver)?;
}
Ok(Raw::from_input(unsafe { RawInput::new(bytes, info) }))
}
pub fn encode<T: Serialize + ?Sized>(value: &T) -> Result<Raw<'static, F>, Error> {
let info = F::info();
let bytes = (info.encode)(SerializeRef::new(&value))?;
if info.is_text() && core::str::from_utf8(&bytes).is_err() {
return Err(Error::new(
ErrorKind::InvalidState,
"the encoding of a text format is not utf-8",
));
}
Ok(Raw::from_input(unsafe { RawInput::new(bytes, info) }))
}
fn from_input(input: RawInput<'a>) -> Raw<'a, F> {
debug_assert!(input.is::<F>());
Raw {
input,
_format: PhantomData,
}
}
pub fn as_bytes(&self) -> &[u8] {
&self.input.bytes
}
pub fn is_borrowed(&self) -> bool {
matches!(self.input.bytes, Cow::Borrowed(_))
}
pub fn replay<'x>(&'x self, sink: SinkHandle<'_, 'x>, state: &mut State) -> Result<(), Error> {
self.input.replay(sink, state)
}
pub fn deserialize<'x, T: Deserialize<'x>>(&'x self) -> Result<T, Error> {
self.input.deserialize()
}
pub fn into_owned(self) -> Raw<'static, F> {
Raw::from_input(self.input.into_owned())
}
#[inline(never)]
fn from_atom(atom: Atom<'_>, state: &State) -> Result<Raw<'static, F>, Error> {
if let Atom::Ext(ref ext) = atom
&& let Some(input) = ext.downcast_value_ref::<RawInput>()
{
if input.is::<F>() {
return Ok(Raw::from_input(input.clone().into_owned()));
}
return Raw::encode(&input.record()?);
}
let mut recording = RecordBuf::new();
recording.set_atom(&atom, state);
Raw::encode(&recording)
}
}
impl<'de, F: RawFormat> Raw<'de, F> {
#[inline(never)]
fn from_borrowed_atom(atom: Atom<'de>, state: &State) -> Result<Raw<'de, F>, Error> {
if let Atom::Ext(ref ext) = atom {
if let Some(input) = unsafe { ext.downcast_value_ref_covariant::<RawInput>() }
&& input.is::<F>()
{
return Ok(Raw::from_input(input.clone()));
}
}
Raw::from_atom(atom, state)
}
}
impl<F: TextRawFormat> Raw<'_, F> {
pub fn get(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(&self.input.bytes) }
}
}
impl<F: RawFormat> Clone for Raw<'_, F> {
fn clone(&self) -> Self {
Raw::from_input(self.input.clone())
}
}
impl<F: RawFormat> fmt::Debug for Raw<'_, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut debug = f.debug_tuple("Raw");
debug.field(&self.input.format.id.name);
match self.input.as_str() {
Some(text) => debug.field(&text),
None => debug.field(&self.input.bytes),
};
debug.finish()
}
}
impl<F: RawFormat> PartialEq for Raw<'_, F> {
fn eq(&self, other: &Self) -> bool {
self.input.bytes == other.input.bytes
}
}
impl<F: RawFormat> Eq for Raw<'_, F> {}
impl<F: RawFormat> core::hash::Hash for Raw<'_, F> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.input.bytes.hash(state)
}
}
impl<F: RawFormat> Serialize for Raw<'_, F> {
fn serialize<'a>(value: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
serialize_input(&value.input, state)
}
}
impl<'de, 'a, F: RawFormat> Deserialize<'de> for Raw<'a, F> {
fn deserialize_into<'out>(
out: &'out mut Option<Self>,
state: &mut State,
) -> SinkHandle<'out, 'de> {
RecordBuf::capture_with(RawCapture(out), state)
}
fn expecting() -> Cow<'static, str> {
Cow::Borrowed("any value")
}
#[inline]
fn __private_atom_into(
out: &mut Option<Self>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
*out = Some(Raw::from_atom(atom, state)?);
Ok(())
}
#[inline]
fn __private_borrowed_atom_into(
out: &mut Option<Self>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
*out = Some(Raw::from_atom(atom, state)?);
Ok(())
}
#[inline(always)]
fn __private_raw() -> Option<&'static RawFormatInfo> {
Some(F::info())
}
}
impl<'de: 'a, 'a, F: RawFormat> Deserialize<'de, Raw<'a, F>> for Borrowed {
fn deserialize_into<'out>(
out: &'out mut Option<Raw<'a, F>>,
state: &mut State,
) -> SinkHandle<'out, 'de> {
RecordBuf::capture_with(BorrowedRawCapture(out), state)
}
fn expecting() -> Cow<'static, str> {
Cow::Borrowed("any value")
}
#[inline]
fn __private_atom_into(
out: &mut Option<Raw<'a, F>>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
*out = Some(Raw::from_atom(atom, state)?);
Ok(())
}
#[inline]
fn __private_borrowed_atom_into(
out: &mut Option<Raw<'a, F>>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
*out = Some(Raw::from_borrowed_atom(atom, state)?);
Ok(())
}
#[inline(always)]
fn __private_raw() -> Option<&'static RawFormatInfo> {
Some(F::info())
}
}
impl<'a, F: RawFormat> Serialize<Raw<'a, F>> for Borrowed {
fn serialize<'x>(value: &'x Raw<'a, F>, state: &mut State) -> Result<Emit<'x>, Error> {
<Raw<'a, F>>::serialize(value, state)
}
}
struct RawCapture<'o, 'a, F: RawFormat>(&'o mut Option<Raw<'a, F>>);
impl<'o, 'a, 'de, F: RawFormat> Capture<'de, RecordBuf<'de>> for RawCapture<'o, 'a, F> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
*self.0 = Some(Raw::from_atom(atom, state)?);
Ok(())
}
fn recorded(&mut self, recording: RecordBuf<'de>, _state: &mut State) -> Result<(), Error> {
*self.0 = Some(Raw::encode(&recording)?);
Ok(())
}
}
struct BorrowedRawCapture<'o, 'a, F: RawFormat>(&'o mut Option<Raw<'a, F>>);
impl<'o, 'a, 'de: 'a, F: RawFormat> Capture<'de, RecordBuf<'de>> for BorrowedRawCapture<'o, 'a, F> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
*self.0 = Some(Raw::from_atom(atom, state)?);
Ok(())
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
*self.0 = Some(Raw::from_borrowed_atom(atom, state)?);
Ok(())
}
fn recorded(&mut self, recording: RecordBuf<'de>, _state: &mut State) -> Result<(), Error> {
*self.0 = Some(Raw::encode(&recording)?);
Ok(())
}
}