Я использую Serde для десериализации пользовательского файла конфигурации, написанного на YAML. Файл может содержать определения различных типов, которые я представляю как перечисления с внутренними тегами:
OfKindFoo:
kind: Foo
bar: bar;
baz: baz;
OfKindQux:
kind: Qux
quux: qux;
Я представляю это в Rust так:
#[derive(Deserialize)]
#[serde(tag = "kind")]
enum Definition {
Foo(Foo),
Qux(Qux),
}
#[derive(Deserialize)]
struct Foo {
bar: String,
baz: String,
}
#[derive(Deserialize)]
struct Qux {
quux: String,
}
Я хочу, чтобы пользователь мог полностью опустить поле kind
, и когда оно опущено, Serde должен по умолчанию десериализовать его как Foo
.
Я начал внедрять Deserialize
на Definition
. Я пытаюсь десериализовать его как карту и искать ключ kind
и возвращать соответствующий вариант перечисления на основе этого ключа и того, присутствует ли он.
Мне нужно как-то «переправить» десериализацию других полей карты в Foo::deserialize
или Bar::deserialize
соответственно. fn deserialize
принимает только один аргумент - Deserializer
. Есть ли способ «преобразовать» карту в десериализатор или иным образом получить десериализатор, который «запускается» на этой конкретной карте?
Я не могу использовать #[serde(other)]
, потому что он возвращает Err
для отсутствующего тега. Даже если это не так, в документации указано, что other
может применяться только к «варианту устройства», варианту, не содержащему никаких данных.