use std::borrow::Cow;
use std::marker::PhantomData;
use deser_core::adapters::Same;
use deser_core::de::{OwnedSink, Sink, SinkHandle, checked_update};
use deser_core::ser::{Describe, Emit};
use deser_core::{Atom, ContainerShape, Deserialize, Error, Serialize, State};
use crate::{Validator, Violation};
pub struct Check<V, A = Same>(PhantomData<fn() -> (V, A)>);
impl<'de, T, V, A> Deserialize<'de, T> for Check<V, A>
where
T: Send,
V: Validator<T> + 'static,
A: Deserialize<'de, T>,
{
fn deserialize_into<'out>(
out: &'out mut Option<T>,
state: &mut State,
) -> SinkHandle<'out, 'de> {
SinkHandle::arena(
CheckSink::<T, V> {
out,
sink: OwnedSink::deserialize_as::<A>(state),
start: None,
_validator: PhantomData,
},
state,
)
}
fn expecting() -> Cow<'static, str> {
A::expecting()
}
fn describe_type(d: &mut dyn Describe) {
A::describe_type(d)
}
fn initial_value() -> Option<T> {
A::initial_value().filter(|value| V::validate(value).is_ok())
}
fn deserialize_update<'out>(value: &'out mut T, state: &mut State) -> SinkHandle<'out, 'de> {
checked_update(
value,
A::deserialize_update,
|value| V::validate(value).map_err(Violation::into_error),
state,
)
}
#[inline]
fn __private_atom_into(
out: &mut Option<T>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
A::__private_atom_into(out, atom, state)?;
validate_slot::<T, V>(out)
}
#[inline]
fn __private_borrowed_atom_into(
out: &mut Option<T>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
A::__private_borrowed_atom_into(out, atom, state)?;
validate_slot::<T, V>(out)
}
}
fn validate_slot<T, V: Validator<T>>(slot: &mut Option<T>) -> Result<(), Error> {
if let Some(ref value) = *slot
&& let Err(violation) = V::validate(value)
{
*slot = None;
return Err(violation.into_error());
}
Ok(())
}
impl<T: ?Sized, V: 'static, A: Serialize<T>> Serialize<T> for Check<V, A> {
fn serialize<'a>(value: &'a T, state: &mut State) -> Result<Emit<'a>, Error> {
A::serialize(value, state)
}
fn finish(value: &T, state: &mut State) -> Result<(), Error> {
A::finish(value, state)
}
fn is_optional(value: &T) -> bool {
A::is_optional(value)
}
fn container_shape(value: &T) -> ContainerShape {
A::container_shape(value)
}
fn describe(value: &T, d: &mut dyn Describe) {
A::describe(value, d)
}
}
struct CheckSink<'a, 'de, T, V> {
out: &'a mut Option<T>,
sink: OwnedSink<'de, T>,
start: Option<usize>,
_validator: PhantomData<fn() -> V>,
}
impl<'a, 'de, T, V> CheckSink<'a, 'de, T, V> {
fn begin(&mut self, state: &State) -> &mut (dyn Sink<'de> + '_) {
self.start = state.input_range().map(|range| range.start);
self.sink.get_mut()
}
}
impl<'a, 'de, T: Send, V: Validator<T>> Sink<'de> for CheckSink<'a, 'de, T, V> {
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.get_mut().next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.sink.get_mut().next_value(state)
}
fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().__private_key_atom(atom, state)
}
fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().__private_value_atom(atom, state)
}
fn __private_borrowed_key_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.sink.get_mut().__private_borrowed_key_atom(atom, state)
}
fn __private_borrowed_value_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.sink
.get_mut()
.__private_borrowed_value_atom(atom, state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
self.sink.get_mut().value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().recover(err, state)
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
self.sink.get_mut().finish(state)?;
if let Some(value) = self.sink.take() {
if let Err(violation) = V::validate(&value) {
let mut err = violation.into_error();
if let Some(start) = self.start {
err.set_offset(start);
}
return Err(err);
}
*self.out = Some(value);
}
Ok(())
}
fn expecting(&self) -> Cow<'_, str> {
self.sink.get().expecting()
}
}