-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enums of named integer constants/enums with "other" variant #574
Comments
First, clearly typify is not doing a good job of handling pub enum MyEnum {
Variant0(i64),
Variant1(i64),
} I would note that if you use the pub enum MyEnum {
Foo(i64),
Bar(i64),
} ... but that's only slightly better looking and no more faithful. Here's what I'd want to see (more or less). pub enum MyEnum {
Foo,
Bar,
}
impl<'de> serde::Deserialize<'de> for MyEnum {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
match u64::deserialize(deserializer)? {
1 => Ok(Self::Foo),
5 => Ok(Self::Bar),
_ => Err(D::Error::invalid_value(...)),
}
}
} I don't think I'd use the discriminant value since 1. serde itself doesn't consider that (and I'm loath to pull in another serde-like dependency) and 2. we need something similar for other, constant, non-integral values. With regard to that second type (the I get that's the point of |
Sure, that code looks good. Setting a discriminant would make serialization code shorter but doesn't help that much for deserialization since there's no
Sure, looking purely at the schema, with In any case, what I suspect the authors of that schema meant is: "These are the known values as of now, but there may be user-defined values or future extensions that should be accepted for forward compatibility". |
Agreed! I'm trying to figure out how we would infer that to be the case or come up with a heuristic that is generally applicable (i.e. rather than one that might be wrong). In general our current enum MyEnum {
Foo,
Bar,
Other(MyEnumOther),
}
struct MyEnumOther(i64);
impl From<i64> for MyEnum {
fn from(value: i64) -> Self {
match value {
1 => Self::Foo,
5 => Self::Bar,
n => Self::Other(n),
}
}
}
impl From<MyEnum> for i64 { .. }
impl From<MyEnumOther> for i64 {
fn from(value: MyEnumOther) -> Self {
value.0
}
}
// .. and maybe this as well:
impl TryFrom<i64> for MyEnumOther {
fn try_from(value: i64) -> Result<Self, ..> {
match (value) {
/* known values */ => Err(..),
n => Ok(Self(n)),
}
}
} This might be overly fussy but it would mean that a particular value had a single representation in the generated code. |
That seems reasonable to me. For what it's worth, I don't know if this is a common pattern in the json schema world. I would be content to just write these types myself for now, but there it is somewhat annoying that the replacements in |
This schema:
generates this non-functional output:
Desured output would be:
I think the
serde_repr
crate could be used in this case.Similarly, this:
generates
Desired output would be something like
I think for integer variants this would require custom (de)serialization code. However, this
Other
feature would also be useful for enums with string variants, where I believe it might be accomplished with#[serde(other)]
Examples in the wild:
The text was updated successfully, but these errors were encountered: