Unfortunately I can think of no better title. I'm currently exploring serde by making a toy Deserializer that is generic over Deserializer. Basically just a wrapper based instrumentation/logging for exploration. My first attempt was to "wrap" a JSON Deserializer which raised a bunch of questions. Specifically, Deserializer is implemented on a mutable borrow of serde_json's Deserializer struct and I've found myself unable to properly "wrap" that in a way that makes the compiler happy, and the way I've structured things "delegating" to the wrapped Deserializer wants to move that deserializer as Deserializer<'de> does not implement copy.
Here's what I'm working with (serde 1.0 and serde_json 1.0):
My wrapper:
pub struct Wrapper<'a, D> {
de: &'a mut D,
}
impl<'a, 'de, D: 'de> Wrapper<'a, D>
where
D: Deserializer<'de>,
{
pub fn new(de: &'a mut D) -> Self {
Wrapper { de }
}
}
impl<'a, 'de, D> Deserializer<'de> for &mut Wrapper<'a, D>
where
D: Deserializer<'de>,
{
type Error = crate::Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.de
.deserialize_any(visitor)
.map_err(|e| crate::Error::Custom("deserialize_any".into()))
}
...
...
}
It's compiler error:
error[E0507]: cannot move out of `*self.de` which is behind a mutable reference
--> src/deserializer.rs:30:9
|
30 | / self.de
31 | | .deserialize_any(visitor)
| | -----------------------^
| |______________|______________________|
| | move occurs because `*self.de` has type `D`, which does not implement the `Copy` trait
| `*self.de` moved due to this method call
|
note: this function takes ownership of the receiver `self`, which moves `*self.de`
--> /home/sean/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.154/src/de/mod.rs:919:27
|
919 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
| ^^^^
My attempted call site:
let mut de = serde_json::Deserializer::from_str(input);
let wrap = Wrapper::new(&mut de);
It's compiler error:
error[E0277]: the trait bound `serde_json::Deserializer<StrRead<'_>>: types::_::_serde::Deserializer<'_>` is not satisfied
--> src/deserializer.rs:284:32
|
284 | let wrap = Wrapper::new(&mut de);
| ------------ ^^^^^^^ the trait `types::_::_serde::Deserializer<'_>` is not implemented for `serde_json::Deserializer<StrRead<'_>>`
| |
| required by a bound introduced by this call
|
= help: the trait `types::_::_serde::Deserializer<'de>` is implemented for `&'a mut serde_json::Deserializer<R>`
note: required by a bound in `Wrapper::<'a, D>::new`
--> src/deserializer.rs:13:8
|
13 | D: Deserializer<'de>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `Wrapper::<'a, D>::new`
14 | {
15 | pub fn new(de: &'a mut D) -> Self {
| --- required by a bound in this
I feel like I generally understand what these error messages are saying, but at this point I've been tinkering with it for so long I've confused myself with what's actually going on.
My specific questions:
- I'm curious how (or if) it's possible to satisfy the
Deserializer<'de>
trait bound with something like serde_json's deserializer that only implementsDeserializer<'de>
on a mutable borrow. - When attempting to be generic over a trait such as
Deserializer<'de>
that does not implement Copy, how does one signal to the compiler that it's a reference? - Is this pattern in general even a good idea? An alternative thought I had instead of a generic was to use an enum that would hold the concrete type(s) of Deserializer that I'm attempting to wrap, but that has the downside of having to know of them before hand.