/rust/registry/src/index.crates.io-6f17d22bba15001f/bitflags-2.9.1/src/external/serde.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! Specialized serialization for flags types using `serde`. |
2 | | |
3 | | use crate::{ |
4 | | parser::{self, ParseHex, WriteHex}, |
5 | | Flags, |
6 | | }; |
7 | | use core::{fmt, str}; |
8 | | use serde::{ |
9 | | de::{Error, Visitor}, |
10 | | Deserialize, Deserializer, Serialize, Serializer, |
11 | | }; |
12 | | |
13 | | /** |
14 | | Serialize a set of flags as a human-readable string or their underlying bits. |
15 | | |
16 | | Any unknown bits will be retained. |
17 | | */ |
18 | 0 | pub fn serialize<B: Flags, S: Serializer>(flags: &B, serializer: S) -> Result<S::Ok, S::Error> |
19 | 0 | where |
20 | 0 | B::Bits: WriteHex + Serialize, |
21 | 0 | { |
22 | 0 | // Serialize human-readable flags as a string like `"A | B"` |
23 | 0 | if serializer.is_human_readable() { |
24 | 0 | serializer.collect_str(&parser::AsDisplay(flags)) |
25 | | } |
26 | | // Serialize non-human-readable flags directly as the underlying bits |
27 | | else { |
28 | 0 | flags.bits().serialize(serializer) |
29 | | } |
30 | 0 | } |
31 | | |
32 | | /** |
33 | | Deserialize a set of flags from a human-readable string or their underlying bits. |
34 | | |
35 | | Any unknown bits will be retained. |
36 | | */ |
37 | 0 | pub fn deserialize<'de, B: Flags, D: Deserializer<'de>>(deserializer: D) -> Result<B, D::Error> |
38 | 0 | where |
39 | 0 | B::Bits: ParseHex + Deserialize<'de>, |
40 | 0 | { |
41 | 0 | 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 | 0 | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
52 | 0 | formatter.write_str("a string value of `|` separated flags") |
53 | 0 | } |
54 | | |
55 | 0 | fn visit_str<E: Error>(self, flags: &str) -> Result<Self::Value, E> { |
56 | 0 | parser::from_str(flags).map_err(|e| E::custom(e)) |
57 | 0 | } |
58 | | } |
59 | | |
60 | 0 | deserializer.deserialize_str(FlagsVisitor(Default::default())) |
61 | | } else { |
62 | | // Deserialize non-human-readable flags directly from the underlying bits |
63 | 0 | let bits = B::Bits::deserialize(deserializer)?; |
64 | | |
65 | 0 | Ok(B::from_bits_retain(bits)) |
66 | | } |
67 | 0 | } |
68 | | |
69 | | #[cfg(test)] |
70 | | mod 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 | | } |