bitflags/external/
serde.rs

1//! Specialized serialization for flags types using `serde`.
2
3use crate::{
4    parser::{self, ParseHex, WriteHex},
5    Flags,
6};
7use core::{fmt, str};
8use serde::{
9    de::{Error, Visitor},
10    Deserialize, Deserializer, Serialize, Serializer,
11};
12
13/**
14Serialize a set of flags as a human-readable string or their underlying bits.
15
16Any unknown bits will be retained.
17*/
18pub fn serialize<B: Flags, S: Serializer>(flags: &B, serializer: S) -> Result<S::Ok, S::Error>
19where
20    B::Bits: WriteHex + Serialize,
21{
22    // Serialize human-readable flags as a string like `"A | B"`
23    if serializer.is_human_readable() {
24        serializer.collect_str(&parser::AsDisplay(flags))
25    }
26    // Serialize non-human-readable flags directly as the underlying bits
27    else {
28        flags.bits().serialize(serializer)
29    }
30}
31
32/**
33Deserialize a set of flags from a human-readable string or their underlying bits.
34
35Any unknown bits will be retained.
36*/
37pub fn deserialize<'de, B: Flags, D: Deserializer<'de>>(deserializer: D) -> Result<B, D::Error>
38where
39    B::Bits: ParseHex + Deserialize<'de>,
40{
41    if deserializer.is_human_readable() {
42        // Deserialize human-readable flags by parsing them from strings like `"A | B"`
43        struct FlagsVisitor<B>(core::marker::PhantomData<B>);
44
45        impl<'de, B: Flags> Visitor<'de> for FlagsVisitor<B>
46        where
47            B::Bits: ParseHex,
48        {
49            type Value = B;
50
51            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
52                formatter.write_str("a string value of `|` separated flags")
53            }
54
55            fn visit_str<E: Error>(self, flags: &str) -> Result<Self::Value, E> {
56                parser::from_str(flags).map_err(|e| E::custom(e))
57            }
58        }
59
60        deserializer.deserialize_str(FlagsVisitor(Default::default()))
61    } else {
62        // Deserialize non-human-readable flags directly from the underlying bits
63        let bits = B::Bits::deserialize(deserializer)?;
64
65        Ok(B::from_bits_retain(bits))
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use serde_test::{assert_tokens, Configure, Token::*};
72    bitflags! {
73        #[derive(serde_derive::Serialize, serde_derive::Deserialize, Debug, PartialEq, Eq)]
74        #[serde(transparent)]
75        struct SerdeFlags: u32 {
76            const A = 1;
77            const B = 2;
78            const C = 4;
79            const D = 8;
80        }
81    }
82
83    #[test]
84    fn test_serde_bitflags_default() {
85        assert_tokens(&SerdeFlags::empty().readable(), &[Str("")]);
86
87        assert_tokens(&SerdeFlags::empty().compact(), &[U32(0)]);
88
89        assert_tokens(&(SerdeFlags::A | SerdeFlags::B).readable(), &[Str("A | B")]);
90
91        assert_tokens(&(SerdeFlags::A | SerdeFlags::B).compact(), &[U32(1 | 2)]);
92    }
93}