让我们考虑下面的泛型枚举示例:

enum Enum<T, U> {
    T(T),
    U(U),
}

Enum中实现Serde::Serialize特征相当容易:

impl<T, U> Serialize for Enum<T, U>
where
    T: Serialize,
    U: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Enum::T(t) => t.serialize(serializer),
            Enum::U(u) => u.serialize(serializer),
        }
    }
}

然而,我很难实现Serde::Deserialize特征,它的行为应该如下所示:

  • 如果该值可以反序列化为类型T,那么它应该返回Enum::T(t).
  • 否则,如果该值可以反序列化为类型U,则它应该返回Enum::U(u).
  • 否则,它应该返回一个错误.

这是我能得到的最接近的结果:

impl<'de, T, U> Deserialize<'de> for Enum<T, U>
where
    T: Deserialize<'de>,
    U: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        if let Ok(t) = T::deserialize(deserializer) {
            Ok(Enum::T(t))
        } else {
            if let Ok(u) = U::deserialize(deserializer) {
                Ok(Enum::U(u))
            } else {
                Err(D::Error::custom("Failed to deserialize Enum"))
            }
        }
    }
}

但是,我得到以下错误:

error[E0382]: use of moved value: `deserializer`
   --> src\lib.rs:731:47
    |
724 |         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    |                           ------------ move occurs because `deserializer` has type `D`, which does not implement the `Copy` trait
...
728 |             if let Ok(t) = T::deserialize(deserializer) {
    |                                           ------------ value moved here
...
731 |                 if let Ok(f) = F::deserialize(deserializer) {
    |                                               ^^^^^^^^^^^^ value used here after move
    |
help: consider further restricting this bound
    |
726 |             D: Deserializer<'de> + std::marker::Copy,
    |                                  +++++++++++++++++++

For more information about this error, try `rustc --explain E0382`.

我知道发生了什么,但我不确定如何修复它(编译器建议也不起作用).

推荐答案

在Kevin Reid的 comments 之后,我使用cargo expand判断了serde_derive为未标记的枚举生成的代码,并提出了以下实现:

impl<'de, T, U> Deserialize<'de> for Enum<T, U>
where
    T: Deserialize<'de>,
    F: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let content = serde::__private::de::Content::deserialize(de)?;
        let deserializer = serde::__private::de::ContentRefDeserializer::<D::Error>::new(
        &content,
    );
        if let Ok(t) = T::deserialize(de) {
            Ok(Enum::T(t))
        } else if let Ok(u) = U::deserialize(de) {
            Ok(Enum::U(u))
        } else {
            Err(D::Error::custom("input data did not match any variant type"))
    }
}

诀窍是依赖serde::__private::de::Contentserde::__private::de::ContentRefDeserializer,它们目前在Serde私有API中,但future 可能会成为公共的,请参见:

Rust相关问答推荐

rust 蚀将动力特性浇到混凝土 struct 上是行不通的

Box::new()会从一个堆栈复制到另一个堆吗?

有没有办法指定只在Rust的测试中有效的断言?

是否可以使用Rust宏来构建元组的项?

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

无符号整数的Rust带符号差

使用关联类型重写时特征的实现冲突

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

如何在Rust中基于字符串 Select struct ?

应为关联类型,找到类型参数

Cargo.toml:如何有条件地启用依赖项功能?

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

在Rust中实现Trie数据 struct 的更好方式

部署Rust发布二进制文件的先决条件

Rust编译器通过哪些规则来确保锁被释放?

在不安全的 Rust 中存储对 struct 内部数据的静态引用是否合法?

有什么方法可以通过使用生命周期来减轻嵌套生成器中的当生成器产生时borrow 可能仍在使用错误?

如何将 Rust 字符串转换为 i8(c_char) 数组?

如何在 C++ 和 Rust 之间共享 pthread 同步原语?

Rust 生命周期:不能在方法内重新borrow 可变字段