firehazard 0.0.0-2022-09-10

Unopinionated low level API bindings focused on soundness, safety, and stronger types over raw FFI.
Documentation
macro_rules! flags {
    (impl .. for $flags:ident ( $($inner:ty),+ $(,)? ) - $mask:ident) => {
        flags!(impl *LocalHandle<HANDLE> for $flags ( $($inner),+ ) - $mask);
        flags!(impl @extra for $flags);
    };

    (impl *LocalHandle<HANDLE> for $flags:ident ( $($inner:ty),+ $(,)? ) - $mask:ident) => {
        impl From<()                               > for $flags { fn from(_: ()                               ) -> Self { Self(0) } }
        impl From<()                               > for $mask  { fn from(_: ()                               ) -> Self { Self(0) } }
        impl From<Option<core::convert::Infallible>> for $flags { fn from(_: Option<core::convert::Infallible>) -> Self { Self(0) } }
        impl From<Option<core::convert::Infallible>> for $mask  { fn from(_: Option<core::convert::Infallible>) -> Self { Self(0) } }
        impl From<$flags                           > for $mask  { fn from(flags: $flags                       ) -> Self { Self(flags.0) } }
    $(  impl From<$flags>                            for $inner { fn from(flags: $flags                       ) -> Self { flags.0 as _ } } )*
    $(  impl From<$mask >                            for $inner { fn from(mask:  $mask                        ) -> Self { mask .0 as _ } } )*
    $(  impl From<$inner>                            for $mask  { fn from(mask:  $inner                       ) -> Self { Self(mask as _) } } )*

        impl core::ops::BitAnd              for $flags { type Output = Self; fn bitand(self, rhs: Self) -> Self::Output { Self(self.0 & rhs.0) } }
        impl core::ops::BitOr               for $flags { type Output = Self; fn bitor (self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) } }
        impl core::ops::BitAndAssign        for $flags { fn bitand_assign(&mut self, rhs: Self) { self.0 &= rhs.0 } }
        impl core::ops::BitOrAssign         for $flags { fn bitor_assign (&mut self, rhs: Self) { self.0 |= rhs.0 } }

        impl core::ops::Not                 for $flags  { type Output = $mask;  fn not(self) -> Self::Output { $mask(!self.0) } }
        impl core::ops::BitAnd<$mask>       for $flags  { type Output = $flags; fn bitand(self, rhs: $mask ) -> $flags { $flags(self.0 & rhs.0) } }
        impl core::ops::BitAnd<$flags>      for $mask   { type Output = $flags; fn bitand(self, rhs: $flags) -> $flags { $flags(self.0 & rhs.0) } }
        impl core::ops::BitAndAssign<$mask> for $flags  { fn bitand_assign(&mut self, rhs: $mask) { self.0 &= rhs.0 } }

        impl core::ops::BitOr<()> for $flags                                { type Output = $flags; fn bitor (self, rhs: ()                                 ) -> Self::Output { $flags::from(self) | $flags::from(rhs) } }
        impl core::ops::BitOr<$flags> for ()                                { type Output = $flags; fn bitor (self, rhs: $flags                             ) -> Self::Output { $flags::from(self) | $flags::from(rhs) } }
        impl core::ops::BitOr<Option<core::convert::Infallible>> for $flags { type Output = $flags; fn bitor (self, rhs: Option<core::convert::Infallible>  ) -> Self::Output { $flags::from(self) | $flags::from(rhs) } }
        impl core::ops::BitOr<$flags> for Option<core::convert::Infallible> { type Output = $flags; fn bitor (self, rhs: $flags                             ) -> Self::Output { $flags::from(self) | $flags::from(rhs) } }

        impl core::ops::Mul<bool> for $flags { type Output = $flags; fn mul(self, rhs: bool  ) -> Self::Output { if rhs  { self } else { $flags(0) } } }
        impl core::ops::Mul<$flags> for bool { type Output = $flags; fn mul(self, rhs: $flags) -> Self::Output { if self { rhs  } else { $flags(0) } } }
    };

    (impl @extra for AccessRights) => {
        impl From<access::Mask> for AccessRights { fn from(am: access::Mask) -> Self { Self(am.into()) } }
        impl From<AccessRights> for access::Mask { fn from(am: AccessRights) -> Self { unsafe { access::Mask::from_unchecked(am.into()) } } }

        impl core::ops::BitAnd         <access::Mask> for AccessRights { type Output = Self; fn bitand(self, rhs: access::Mask) -> Self::Output { Self(u32::from(self) & u32::from(rhs)) } }
        impl core::ops::BitOr          <access::Mask> for AccessRights { type Output = Self; fn bitor (self, rhs: access::Mask) -> Self::Output { Self(u32::from(self) | u32::from(rhs)) } }
        impl core::ops::BitAndAssign   <access::Mask> for AccessRights { fn bitand_assign(&mut self, rhs: access::Mask) { self.0 &= u32::from(rhs) } }
        impl core::ops::BitOrAssign    <access::Mask> for AccessRights { fn bitor_assign (&mut self, rhs: access::Mask) { self.0 |= u32::from(rhs) } }

        impl core::ops::BitAnd<access::MaskMask>       for AccessRights { type Output = AccessRights; fn bitand(self, rhs: access::MaskMask) -> AccessRights { AccessRights(u32::from(self) & u32::from(rhs)) } }
        impl core::ops::BitAnd<AccessRights>       for access::MaskMask { type Output = AccessRights; fn bitand(self, rhs: AccessRights    ) -> AccessRights { AccessRights(u32::from(self) & u32::from(rhs)) } }
        impl core::ops::BitAndAssign<access::MaskMask> for AccessRights { fn bitand_assign(&mut self, rhs: access::MaskMask) { self.0 &= u32::from(rhs) } }
    };
    (impl @extra for $ty:ident) => {};

    ($value:expr, $fmt:expr, $final:literal, [$($flag:ident),+$(,)?]) => {{
        let mut value = $value;
        if value == 0 { return write!($fmt, "0") }

    $(  if value & $flag != 0 {
            write!($fmt, "{}", stringify!($flag))?;
            value &= !$flag;
            if value != 0 { write!($fmt, " | ")?; }
        })+

        if value != 0 { write!($fmt, $final, value)? }

        Ok(())
    }};
}