英文:
How to avoid breaking serialized data where enum variants are going to be modified in the future?
问题
使用Bincode进行序列化,数据包含一个类似这样的enum
:
enum E {
A = 0,
B = 1,
C = 2,
}
变体E::A
从未被使用,所以我认为移除它不会引发问题:
enum E {
B = 1,
C = 2,
}
显然,序列化器不关心显式的判别值:
// 反序列化错误:
"invalid value: integer `2`, expected variant index 0 <= i < 2"
是否有办法使"Bincode"使用显式的判别值?或者是否有更合适的解决方案?
谢谢。
英文:
Serializing with Bincode, data contains an enum
like this:
enum E {
A = 0,
B = 1,
C = 2,
}
The variant E::A
was never used, so I thought removing it wouldn't cause a problem:
enum E {
B = 1,
C = 2,
}
Apparently the serializer does not care about explicit discriminants:
// deser error:
"invalid value: integer `2`, expected variant index 0 <= i < 2"
Is there a way to make "Bincode" use the explicit discriminants? Or is there a more proper solution?
Thanks.
答案1
得分: 1
serde派生宏在序列化枚举时使用变体的索引或名称(由格式选择)。Bincode选择索引。
只要您的枚举完全由单元变体组成,您可以使用serde_repr来表示为u32
。
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Deserialize_repr, Serialize_repr)]
#[repr(u32)]
enum E1 {
A = 0,
B = 1,
C = 2,
}
#[derive(Deserialize_repr, Serialize_repr)]
#[repr(u32)]
enum E2 {
B = 1,
C = 2,
}
这些也可以与具有serde派生的枚举在bincode中兼容:
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
enum E1 {
A,
B,
C,
}
请注意,这会覆盖在人类可读格式中使用的变体名称。如果您还要将其序列化为人类可读格式并希望保留变体名称,或者如果您有带有数据的变体,您将需要编写自定义的Deserialize
和Serialize
实现。
相关问题,我刚刚回答过:如何在Rust中使用Bincode序列化枚举时保留枚举标志而不是索引? 由于u64
标签,这个问题最终变得完全不同,但它包含了有关枚举序列化的各个部分由哪些库负责的大量信息。
英文:
The serde derive macros use the variant's index or name (chosen by the format) when serializing an enum. Bincode chooses the index.
As long as your enum is composed entirely of unit variants, you can use serde_repr with a u32
representation.
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Deserialize_repr, Serialize_repr)]
#[repr(u32)]
enum E1 {
A = 0,
B = 1,
C = 2,
}
#[derive(Deserialize_repr, Serialize_repr)]
#[repr(u32)]
enum E2 {
B = 1,
C = 2,
}
These will also be compatible in bincode specifically with an enum with serde derives:
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
enum E1 {
A,
B,
C,
}
Note that this overrides the variant names used in human-readable formats. If you are also serializing to a human-readable format and want to preserve the variant names, or if you have variants with data, you will need to write custom Deserialize
and Serialize
implementations.
Related question that I just answered: How to Serialize Enum in Rust with Bincode While Retaining Enum Discriminant Instead of Index? This one ended up being completely different because of the u64
tags, but it has lots of information on which libraries are responsible for each part of enum serialization.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论