diff options
Diffstat (limited to 'vendor/static_assertions/src/assert_eq_size.rs')
-rw-r--r-- | vendor/static_assertions/src/assert_eq_size.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/vendor/static_assertions/src/assert_eq_size.rs b/vendor/static_assertions/src/assert_eq_size.rs new file mode 100644 index 000000000..9c3c4901c --- /dev/null +++ b/vendor/static_assertions/src/assert_eq_size.rs @@ -0,0 +1,123 @@ +/// Asserts that types are equal in size. +/// +/// When performing operations such as pointer casts or dealing with [`usize`] +/// versus [`u64`] versus [`u32`], the size of your types matter. That is where +/// this macro comes into play. +/// +/// # Alternatives +/// +/// There also exists [`assert_eq_size_val`](macro.assert_eq_size_val.html) and +/// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying +/// types to compare, values' sizes can be directly compared against each other. +/// +/// # Examples +/// +/// These three types, despite being very different, all have the same size: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_size!([u8; 4], (u16, u16), u32); +/// ``` +/// +/// The following example fails to compile because `u32` has 4 times the size of +/// `u8`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_size!(u32, u8); +/// ``` +/// +/// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html +/// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html +/// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html +#[macro_export] +macro_rules! assert_eq_size { + ($x:ty, $($xs:ty),+ $(,)?) => { + const _: fn() = || { + $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+ + }; + }; +} + +/// Asserts that values pointed to are equal in size. +/// +/// # Examples +/// +/// This especially is useful for when coercing pointers between different types +/// and ensuring the underlying values are the same size. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// fn operation(x: &(u32, u32), y: &[u16; 4]) { +/// assert_eq_size_ptr!(x, y); +/// // ... +/// } +/// ``` +/// +/// The following example fails to compile because byte arrays of different +/// lengths have different sizes: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// static BYTES: &[u8; 4] = &[ +/// /* ... */ +/// # 0; 4 +/// ]; +/// +/// static TABLE: &[u8; 16] = &[ +/// /* ... */ +/// # 0; 16 +/// ]; +/// +/// assert_eq_size_ptr!(BYTES, TABLE); +/// ``` +#[macro_export] +macro_rules! assert_eq_size_ptr { + ($x:expr, $($xs:expr),+ $(,)?) => { + #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)] + let _ = || unsafe { + use $crate::_core::{mem, ptr}; + let mut copy = ptr::read($x); + $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+ + mem::forget(copy); + }; + } +} + +/// Asserts that values are equal in size. +/// +/// This macro doesn't consume its arguments and thus works for +/// non-[`Clone`]able values. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// struct Byte(u8); +/// +/// let x = 10u8; +/// let y = Byte(42); // Works for non-cloneable types +/// +/// assert_eq_size_val!(x, y); +/// assert_eq_size_val!(x, y, 0u8); +/// # } +/// ``` +/// +/// Even though both values are 0, they are of types with different sizes: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// assert_eq_size_val!(0u8, 0u32); +/// # } +/// ``` +/// +/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +#[macro_export(local_inner_macros)] +macro_rules! assert_eq_size_val { + ($x:expr, $($xs:expr),+ $(,)?) => { + assert_eq_size_ptr!(&$x, $(&$xs),+); + } +} |