Hi, I am trying to write a customized serde deserializer for a Vec
that contains something that could be converted into a base64 string. Unfortunately I get a "type annotations needed" compilation error that I can't manage to fix.
Strangely enough, if I attempt to do about the same thing with a map instead of a Vec
, things compile correctly. (You can see the compiling map example at the playground link)
This is the relevant code for the custom deserializer:
pub mod ser_vec_b64 {
use super::*;
pub fn deserialize<'de, T, V, D>(deserializer: D) -> Result<V, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de> + for<'t> TryFrom<&'t [u8]>,
V: Default + Extend<T>,
{
struct SeqVisitor<T, V> {
item: PhantomData<T>,
seq: PhantomData<V>,
}
impl<'de, T, V> Visitor<'de> for SeqVisitor<T, V>
where
T: Deserialize<'de> + for<'t> TryFrom<&'t [u8]>,
V: Default + Extend<T>,
{
type Value = V;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("A vector")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut res_vec: V = V::default();
while let Some(str_item) = seq.next_element::<String>()? {
let vec = base64::decode_config(&str_item, URL_SAFE_NO_PAD)
.map_err(|err| Error::custom(err.to_string()))?;
let item = T::try_from(&vec).map_err(|_| Error::custom("Length mismatch"))?;
res_vec.extend(Some(item));
}
Ok(res_vec)
}
}
let visitor = SeqVisitor {
item: PhantomData,
seq: PhantomData,
};
deserializer.deserialize_seq(visitor)
}
}
And this is an example struct:
#[derive(Deserialize)]
struct MyVecStruct {
#[serde(deserialize_with = "ser_vec_b64::deserialize")]
my_vec: Vec<[u8; 16]>,
}
I get this compilation error:
$ cargo run
Compiling check_serde_vec v0.1.0 (/home/real/projects/rust_check/check_serde_vec)
error[E0283]: type annotations needed: cannot resolve `_: serde::Deserialize<'_>`
--> src/main.rs:124:32
|
74 | pub fn deserialize<'de, T, V, D>(deserializer: D) -> Result<V, D::Error>
| -----------
...
77 | T: Deserialize<'de> + for<'t> TryFrom<&'t [u8]>,
| ---------------- required by this bound in `ser_vec_b64::deserialize`
...
124 | #[serde(deserialize_with = "ser_vec_b64::deserialize")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
I tried to expand the macros using cargo expand
, but I didn't manage to spot any important difference between the two cases of Vec
and HashMap
. I suspected that the issue has something to do with this expression: for<'t> TryFrom<&'t [u8]>
, but even when I tried to modify or remove it in various way I couldn't convince the compiler to compile the MyVecStruct
.
Any help is appreciated!