diff options
Diffstat (limited to 'vendor/bitflags/src/external/serde.rs')
-rw-r--r-- | vendor/bitflags/src/external/serde.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/vendor/bitflags/src/external/serde.rs b/vendor/bitflags/src/external/serde.rs new file mode 100644 index 0000000..be4f2ed --- /dev/null +++ b/vendor/bitflags/src/external/serde.rs @@ -0,0 +1,93 @@ +//! Specialized serialization for flags types using `serde`. + +use crate::{ + parser::{self, ParseHex, WriteHex}, + Flags, +}; +use core::{fmt, str}; +use serde::{ + de::{Error, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; + +/** +Serialize a set of flags as a human-readable string or their underlying bits. + +Any unknown bits will be retained. +*/ +pub fn serialize<B: Flags, S: Serializer>(flags: &B, serializer: S) -> Result<S::Ok, S::Error> +where + B::Bits: WriteHex + Serialize, +{ + // Serialize human-readable flags as a string like `"A | B"` + if serializer.is_human_readable() { + serializer.collect_str(&parser::AsDisplay(flags)) + } + // Serialize non-human-readable flags directly as the underlying bits + else { + flags.bits().serialize(serializer) + } +} + +/** +Deserialize a set of flags from a human-readable string or their underlying bits. + +Any unknown bits will be retained. +*/ +pub fn deserialize<'de, B: Flags, D: Deserializer<'de>>(deserializer: D) -> Result<B, D::Error> +where + B::Bits: ParseHex + Deserialize<'de>, +{ + if deserializer.is_human_readable() { + // Deserialize human-readable flags by parsing them from strings like `"A | B"` + struct FlagsVisitor<B>(core::marker::PhantomData<B>); + + impl<'de, B: Flags> Visitor<'de> for FlagsVisitor<B> + where + B::Bits: ParseHex, + { + type Value = B; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a string value of `|` separated flags") + } + + fn visit_str<E: Error>(self, flags: &str) -> Result<Self::Value, E> { + parser::from_str(flags).map_err(|e| E::custom(e)) + } + } + + deserializer.deserialize_str(FlagsVisitor(Default::default())) + } else { + // Deserialize non-human-readable flags directly from the underlying bits + let bits = B::Bits::deserialize(deserializer)?; + + Ok(B::from_bits_retain(bits)) + } +} + +#[cfg(test)] +mod tests { + use serde_test::{assert_tokens, Configure, Token::*}; + bitflags! { + #[derive(serde_derive::Serialize, serde_derive::Deserialize, Debug, PartialEq, Eq)] + #[serde(transparent)] + struct SerdeFlags: u32 { + const A = 1; + const B = 2; + const C = 4; + const D = 8; + } + } + + #[test] + fn test_serde_bitflags_default() { + assert_tokens(&SerdeFlags::empty().readable(), &[Str("")]); + + assert_tokens(&SerdeFlags::empty().compact(), &[U32(0)]); + + assert_tokens(&(SerdeFlags::A | SerdeFlags::B).readable(), &[Str("A | B")]); + + assert_tokens(&(SerdeFlags::A | SerdeFlags::B).compact(), &[U32(1 | 2)]); + } +} |