enumflags2/
fallible.rs

1use super::BitFlag;
2use super::BitFlags;
3use core::convert::TryFrom;
4use core::fmt;
5
6// Coherence doesn't let us use a generic type here. Work around by implementing
7// for each integer type manually.
8for_each_uint! { $ty $hide_docs =>
9    impl<T> TryFrom<$ty> for BitFlags<T>
10    where
11        T: BitFlag<Numeric=$ty>,
12    {
13        type Error = FromBitsError<T>;
14
15        fn try_from(bits: T::Numeric) -> Result<Self, Self::Error> {
16            Self::from_bits(bits)
17        }
18    }
19}
20
21/// The error struct used by [`BitFlags::from_bits`]
22/// and the [`TryFrom`] implementation`
23/// for invalid values.
24///
25/// ```
26/// # use std::convert::TryInto;
27/// # use enumflags2::{bitflags, BitFlags};
28/// #[bitflags]
29/// #[derive(Clone, Copy, Debug)]
30/// #[repr(u8)]
31/// enum MyFlags {
32///     A = 0b0001,
33///     B = 0b0010,
34///     C = 0b0100,
35///     D = 0b1000,
36/// }
37///
38/// let result: Result<BitFlags<MyFlags>, _> = 0b10101u8.try_into();
39/// assert!(result.is_err());
40/// let error = result.unwrap_err();
41/// assert_eq!(error.truncate(), MyFlags::C | MyFlags::A);
42/// assert_eq!(error.invalid_bits(), 0b10000);
43/// ```
44#[derive(Debug, Copy, Clone)]
45pub struct FromBitsError<T: BitFlag> {
46    pub(crate) flags: BitFlags<T>,
47    pub(crate) invalid: T::Numeric,
48}
49
50impl<T: BitFlag> FromBitsError<T> {
51    /// Return the truncated result of the conversion.
52    pub fn truncate(self) -> BitFlags<T> {
53        self.flags
54    }
55
56    /// Return the bits that didn't correspond to any flags.
57    pub fn invalid_bits(self) -> T::Numeric {
58        self.invalid
59    }
60}
61
62impl<T: BitFlag + fmt::Debug> fmt::Display for FromBitsError<T> {
63    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(
65            fmt,
66            "Invalid bits for {:?}: {:#b}",
67            self.flags, self.invalid
68        )
69    }
70}
71
72#[cfg(feature = "std")]
73impl<T: BitFlag + fmt::Debug> std::error::Error for FromBitsError<T> {
74    fn description(&self) -> &str {
75        "invalid bitflags representation"
76    }
77}