3Hren / 3Hren/msgpack-rust

`#[serde(other)]` not working as expected on enum tuple-like variants

Open
#359 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
1.4k
Forks
162
PR merge metrics
No merged PRs in 30d

Description

I have a use case where I want to have the possibility to introduce a breaking change to a data structure. If my app currently only supports version `0`, it will detect when a version `1` is used. I have written the following code, but I get an error instead of matching on the `#[serde(other)]` variant. (Inspiration taken from https://stackoverflow.com/a/70380491)

```rust
#[derive(serde::Serialize, serde::Deserialize)]
enum A {
V0(String),
#[serde(other)]
Unsupported,
}

#[derive(serde::Serialize, serde::Deserialize)]
enum B {
V0(String),
V1(usize),
#[serde(other)]
Unsupported,
}

#[test]
fn test() {
let b_v1 = rmp_serde::to_vec(&B::V1(1)).unwrap();

// Yields `Err(rmp_serde::decode::Error::TypeMismatch(rmp::Marker::FixPos(1)))`
let a_unsupported = rmp_serde::from_slice::(b_v1.as_slice());
// But instead, I would expect this to pass (`Ok(A::Unsupported)`):
assert!(matches!(a_unsupported, Ok(A::Unsupported)));
}
```

The above code _does_ work when I change the `A` and `B` enums to be _unit-only_:
```diff
#[derive(serde::Serialize, serde::Deserialize)]
enum A {
- V0(String),
+ V0,
#[serde(other)]
Unsupported,
}

#[derive(serde::Serialize, serde::Deserialize)]
enum B {
- V0(String),
- V1(usize),
+ V0,
+ V1,
#[serde(other)]
Unsupported,
}

#[test]
fn test() {
- let b_v1 = rmp_serde::to_vec(&B::V1(1)).unwrap();
+ let b_v1 = rmp_serde::to_vec(&B::V1).unwrap();

// Yields `Err(rmp_serde::decode::Error::TypeMismatch(rmp::Marker::FixPos(1)))`
let a_unsupported = rmp_serde::from_slice::
(b_v1.as_slice());
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.