summaryrefslogtreecommitdiff
path: root/crates/utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/utils/src')
-rw-r--r--crates/utils/src/lib.rs95
1 files changed, 94 insertions, 1 deletions
diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs
index 248227a..3649666 100644
--- a/crates/utils/src/lib.rs
+++ b/crates/utils/src/lib.rs
@@ -1,6 +1,7 @@
+//! Common utilities.
#![no_std]
-use core::fmt;
+use core::{fmt, mem::size_of};
/// Creates an ad-hoc `Debug` instance.
pub fn debug(f: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl fmt::Debug {
@@ -14,3 +15,95 @@ pub fn debug(f: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl fmt::Debug
Debug(f)
}
+
+/// A hint that this branch is unlikely to be called.
+#[cold]
+#[inline(always)]
+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 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);