#![no_std]
use core::fmt;
use serde::{
de::{Error, MapAccess, Visitor},
ser::SerializeStruct,
Deserialize, Deserializer, Serialize, Serializer,
};
use bitflags::Flags;
pub fn serialize<T: Flags, S: Serializer>(
flags: &T,
name: &'static str,
serializer: S,
) -> Result<S::Ok, S::Error>
where
T::Bits: Serialize,
{
let mut serialize_struct = serializer.serialize_struct(name, 1)?;
serialize_struct.serialize_field("bits", &flags.bits())?;
serialize_struct.end()
}
pub fn deserialize<'de, T: Flags, D: Deserializer<'de>>(
name: &'static str,
deserializer: D,
) -> Result<T, D::Error>
where
T::Bits: Deserialize<'de>,
{
struct BitsVisitor<T>(core::marker::PhantomData<T>);
impl<'de, T: Deserialize<'de>> Visitor<'de> for BitsVisitor<T> {
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a primitive bitflags value wrapped in a struct")
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
let mut bits = None;
struct Field;
impl<'de> Deserialize<'de> for Field {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("field identifier")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
match v {
"bits" => Ok(Field),
field => Err(E::unknown_field(field, &["bits"])),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
while map.next_key::<Field>()?.is_some() {
if bits.is_some() {
return Err(Error::duplicate_field("bits"));
}
bits = Some(map.next_value()?);
}
bits.ok_or_else(|| Error::missing_field("bits"))
}
}
let bits = deserializer.deserialize_struct(name, &["bits"], BitsVisitor(Default::default()))?;
Ok(T::from_bits_retain(bits))
}
#[cfg(test)]
mod tests {
bitflags1::bitflags! {
#[derive(serde_derive::Serialize, serde_derive::Deserialize)]
struct Flags1: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
}
}
bitflags::bitflags! {
#[derive(Debug, PartialEq, Eq)]
struct Flags2: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
}
}
impl serde::Serialize for Flags2 {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
crate::serialize(self, "Flags1", serializer)
}
}
impl<'de> serde::Deserialize<'de> for Flags2 {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
crate::deserialize("Flags1", deserializer)
}
}
#[test]
fn serde_compat() {
use serde_test::{assert_tokens, Configure as _, Token::*};
let expected = &[
Struct {
name: "Flags1",
len: 1,
},
Str("bits"),
U32(0b00000010),
StructEnd,
];
assert_tokens(&(Flags1::B).readable(), expected);
assert_tokens(&(Flags2::B).readable(), expected);
assert_tokens(&(Flags1::B).compact(), expected);
assert_tokens(&(Flags2::B).compact(), expected);
}
}