#[cfg(not(test))] macro_rules! test_layout_only { ( $($tt:tt)* ) => {} }
#[cfg( test )] macro_rules! test_layout_only {
(
$thin:ty => $d3d:ty {
$( $thin_field:ident => $d3d_field:ident ),*
$(,)?
}
) => {
#[test] fn layout() {
use std::mem::*;
use std::ptr::addr_of;
use $crate::macros::*;
let thin = MaybeUninit::<$thin>::uninit();
let d3d = MaybeUninit::<$d3d >::uninit();
let thin = thin.as_ptr();
let d3d = d3d .as_ptr();
assert_eq!( size_of::<$thin>(), size_of::<$d3d>(), "size_of {} != {}", stringify!($thin), stringify!($d3d));
assert_eq!(align_of::<$thin>(), align_of::<$d3d>(), "align_of {} != {}", stringify!($thin), stringify!($d3d));
assert!(stringify!($d3d).to_lowercase().replace("_","").contains(stringify!($thin).to_lowercase().as_str()), "{} not included in {}'s name", stringify!($thin), stringify!($d3d));
$(unsafe {
assert_eq!(size_of_val_raw_sized(addr_of!((*thin).$thin_field)), size_of_val_raw_sized(addr_of!((*d3d).$d3d_field)), "size_of {}::{} != {}::{}", stringify!($thin), stringify!($thin_field), stringify!($d3d), stringify!($d3d_field));
assert_eq!( offset_of(thin, addr_of!((*thin).$thin_field)), offset_of(d3d, addr_of!((*d3d).$d3d_field)), "offset_of {}::{} != {}::{}", stringify!($thin), stringify!($thin_field), stringify!($d3d), stringify!($d3d_field));
})*
}
};
}
#[cfg(not(test))] macro_rules! test_layout { ( $($tt:tt)* ) => {} }
#[cfg( test )] macro_rules! test_layout {
($(
$thin:ty => $d3d:ty {
$( $thin_field:ident => $d3d_field:ident ),*
$(,)?
}
)*) => {
#[test] fn layout() {
use std::mem::*;
use std::ptr::addr_of;
use $crate::macros::*;
$(
let thin = MaybeUninit::<$thin>::uninit();
let d3d = MaybeUninit::<$d3d >::uninit();
let thin = thin.as_ptr();
let d3d = d3d .as_ptr();
assert_eq!( size_of::<$thin>(), size_of::<$d3d>(), "size_of {} != {}", stringify!($thin), stringify!($d3d));
assert_eq!(align_of::<$thin>(), align_of::<$d3d>(), "align_of {} != {}", stringify!($thin), stringify!($d3d));
assert!(stringify!($d3d).to_lowercase().replace("_","").contains(stringify!($thin).to_lowercase().as_str()), "{} not included in {}'s name", stringify!($thin), stringify!($d3d));
$(unsafe {
assert_eq!(size_of_val_raw_sized(addr_of!((*thin).$thin_field)), size_of_val_raw_sized(addr_of!((*d3d).$d3d_field)), "size_of {}::{} != {}::{}", stringify!($thin), stringify!($thin_field), stringify!($d3d), stringify!($d3d_field));
assert_eq!( offset_of(thin, addr_of!((*thin).$thin_field)), offset_of(d3d, addr_of!((*d3d).$d3d_field)), "offset_of {}::{} != {}::{}", stringify!($thin), stringify!($thin_field), stringify!($d3d), stringify!($d3d_field));
assert!(stringify!($d3d_field).to_lowercase().replace("_","").contains(stringify!($thin_field).strip_prefix("r#").unwrap_or(stringify!($thin_field)).to_lowercase().replace("_","").as_str()), "{} not included in {}'s name", stringify!($thin_field), stringify!($d3d_field));
})*
)*
}
};
}
#[cfg(test)] pub const fn size_of_val_raw_sized<T>(_: *const T) -> usize { std::mem::size_of::<T>() }
#[cfg(test)] pub fn offset_of<S, F>(s: *const S, f: *const F) -> usize { (f as usize) - (s as usize) }
macro_rules! enumish {
( $enumish:ty => $d3d:ty; FQN; $($a:ident :: $b:ident),* $(,)? ) => {
impl std::fmt::Debug for $enumish {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
$(
$a::$b => write!(f, "{}", concat!(stringify!($a), "::", stringify!($b))),
)*
other => write!(f, "{}({})", stringify!($enumish), other.0),
}
}
}
enumish!( $enumish => $d3d );
};
( $enumish:ty => $d3d:ty; FQN; $($($ident:ident)::+),* $(,)? ) => {
impl std::fmt::Debug for $enumish {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
$(
$($ident)::+ => write!(f, "{}", concat!(stringify!($($ident)::+))),
)*
other => write!(f, "{}({})", stringify!($enumish), other.0),
}
}
}
enumish!( $enumish => $d3d );
};
( $enumish:ty => $d3d:ty; $($ident:ident),* $(,)? ) => {
impl std::fmt::Debug for $enumish {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
$(
< $enumish > :: $ident => write!(f, concat!(stringify!($enumish), "::", stringify!($ident))),
)*
other => write!(f, "{}({})", stringify!($enumish), other.0),
}
}
}
enumish!( $enumish => $d3d );
};
( $enumish:ty => $d3d:ty ) => {
impl From<$enumish> for $d3d {
fn from(value: $enumish) -> Self { value.0.into() }
}
#[cfg(feature = "impl-from-unchecked")]
impl From<$d3d> for $enumish {
fn from(value: $d3d) -> Self { Self(value as _) }
}
impl $enumish {
pub const fn from_unchecked(d3d: $d3d) -> Self { Self(d3d as _) }
pub const fn into(self) -> $d3d { self.0 as _ }
}
};
}
macro_rules! flags {
( $flagish:ty => $d3d:ty; $($ident:ident),* $(,)? ) => {
impl std::fmt::Debug for $flagish {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
$(
<$flagish>::$ident => write!(f, concat!(stringify!($flagish), "::", stringify!($ident))),
)*
#[allow(unreachable_patterns)] Self(0) => {
write!(f, "{}(0)", stringify!($flagish))
},
other => {
let mut bits = other.0;
$(
if bits & <$flagish>::$ident.0 == <$flagish>::$ident.0 && <$flagish>::$ident.0 != 0 {
if bits == other.0 {
write!(f, "{}::{{{}", stringify!($flagish), stringify!($ident))?;
} else {
write!(f, "|{}", stringify!($ident))?;
}
bits &= !<$flagish>::$ident.0;
}
)*
if bits == other.0 {
write!(f, "{}(0x{:08x})", stringify!($flagish), bits)?;
} else if bits != 0 {
write!(f, "|0x{:08x}}}", bits)?;
} else {
write!(f, "}}")?;
}
Ok(())
},
}
}
}
impl From<$flagish> for $d3d {
fn from(value: $flagish) -> Self { value.0.into() }
}
#[cfg(feature = "impl-from-unchecked")]
impl From<$d3d> for $flagish {
fn from(value: $d3d) -> Self { Self(value as _) }
}
impl $flagish {
pub const fn from_unchecked(d3d: $d3d) -> Self { Self(d3d as _) }
pub const fn into(self) -> $d3d { self.0 as _ }
}
impl std::ops::BitOrAssign for $flagish {
fn bitor_assign(&mut self, other: Self) { self.0 |= other.0 }
}
impl std::ops::BitOr for $flagish {
type Output = Self;
fn bitor(self, other: Self) -> Self { Self(self.0 | other.0) }
}
}
}
macro_rules! convert {
( unsafe $outer:ty => $deref:ty, $winapi:ty ) => {
convert!(unsafe $outer, $winapi);
impl std::ops::Deref for $outer {
type Target = $deref;
fn deref(&self) -> &Self::Target { self.0.up_ref().into() }
}
};
( unsafe $outer:ty, $winapi:ty ) => {
impl From<mcom::Rc<$winapi>> for $outer { fn from(value: mcom::Rc<$winapi>) -> Self { Self(value) } }
impl From<$outer> for mcom::Rc<$winapi> { fn from(value: $outer) -> Self { value.0 } }
impl From<&mcom::Rc<$winapi>> for &$outer { fn from(value: &mcom::Rc<$winapi>) -> Self {
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe { std::mem::transmute(value) }
}}
impl From<&$outer> for &mcom::Rc<$winapi> { fn from(value: &$outer) -> Self {
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe { std::mem::transmute(value) }
}}
unsafe impl $crate::Raw for $outer {
type Raw = $winapi;
unsafe fn from_raw(raw: *mut Self::Raw) -> Self { Self(mcom::Rc::from_raw(raw)) }
unsafe fn from_raw_opt(raw: *mut Self::Raw) -> Option<Self> { Some(Self(mcom::Rc::from_raw_opt(raw)?)) }
fn into_raw(self) -> *mut Self::Raw { self.0.into_raw() }
fn as_raw(&self) -> *mut Self::Raw { self.0.as_ptr() }
}
};
}
macro_rules! mods {
( $( #[$attr:meta] )* inl mod $mod:ident ; $($tt:tt)* ) => { $(#[$attr])* pub(crate) mod $mod; #[allow(unused_imports)] pub use $mod::*; mods!{ $($tt)* } };
( $( #[$attr:meta] )* inl mod $mod:ident { $($body:tt)* } $($tt:tt)* ) => { $(#[$attr])* pub(crate) mod $mod { mods!{ $($body)* } } #[allow(unused_imports)] pub use $mod::*; mods!{ $($tt)* } };
( $( #[$attr:meta] )* $vis:vis mod $mod:ident ; $($tt:tt)* ) => { $(#[$attr])* $vis mod $mod; mods!{ $($tt)* } };
( $( #[$attr:meta] )* $vis:vis mod $mod:ident { $($body:tt)* } $($tt:tt)* ) => { $(#[$attr])* $vis mod $mod { mods!{ $($body)* } } mods!{ $($tt)* } };
() => {};
}