mirror of
https://git.proxmox.com/git/proxmox
synced 2025-04-30 08:09:37 +00:00

This reverts commit 8f89f9ad60
.
generates broken code in release builds on current rustc
1.55
140 lines
3.6 KiB
Rust
140 lines
3.6 KiB
Rust
//! Rust language related helpers.
|
|
//!
|
|
//! This provides some macros for features which are not yet available in the language, or
|
|
//! sometimes also types from nightly `std` which are simple enough to do just haven't been
|
|
//! bikeshedded and stabilized in the standard library yet.
|
|
|
|
mod constnamedbitmap;
|
|
|
|
pub mod ops;
|
|
|
|
/// Macro to write error-handling blocks (like perl eval {})
|
|
///
|
|
/// #### Example:
|
|
/// ```
|
|
/// # use proxmox_lang::try_block;
|
|
/// # macro_rules! format_err {
|
|
/// # ($($msg:tt)+) => { format!($($msg)+) }
|
|
/// # }
|
|
/// # macro_rules! bail {
|
|
/// # ($($msg:tt)+) => { return Err(format_err!($($msg)+)); }
|
|
/// # }
|
|
/// # let some_condition = false;
|
|
/// let result = try_block!({
|
|
/// if (some_condition) {
|
|
/// bail!("some error");
|
|
/// }
|
|
/// Ok(())
|
|
/// })
|
|
/// .map_err(|e| format_err!("my try block returned an error - {}", e));
|
|
/// ```
|
|
|
|
#[macro_export]
|
|
macro_rules! try_block {
|
|
{ $($token:tt)* } => {{ (|| -> Result<_,_> { $($token)* })() }}
|
|
}
|
|
|
|
/// Statically assert the size of a type at compile time.
|
|
///
|
|
/// This should compile:
|
|
/// ```
|
|
/// # use proxmox_lang::static_assert_size;
|
|
/// #[repr(C)]
|
|
/// struct Stuff {
|
|
/// value: [u8; 32]
|
|
/// }
|
|
/// static_assert_size!(Stuff, 32);
|
|
/// ```
|
|
///
|
|
/// This should fail to compile:
|
|
/// ```compile_fail
|
|
/// # use proxmox_lang::static_assert_size;
|
|
/// #[repr(C)]
|
|
/// struct Stuff {
|
|
/// value: [u8; 32]
|
|
/// }
|
|
/// static_assert_size!(Stuff, 128);
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! static_assert_size {
|
|
($ty:ty, $size:expr) => {
|
|
const _: fn() -> () = || {
|
|
let _ = ::std::mem::transmute::<[u8; $size], $ty>;
|
|
};
|
|
};
|
|
}
|
|
|
|
/// Evaluates to the offset (in bytes) of a given member within a struct
|
|
///
|
|
/// ```
|
|
/// # use proxmox_lang::offsetof;
|
|
///
|
|
/// #[repr(C)]
|
|
/// struct Stuff {
|
|
/// first: u32,
|
|
/// second: u32,
|
|
/// }
|
|
///
|
|
/// assert_eq!(offsetof!(Stuff, second), 4);
|
|
///
|
|
/// ```
|
|
// FIXME: With 1.56 we get `const transmute` which may help making this usable `const fn` as we can
|
|
// avoid dereferencing the raw pointer by transmuting `0usize` into a proper reference instead.
|
|
//
|
|
// So with 1.56, do this instead:
|
|
//
|
|
// unsafe { &(std::mem::transmute::<_, &$ty>(0usize).$field) as *const _ as usize }
|
|
#[macro_export]
|
|
macro_rules! offsetof {
|
|
($ty:ty, $field:ident) => {
|
|
unsafe { &(*(std::ptr::null::<$ty>())).$field as *const _ as usize }
|
|
};
|
|
}
|
|
|
|
/// Shortcut for generating an `&'static CStr`.
|
|
///
|
|
/// This takes a *string* (*not* a *byte-string*), appends a terminating zero, and calls
|
|
/// `CStr::from_bytes_with_nul_unchecked`.
|
|
///
|
|
/// Shortcut for:
|
|
/// ```no_run
|
|
/// let bytes = concat!("THE TEXT", "\0");
|
|
/// unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(bytes.as_bytes()) }
|
|
/// # ;
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! c_str {
|
|
($data:expr) => {{
|
|
let bytes = concat!($data, "\0");
|
|
unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(bytes.as_bytes()) }
|
|
}};
|
|
}
|
|
|
|
/*
|
|
// With rust 1.56 we can enable the `c_str!()` macro for const fns:
|
|
|
|
#[doc(hidden)]
|
|
#[allow(unconditional_panic)]
|
|
pub const fn illegal_c_string() {
|
|
[][0]
|
|
}
|
|
|
|
/// Assert that a static byte slice is a valid C string (has no zeros except at the very end),
|
|
/// and return it as a `&'static CStr`.
|
|
pub const fn checked_c_str(bytes: &'static [u8]) -> &'static std::ffi::CStr {
|
|
let mut i = 0;
|
|
while i < bytes.len() - 1 {
|
|
if bytes[i] == 0 {
|
|
illegal_c_string();
|
|
}
|
|
i += 1;
|
|
}
|
|
unsafe { std::mem::transmute::<_, &'static std::ffi::CStr>(bytes) }
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! c_str {
|
|
($data:expr) => { $crate::checked_c_str(concat!($data, "\0")) };
|
|
}
|
|
*/
|