//! Common utilities. #![no_std] use core::{ fmt, mem::size_of, ops::{Deref, DerefMut}, }; /// Creates an ad-hoc `Debug` instance. pub fn debug(f: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl fmt::Debug { struct Debug(F); impl fmt::Result> fmt::Debug for Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { (self.0)(fmt) } } Debug(f) } /// A hint that this branch is unlikely to be called. #[cold] #[inline(always)] pub fn cold() {} /// A hint that `b` is likely to be true. See `core::intrinsics::likely`. #[inline(always)] pub fn likely(b: bool) -> bool { if !b { cold() } b } /// A hint that `b` is likely to be false. See `core::intrinsics::unlikely`. #[inline(always)] pub fn unlikely(b: bool) -> bool { if b { cold() } b } /// A version of `std::dbg` built on top of `log::debug` instead of /// `std::eprintln`. /// /// This code is copied from libstd, and inherits its copyright. #[macro_export] macro_rules! dbg { // NOTE: We cannot use `concat!` to make a static string as a format // argument of `log::debug!` because the `$expr` expression could be a // block (`{ .. }`), in which case the format string will be malformed. () => { log::debug!("") }; ($expr:expr $(,)?) => { // Use of `match` here is intentional because it affects the lifetimes // of temporaries - https://stackoverflow.com/a/48732525/1063961 match $expr { tmp => { log::debug!("{} = {:#?}", core::stringify!($expr), &tmp); tmp } } }; ($($expr:expr),+ $(,)?) => { ($($crate::dbg!($expr)),+,) }; } /// A wrapper type that promises that its contents are Send. pub struct BelieveMeSend(pub T); impl Deref for BelieveMeSend { type Target = T; fn deref(&self) -> &T { &self.0 } } impl DerefMut for BelieveMeSend { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } unsafe impl Send for BelieveMeSend {} /// A trait for types that can be converted to from big-endian or little-endian byte slices. pub trait FromEndianBytes { /// Converts from a big-endian byte slice. fn from_big_endian_bytes(bytes: &[u8]) -> Self; /// Converts from a little-endian byte slice. fn from_little_endian_bytes(bytes: &[u8]) -> Self; } macro_rules! impl_FromEndianBytes { ($($ty:ty),* $(,)?) => { $(impl FromEndianBytes for $ty { fn from_big_endian_bytes(bytes: &[u8]) -> $ty { let chunk = match bytes.last_chunk() { Some(chunk) => *chunk, None => { let mut chunk = [0; size_of::<$ty>()]; chunk[size_of::<$ty>() - bytes.len()..] .copy_from_slice(bytes); chunk }, }; <$ty>::from_be_bytes(chunk) } fn from_little_endian_bytes(bytes: &[u8]) -> $ty { let chunk = match bytes.first_chunk() { Some(chunk) => *chunk, None => { let mut chunk = [0; size_of::<$ty>()]; chunk[.. bytes.len()].copy_from_slice(bytes); chunk }, }; <$ty>::from_le_bytes(chunk) } })* }; } impl_FromEndianBytes!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); /// Runs the body block the first time it is encountered. #[macro_export] macro_rules! first_time { ($($stmt:stmt);*) => {{ use core::cell::LazyCell; static LAZY_CELL = LazyCell::new(|| { $($stmt);* }); let _: &() = core::cell::LazyCell::force(&LAZY_CELL); }}; }