I'm looking for a good way to deserialize a Vec
of u32
to a Vec
of enum
.
So basically I'm receiving a json object like this:
{
"Account": "r...",
"Flags": 20,
...
}
The struct
I'm trying to deserialize it into looks something like this:
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all(serialize = "PascalCase", deserialize = "snake_case"))]
pub struct Foo<'a> {
account: &'a str,
flags: Option<Vec<FooFlag>>
}
FooFlag
looks something like this:
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize, Display, AsRefStr)]
pub enum FooFlag {
Example1 = 5,
Example2 = 15,
...
}
Now after I've received the json I want to derive the Vec<FooFlag>
from that u32
Flags
value. So for this example it should be vec![FooFlag::Example1, FooFlag::Example2]
(5 + 15 = 20). How I decide that these are the two enums doesn't matter for now.
I would like to have a deserialization function that I could use for multiple structs like Foo
.
I know there are crates like serde_repr
for C-like enums but I didn't manage to put it together in a generic way.
So far I've written a mod
:
mod flag_conversion {
use alloc::vec::Vec;
use serde::{Deserializer, Serializer, Deserialize};
fn serialize<'a, T, S>(flags: &'a Option<Vec<T>>, s: S) -> Result<S::Ok, S::Error>
where
T: Into<u32>,
S: Serializer,
{
s.serialize_option(
{
if let Some(flags) = &flags {
let transaction_flags: Vec<u32> = flags.into_iter().map(|&flag| {
let f = flag;
let n = f.into();
n
}).collect();
transaction_flags.iter().sum::<u32>()
} else {
0
}
}
)
}
fn deserialize<'de, D>(d: D) -> Result<D::Ok, D::Error>
where
D: Deserializer<'de>,
{
let specified_flags = u32::deserialize(d).unwrap();
d.deserialize_u32(
{
if specified_flags == 0 {
None
} else {
todo!() // convert to `Vec` of `...Flag` enum
}
}
)
}
}
So I can use the module in the Foo
struct like this:
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all(serialize = "PascalCase", deserialize = "snake_case"))]
pub struct Foo<'a> {
account: &'a str,
#[serde(with = "flag_conversion")]
flags: Option<Vec<FooFlag>>
}