use alloc::borrow::Cow;
use core::marker::PhantomData;
use core::ptr::NonNull;
use crate::State;
use crate::arena::ArenaBox;
use crate::de::{Deserialize, OwnedSink, Sink, SinkHandle, is_null_atom};
use crate::error::Error;
use crate::event::Atom;
trait Replace<'de>: Send {
fn sink(&mut self) -> &mut (dyn Sink<'de> + '_);
fn sink_ref(&self) -> &(dyn Sink<'de> + '_);
fn replace(&mut self);
}
struct Replacer<'a, 'de, T> {
out: &'a mut T,
sink: OwnedSink<'de, T>,
}
impl<'a, 'de, T: Send> Replace<'de> for Replacer<'a, 'de, T> {
fn sink(&mut self) -> &mut (dyn Sink<'de> + '_) {
self.sink.get_mut()
}
fn sink_ref(&self) -> &(dyn Sink<'de> + '_) {
self.sink.get()
}
fn replace(&mut self) {
if let Some(value) = self.sink.take() {
*self.out = value;
}
}
}
struct ReplaceSink<'a, 'de> {
inner: ArenaBox<dyn Replace<'de> + 'a>,
}
pub(crate) fn replace_handle_with<'a, 'de, T: Send + 'a>(
out: &'a mut T,
make: for<'x> fn(&'x mut Option<T>, &mut State) -> SinkHandle<'x, 'de>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
replace_with(out, OwnedSink::with(make, state), state)
}
pub fn checked_update<'a, 'de, T: Send + 'a>(
value: &'a mut T,
update: for<'x> fn(&'x mut T, &mut State) -> SinkHandle<'x, 'de>,
check: fn(&T) -> Result<(), Error>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
let ptr = NonNull::from(value);
let sink = update(unsafe { &mut *ptr.as_ptr() }, state);
SinkHandle::arena(
CheckedUpdateSink {
value: ptr,
sink: Some(sink),
check,
start: None,
_marker: PhantomData,
},
state,
)
}
struct CheckedUpdateSink<'a, 'de, T> {
value: NonNull<T>,
sink: Option<SinkHandle<'a, 'de>>,
check: fn(&T) -> Result<(), Error>,
start: Option<usize>,
_marker: PhantomData<&'a mut T>,
}
unsafe impl<T: Send> Send for CheckedUpdateSink<'_, '_, T> {}
impl<'a, 'de, T> CheckedUpdateSink<'a, 'de, T> {
fn sink(&mut self) -> &mut SinkHandle<'a, 'de> {
self.sink.as_mut().expect("update is complete")
}
fn begin(&mut self, state: &State) -> &mut SinkHandle<'a, 'de> {
if self.start.is_none() {
self.start = state.input_range().map(|x| x.start);
}
self.sink()
}
}
impl<'a, 'de, T: Send> Sink<'de> for CheckedUpdateSink<'a, 'de, T> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.begin(state).atom(atom, state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
self.begin(state).borrowed_atom(atom, state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.begin(state).map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
self.begin(state).seq(state)
}
fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.sink().next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.sink().next_value(state)
}
fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.sink().__private_key_atom(atom, state)
}
fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.sink().__private_value_atom(atom, state)
}
fn __private_borrowed_key_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.sink().__private_borrowed_key_atom(atom, state)
}
fn __private_borrowed_value_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.sink().__private_borrowed_value_atom(atom, state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
self.sink().value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
self.sink().recover(err, state)
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
let rv = self.sink().finish(state);
self.sink = None;
rv?;
let value = unsafe { self.value.as_ref() };
(self.check)(value).map_err(|mut err| {
if let (None, Some(start)) = (err.offset(), self.start) {
err.set_offset(start);
}
err
})
}
fn expecting(&self) -> Cow<'_, str> {
match self.sink {
Some(ref sink) => sink.expecting(),
None => Cow::Borrowed("compatible type"),
}
}
}
pub(crate) fn replace_with<'a, 'de, T: Send + 'a>(
out: &'a mut T,
sink: OwnedSink<'de, T>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
let inner = ArenaBox::into_raw(ArenaBox::new(Replacer { out, sink }, &mut state.arena));
let inner = unsafe { ArenaBox::from_raw(inner.as_ptr() as *mut (dyn Replace<'de> + 'a)) };
SinkHandle::arena(ReplaceSink { inner }, state)
}
impl<'a, 'de> Sink<'de> for ReplaceSink<'a, 'de> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().atom(atom, state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().borrowed_atom(atom, state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().seq(state)
}
fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.inner.get_mut().sink().next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.inner.get_mut().sink().next_value(state)
}
fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().__private_key_atom(atom, state)
}
fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.inner
.get_mut()
.sink()
.__private_value_atom(atom, state)
}
fn __private_borrowed_key_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.inner
.get_mut()
.sink()
.__private_borrowed_key_atom(atom, state)
}
fn __private_borrowed_value_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.inner
.get_mut()
.sink()
.__private_borrowed_value_atom(atom, state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
self.inner.get_mut().sink().value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().recover(err, state)
}
fn expecting(&self) -> Cow<'_, str> {
self.inner.get().sink_ref().expecting()
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
self.inner.get_mut().sink().finish(state)?;
self.inner.get_mut().replace();
Ok(())
}
}
struct OptionUpdateSink<'a, 'de, T> {
out: &'a mut Option<T>,
sink: OwnedSink<'de, T>,
}
pub(crate) fn update_option<'a, 'de, T: Send + 'a, A: Deserialize<'de, T>>(
out: &'a mut Option<T>,
state: &mut State,
) -> SinkHandle<'a, 'de> {
match out.take() {
Some(value) => SinkHandle::arena(
OptionUpdateSink {
out,
sink: OwnedSink::update(value, A::deserialize_update, state),
},
state,
),
None => replace_handle_with(
out,
<Option<A> as Deserialize<'de, Option<T>>>::deserialize_into,
state,
),
}
}
impl<'a, 'de, T: Send> Sink<'de> for OptionUpdateSink<'a, 'de, T> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
if is_null_atom(&atom) {
drop(self.sink.take());
return Ok(());
}
self.sink.get_mut().atom(atom, state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
if is_null_atom(&atom) {
drop(self.sink.take());
return Ok(());
}
self.sink.get_mut().borrowed_atom(atom, state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().seq(state)
}
forward_to_owned!(sink);
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().finish(state)?;
*self.out = self.sink.take();
Ok(())
}
}
impl<'a, 'de, T> Drop for OptionUpdateSink<'a, 'de, T> {
fn drop(&mut self) {
if let Some(value) = self.sink.take() {
*self.out = Some(value);
}
}
}
#[cfg(feature = "derive")]
#[doc(hidden)]
pub struct UpdateTarget<'a, T> {
ptr: core::ptr::NonNull<T>,
_marker: core::marker::PhantomData<&'a mut T>,
}
#[cfg(feature = "derive")]
unsafe impl<T: Send> Send for UpdateTarget<'_, T> {}
#[cfg(feature = "derive")]
impl<'a, T> UpdateTarget<'a, T> {
#[inline]
pub fn new(value: &'a mut T) -> UpdateTarget<'a, T> {
UpdateTarget {
ptr: core::ptr::NonNull::from(value),
_marker: core::marker::PhantomData,
}
}
#[inline]
pub fn as_ptr(&self) -> *mut T {
self.ptr.as_ptr()
}
}
pub(crate) trait Collection<T>: Sized + Send {
fn empty() -> Self;
fn add(&mut self, value: T) -> Result<(), Error>;
}
enum CollectTarget<'a, C> {
Slot(&'a mut Option<C>),
Value(&'a mut C),
}
struct CollectSink<'a, 'de, C, T, A> {
target: CollectTarget<'a, C>,
element: OwnedSink<'de, T>,
extend: bool,
_marker: PhantomData<fn() -> A>,
}
impl<'a, 'de, C: Collection<T>, T: Send> CollectSink<'a, 'de, C, T, ()> {
fn add(
target: &mut CollectTarget<'a, C>,
element: &mut OwnedSink<'de, T>,
) -> Result<(), Error> {
if let Some(value) = element.take() {
match *target {
CollectTarget::Slot(ref mut slot) => {
slot.get_or_insert_with(C::empty).add(value)?
}
CollectTarget::Value(ref mut collection) => collection.add(value)?,
}
}
Ok(())
}
}
impl<'a, 'de, C, T, A> Sink<'de> for CollectSink<'a, 'de, C, T, A>
where
C: Collection<T>,
T: Send,
A: Deserialize<'de, T>,
{
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.element.get_mut().atom(atom, state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
self.element.get_mut().borrowed_atom(atom, state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.element.get_mut().map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
match self.element.get_mut().seq(state) {
Err(err) if err.kind().is_rejection() => {
self.element = OwnedSink::null(state);
self.extend = true;
Ok(())
}
rv => rv,
}
}
fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.element.get_mut().next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
if self.extend {
CollectSink::<C, T, ()>::add(&mut self.target, &mut self.element)?;
self.element = OwnedSink::deserialize_as::<A>(state);
return Ok(SinkHandle::to(self.element.get_mut()));
}
self.element.get_mut().next_value(state)
}
fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.element.get_mut().__private_key_atom(atom, state)
}
fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
if self.extend {
return crate::de::atom_into_handle(self.next_value(state)?, atom, state);
}
self.element.get_mut().__private_value_atom(atom, state)
}
fn __private_borrowed_key_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.element
.get_mut()
.__private_borrowed_key_atom(atom, state)
}
fn __private_borrowed_value_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
if self.extend {
return crate::de::borrowed_atom_into_handle(self.next_value(state)?, atom, state);
}
self.element
.get_mut()
.__private_borrowed_value_atom(atom, state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
if self.extend {
return Ok(None);
}
self.element.get_mut().value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
if self.extend {
return Err(err);
}
self.element.get_mut().recover(err, state)
}
fn expecting(&self) -> Cow<'_, str> {
self.element.get().expecting()
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
if !self.extend {
self.element.get_mut().finish(state)?;
}
CollectSink::<C, T, ()>::add(&mut self.target, &mut self.element)
}
}
pub(crate) fn collect_into<'a, 'de, C, T, A>(
out: &'a mut Option<C>,
state: &mut State,
) -> SinkHandle<'a, 'de>
where
C: Collection<T> + 'a,
T: Send + 'a,
A: Deserialize<'de, T>,
{
let element = OwnedSink::deserialize_as::<A>(state);
unsafe {
SinkHandle::arena_unbounded(
CollectSink {
target: CollectTarget::Slot(out),
element,
extend: false,
_marker: PhantomData::<fn() -> A>,
},
state,
)
}
}
pub(crate) fn collect_update<'a, 'de, C, T, A>(
value: &'a mut C,
first: bool,
state: &mut State,
) -> SinkHandle<'a, 'de>
where
C: Collection<T> + 'a,
T: Send + 'a,
A: Deserialize<'de, T>,
{
if first {
*value = C::empty();
}
let element = OwnedSink::deserialize_as::<A>(state);
unsafe {
SinkHandle::arena_unbounded(
CollectSink {
target: CollectTarget::Value(value),
element,
extend: false,
_marker: PhantomData::<fn() -> A>,
},
state,
)
}
}