sddl 0.1.0

a library to parse and analyse SDDL Strings
Documentation
pub trait Contains<Rhs> {
    fn contains(&self, rhs: Rhs) -> bool;
}
macro_rules! flag_wrapper {
    ($clazz: ident, $single_flag: ty, $raw_type: ty) => {
        #[derive(Clone, Copy, Debug, serde::Serialize)]
        pub struct $clazz {
            flags: enumflags2::BitFlags<$single_flag, $raw_type>,
            // we store the original binary value in case there have been
            // some undefined flags set
            original_value: Option<$raw_type>,
        }

        impl $clazz {
            pub const EMPTY: Self = Self {
                flags: enumflags2::BitFlags::<$single_flag, $raw_type>::EMPTY,
                original_value: None,
            };

            pub fn empty() -> Self {
                Self {
                    flags: enumflags2::BitFlags::<$single_flag, $raw_type>::empty(),
                    original_value: None,
                }
            }

            pub const fn from_bitflags(
                bitflags: enumflags2::BitFlags<$single_flag, $raw_type>,
            ) -> Self {
                Self {
                    flags: bitflags,
                    original_value: None,
                }
            }

            pub fn from_bitflag(bitflag: $single_flag) -> Self {
                Self {
                    flags: enumflags2::BitFlags::<$single_flag, $raw_type>::EMPTY | bitflag,
                    original_value: None,
                }
            }
            pub fn raw_value(&self) -> $raw_type {
                self.flags.bits()
            }            
        }

        impl Contains<$single_flag> for $clazz {
            fn contains(&self, bitflag: $single_flag) -> bool {
                self.flags.contains(bitflag)
            }
        }

        impl Contains<enumflags2::BitFlags::<$single_flag, $raw_type>> for $clazz {
            fn contains(&self, bitflag: enumflags2::BitFlags::<$single_flag, $raw_type>) -> bool {
                self.flags.contains(bitflag)
            }
        }

        impl From<$raw_type> for $clazz {
            fn from(value: $raw_type) -> Self {
                let flags =
                    enumflags2::BitFlags::<$single_flag, $raw_type>::from_bits_truncate(value);
                Self {
                    flags,
                    original_value: Some(value),
                }
            }
        }

        impl AsRef<enumflags2::BitFlags<$single_flag, $raw_type>> for $clazz {
            fn as_ref(&self) -> &enumflags2::BitFlags<$single_flag, $raw_type> {
                &self.flags
            }
        }

        impl From<enumflags2::BitFlags<$single_flag, $raw_type>> for $clazz {
            fn from(flags: enumflags2::BitFlags<$single_flag, $raw_type>) -> Self {
                Self {
                    flags,
                    original_value: None,
                }
            }
        }

        impl std::ops::BitOr for $clazz {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output {
                let flags = self.flags | rhs.flags;
                let original_value = match (self.original_value, rhs.original_value) {
                    (None, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs | rhs),
                    (Some(lhs), None) => Some(lhs | rhs.flags.bits()),
                    (None, Some(rhs)) => Some(self.flags.bits() | rhs),
                };
                Self {
                    flags,
                    original_value,
                }
            }
        }

        impl std::ops::BitOr<$single_flag> for $clazz {
            type Output = Self;

            fn bitor(self, rhs: $single_flag) -> Self::Output {
                let flags = self.flags | rhs;
                let original_value = match self.original_value {
                    Some(lhs) => Some(lhs | Self::from_bitflag(rhs).flags.bits()),
                    None => None,
                };
                Self {
                    flags,
                    original_value,
                }
            }
        }

        impl std::ops::BitOrAssign<$clazz> for $clazz {
            fn bitor_assign(&mut self, rhs: $clazz) {
                self.flags = self.flags | rhs.flags;
                self.original_value = match (self.original_value, rhs.original_value) {
                    (None, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs | rhs),
                    (Some(lhs), None) => Some(lhs | rhs.flags.bits()),
                    (None, Some(rhs)) => Some(self.flags.bits() | rhs),
                };
            }
        }

        impl std::ops::BitOrAssign<$single_flag> for $clazz {
            fn bitor_assign(&mut self, rhs: $single_flag) {
                self.flags = self.flags | rhs;
                self.original_value = match self.original_value {
                    Some(lhs) => Some(lhs | Self::from_bitflag(rhs).flags.bits()),
                    None => None,
                };
            }
        }

        impl PartialEq for $clazz {
            fn eq(&self, other: &Self) -> bool {
                if self.flags == other.flags {
                    match (self.original_value, other.original_value) {
                        (None, None) => true,
                        (Some(lhs), None) => self.flags.bits() == lhs,
                        (None, Some(rhs)) => rhs == other.flags.bits(),
                        (Some(lhs), Some(rhs)) => lhs == rhs
                    }
                } else {
                    false
                }
            }
        }

        impl Eq for $clazz {

        }

        impl BinRead for $clazz {
            type Args<'a> = ();

            fn read_options<R: std::io::Read + std::io::Seek>(
                reader: &mut R,
                endian: binrw::Endian,
                args: Self::Args<'_>,
            ) -> binrw::BinResult<Self> {
                let raw_value: $raw_type = reader.read_type_args(endian, args)?;
                Ok(Self::from(raw_value))
            }
        }

        impl BinWrite for $clazz {
            type Args<'a> = ();

            fn write_options<W: std::io::Write + std::io::Seek>(
                &self,
                writer: &mut W,
                _endian: binrw::Endian,
                args: Self::Args<'_>,
            ) -> binrw::BinResult<()> {
                let value = self.original_value.unwrap_or(self.flags.bits());
                writer.write_le_args(&value, args)
            }
        }
    };
}

pub(crate) use flag_wrapper;