use std::cell::Cell;
use std::error;
use std::fmt;
use serde::de::{self, DeserializeSeed, Deserializer};
use serde::ser::{self, Serialize, SerializeMap, SerializeSeq, Serializer};
const TRANSLATION_FAILED: &str = "translation failed";
pub(crate) fn transcode<'de, S, D>(ser: S, de: D) -> Result<S::Ok, Error<S::Error, D::Error>>
where
S: Serializer,
D: Deserializer<'de>,
{
let mut visitor = Visitor(Exchange::new(ser));
de.deserialize_any(&mut visitor).map_err(|de_err| {
let (source, ser_err) = visitor.0.into_error();
if matches!(source, ErrorSource::Ser) {
debug_assert!(
ser_err.is_some(),
"ErrorSource::Ser should include a serializer error"
);
}
if let (ErrorSource::Ser, Some(ser_err)) = (source, ser_err) {
Error::Ser(ser_err, de_err)
} else {
Error::De(de_err)
}
})
}
#[derive(Debug)]
pub(crate) enum Error<S, D>
where
S: ser::Error,
D: de::Error,
{
Ser(S, D),
De(D),
}
impl<S, D> fmt::Display for Error<S, D>
where
S: ser::Error,
D: de::Error,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Ser(ser_err, de_err) => write!(f, "{de_err}: {ser_err}"),
Error::De(de_err) => fmt::Display::fmt(de_err, f),
}
}
}
impl<S, D> error::Error for Error<S, D>
where
S: ser::Error + 'static,
D: de::Error + 'static,
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Error::Ser(ser_err, _) => Some(ser_err),
Error::De(de_err) => Some(de_err),
}
}
}
#[derive(Clone, Copy)]
enum ErrorSource {
De,
Ser,
}
struct Exchange<P, E> {
parent: Cell<Option<P>>,
error: Cell<Option<E>>,
source: Cell<ErrorSource>,
}
impl<P, E> Exchange<P, E> {
fn new(parent: P) -> Exchange<P, E> {
Exchange {
parent: Cell::new(Some(parent)),
error: Cell::new(None),
source: Cell::new(ErrorSource::De),
}
}
fn take_parent(&self) -> P {
self.parent
.take()
.expect("Exchange should have its parent taken exactly once")
}
fn stash_error(&self, source: ErrorSource, error: E) {
self.source.set(source);
self.error.set(Some(error));
}
fn into_error(self) -> (ErrorSource, Option<E>) {
(self.source.get(), self.error.into_inner())
}
}
struct Visitor<S: Serializer>(Exchange<S, S::Error>);
impl<S: Serializer> Visitor<S> {
fn forward_scalar<F, E>(&mut self, serialize_with: F) -> Result<S::Ok, E>
where
F: FnOnce(S) -> Result<S::Ok, S::Error>,
E: de::Error,
{
let ser = self.0.take_parent();
serialize_with(ser).map_err(|ser_err| {
self.0.stash_error(ErrorSource::Ser, ser_err);
de::Error::custom(TRANSLATION_FAILED)
})
}
}
macro_rules! impl_forward_scalar_visitors {
( $( $name:ident($($arg:ident: $ty:ty)?) => $op:expr; )* ) => {
$(fn $name<E: de::Error>(self, $($arg: $ty)?) -> Result<Self::Value, E> {
self.forward_scalar($op)
})*
};
}
impl<'de, S: Serializer> de::Visitor<'de> for &mut Visitor<S> {
type Value = S::Ok;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("any supported value")
}
impl_forward_scalar_visitors! {
visit_unit() => |ser| ser.serialize_unit();
visit_bool(v: bool) => |ser| ser.serialize_bool(v);
visit_i8(v: i8) => |ser| ser.serialize_i8(v);
visit_i16(v: i16) => |ser| ser.serialize_i16(v);
visit_i32(v: i32) => |ser| ser.serialize_i32(v);
visit_i64(v: i64) => |ser| ser.serialize_i64(v);
visit_i128(v: i128) => |ser| ser.serialize_i128(v);
visit_u8(v: u8) => |ser| ser.serialize_u8(v);
visit_u16(v: u16) => |ser| ser.serialize_u16(v);
visit_u32(v: u32) => |ser| ser.serialize_u32(v);
visit_u64(v: u64) => |ser| ser.serialize_u64(v);
visit_u128(v: u128) => |ser| ser.serialize_u128(v);
visit_f32(v: f32) => |ser| ser.serialize_f32(v);
visit_f64(v: f64) => |ser| ser.serialize_f64(v);
visit_char(v: char) => |ser| ser.serialize_char(v);
visit_str(v: &str) => |ser| ser.serialize_str(v);
visit_bytes(v: &[u8]) => |ser| ser.serialize_bytes(v);
}
fn visit_seq<A: de::SeqAccess<'de>>(self, mut de: A) -> Result<Self::Value, A::Error> {
let parent = self.0.take_parent();
let mut seq = parent.serialize_seq(de.size_hint()).map_err(|ser_err| {
self.0.stash_error(ErrorSource::Ser, ser_err);
de::Error::custom(TRANSLATION_FAILED)
})?;
loop {
let mut seed = SeqSeed(Exchange::new(&mut seq));
match de.next_element_seed(&mut seed) {
Ok(None) => break,
Ok(Some(())) => {}
Err(de_err) => {
if let (source, Some(ser_err)) = seed.0.into_error() {
self.0.stash_error(source, ser_err);
}
return Err(de_err);
}
}
}
seq.end().map_err(|ser_err| {
self.0.stash_error(ErrorSource::Ser, ser_err);
de::Error::custom(TRANSLATION_FAILED)
})
}
fn visit_map<A: de::MapAccess<'de>>(self, mut de: A) -> Result<Self::Value, A::Error> {
let parent = self.0.take_parent();
let mut map = parent.serialize_map(de.size_hint()).map_err(|ser_err| {
self.0.stash_error(ErrorSource::Ser, ser_err);
de::Error::custom(TRANSLATION_FAILED)
})?;
loop {
let mut key_seed = KeySeed(Exchange::new(&mut map));
match de.next_key_seed(&mut key_seed) {
Ok(None) => break,
Ok(Some(())) => {}
Err(de_err) => {
if let (source, Some(ser_err)) = key_seed.0.into_error() {
self.0.stash_error(source, ser_err);
}
return Err(de_err);
}
}
let mut value_seed = ValueSeed(Exchange::new(&mut map));
if let Err(de_err) = de.next_value_seed(&mut value_seed) {
if let (source, Some(ser_err)) = value_seed.0.into_error() {
self.0.stash_error(source, ser_err);
}
return Err(de_err);
}
}
map.end().map_err(|ser_err| {
self.0.stash_error(ErrorSource::Ser, ser_err);
de::Error::custom(TRANSLATION_FAILED)
})
}
}
macro_rules! impl_seed_types {
( $( struct $name:ident ($trait:ident) => $x:expr; )* ) => {
$(struct $name<'ser, S: $trait>(Exchange<&'ser mut S, S::Error>);
impl<'de, 'ser, S: $trait> DeserializeSeed<'de> for &mut $name<'ser, S> {
type Value = ();
fn deserialize<D: Deserializer<'de>>(self, de: D) -> Result<(), D::Error> {
forward(de, &mut self.0, $x)
}
})*
};
}
impl_seed_types! {
struct SeqSeed(SerializeSeq) => |ser, elt| ser.serialize_element(elt);
struct KeySeed(SerializeMap) => |ser, key| ser.serialize_key(key);
struct ValueSeed(SerializeMap) => |ser, val| ser.serialize_value(val);
}
fn forward<'de, D, S, SErr, F>(
de: D,
ser_exchange: &mut Exchange<S, SErr>,
serialize: F,
) -> Result<(), D::Error>
where
D: Deserializer<'de>,
F: FnOnce(S, &mut Forwarder<'de, D>) -> Result<(), SErr>,
{
let ser = ser_exchange.take_parent();
let mut forwarder = Forwarder(Exchange::new(de));
serialize(ser, &mut forwarder).map_err(|ser_err| {
let (source, de_err) = forwarder.0.into_error();
ser_exchange.stash_error(source, ser_err);
de_err.unwrap_or_else(|| de::Error::custom(TRANSLATION_FAILED))
})
}
struct Forwarder<'de, D: Deserializer<'de>>(Exchange<D, D::Error>);
impl<'de, D: Deserializer<'de>> Serialize for Forwarder<'de, D> {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
let de = self.0.take_parent();
let mut visitor = Visitor(Exchange::new(ser));
de.deserialize_any(&mut visitor).map_err(|de_err| {
let (source, ser_err) = visitor.0.into_error();
self.0.stash_error(source, de_err);
ser_err.unwrap_or_else(|| ser::Error::custom(TRANSLATION_FAILED))
})
}
}