Created
February 12, 2023 12:29
-
-
Save tesaguri/e45f1a829fe7bbb74bf009312c37d82f to your computer and use it in GitHub Desktop.
An (unsuccessful) attempt to deserialize async response body using a type-erased `DeserializeSeed` impl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "erased-deserialize-seed-test" | |
version = "0.0.0" | |
edition = "2021" | |
publish = false | |
[dependencies] | |
erased-serde = "0.3" | |
serde = "1" | |
serde_json = "1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub mod erased { | |
use serde::de; | |
pub trait DeserializeSeed<'de> { | |
type Value; | |
fn erased_deserialize( | |
&mut self, | |
deserializer: &mut dyn erased_serde::Deserializer<'de>, | |
) -> erased_serde::Result<Self::Value>; | |
} | |
pub fn erase_seed<'de, T: de::DeserializeSeed<'de>>( | |
seed: T, | |
) -> self::erase::DeserializeSeed<T> { | |
self::erase::DeserializeSeed { state: Some(seed) } | |
} | |
mod erase { | |
use serde::de; | |
pub struct DeserializeSeed<D> { | |
state: Option<D>, | |
} | |
impl<'de, D: de::DeserializeSeed<'de>> super::DeserializeSeed<'de> for DeserializeSeed<D> { | |
type Value = D::Value; | |
fn erased_deserialize( | |
&mut self, | |
deserializer: &mut dyn erased_serde::Deserializer<'de>, | |
) -> erased_serde::Result<Self::Value> { | |
de::DeserializeSeed::deserialize(self.state.take().unwrap(), deserializer) | |
.map_err(de::Error::custom) | |
} | |
} | |
} | |
impl<'de, T> de::DeserializeSeed<'de> for &mut dyn DeserializeSeed<'de, Value = T> { | |
type Value = T; | |
fn deserialize<D: de::Deserializer<'de>>(self, deserializer: D) -> Result<T, D::Error> { | |
let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer); | |
self.erased_deserialize(&mut erased) | |
.map_err(de::Error::custom) | |
} | |
} | |
} | |
pub mod response { | |
use core::future::Future; | |
use core::marker::Unpin; | |
use core::pin::Pin; | |
use core::task::{Context, Poll}; | |
use serde::de; | |
pub struct ResponseFuture<T> { | |
seed: Option<T>, | |
} | |
impl<T: for<'de> de::DeserializeSeed<'de> + Unpin> ResponseFuture<T> { | |
pub fn new(seed: T) -> Self { | |
Self { seed: Some(seed) } | |
} | |
} | |
impl<T: for<'de> de::DeserializeSeed<'de> + Unpin> Future for ResponseFuture<T> { | |
type Output = Result<<T as de::DeserializeSeed<'static>>::Value, serde_json::Error>; | |
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { | |
let body = "null"; | |
let mut deserializer = serde_json::Deserializer::from_str(body); | |
let response = self.seed.take().unwrap().deserialize(&mut deserializer)?; | |
Poll::Ready(Ok(response)) | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use serde::de; | |
use crate::erased; | |
use crate::response::ResponseFuture; | |
struct DeserializeSeedImpl; | |
impl<'de> de::DeserializeSeed<'de> for DeserializeSeedImpl { | |
type Value = (); | |
fn deserialize<D: de::Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> { | |
<de::IgnoredAny as de::Deserialize>::deserialize(d).map(|_| {}) | |
} | |
} | |
fn it_works() { | |
let mut seed = erased::erase_seed(DeserializeSeedImpl); | |
let response: ResponseFuture<&mut dyn erased::DeserializeSeed<Value = ()>> = | |
ResponseFuture::new(&mut seed); | |
//~^ ERROR implementation of `serde::de::DeserializeSeed` is not general enough | |
let _ = async move { | |
response.await.unwrap() | |
//~^ ERROR implementation of `serde::de::DeserializeSeed` is not general enough | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment