//! Macros for use within the library. They are not publicly available.
/// Division of integers, rounding the resulting value towards negative infinity.
macro_rules! div_floor {
($self:expr, $rhs:expr) => { match ($self, $rhs) {
(this, rhs) => { let d = this / rhs; let r = this % rhs;
// If the remainder is non-zero, we need to subtract one if the // signs of self and rhs differ, as this means we rounded upwards // instead of downwards. We do this branchlessly by creating a mask // which is all-ones iff the signs differ, and 0 otherwise. Then by // adding this mask (which corresponds to the signed value -1), we // get our correction. let correction = (this ^ rhs) >> (size_of_val(&this) * 8 - 1); if r != 0 { d + correction } else { d }
}
}
};
}
/// Similar to `overflowing_add`, but returning the number of times that it overflowed. Contained to /// a certain range and only overflows a maximum number of times.
macro_rules! carry {
(@most_once $value:expr, $min:literal.. $max:expr) => { match ($value, $min, $max) {
(value, min, max) => { ifcrate::hint::likely(value >= min) { ifcrate::hint::likely(value < max) {
(value, 0)
} else {
(value - (max - min), 1)
}
} else {
(value + (max - min), -1)
}
}
}
};
(@most_twice $value:expr, $min:literal.. $max:expr) => { match ($value, $min, $max) {
(value, min, max) => { ifcrate::hint::likely(value >= min) { ifcrate::hint::likely(value < max) {
(value, 0)
} elseif value < 2 * max - min {
(value - (max - min), 1)
} else {
(value - 2 * (max - min), 2)
}
} else { if value >= min - max {
(value + (max - min), -1)
} else {
(value + 2 * (max - min), -2)
}
}
}
}
};
(@most_thrice $value:expr, $min:literal.. $max:expr) => { match ($value, $min, $max) {
(value, min, max) => { ifcrate::hint::likely(value >= min) { ifcrate::hint::likely(value < max) {
(value, 0)
} elseif value < 2 * max - min {
(value - (max - min), 1)
} elseif value < 3 * max - 2 * min {
(value - 2 * (max - min), 2)
} else {
(value - 3 * (max - min), 3)
}
} else { if value >= min - max {
(value + (max - min), -1)
} elseif value >= 2 * (min - max) {
(value + 2 * (max - min), -2)
} else {
(value + 3 * (max - min), -3)
}
}
}
}
};
}
// Cascade an out-of-bounds value from "from" to "to".
($from:ident in $min:literal.. $max:expr => $to:tt) => { #[allow(unused_comparisons, unused_assignments)] let min = $min; let max = $max; ifcrate::hint::unlikely($from >= max) {
$from -= max - min;
$to += 1;
} elseifcrate::hint::unlikely($from < min) {
$from += max - min;
$to -= 1;
}
};
// Special case the ordinal-to-year cascade, as it has different behavior.
($ordinal:ident => $year:ident) => { // We need to actually capture the idents. Without this, macro hygiene causes errors.
cascade!(@ordinal $ordinal);
cascade!(@year $year);
/// Constructs a ranged integer, returning a `ComponentRange` error if the value is out of range.
macro_rules! ensure_ranged {
($type:ty : $value:ident) => { match <$type>::new($value) {
Some(val) => val,
None => {
$crate::hint::cold_path(); return Err(crate::error::ComponentRange::unconditional(stringify!($value)));
}
}
};
/// Try to unwrap an expression, returning if not possible. /// /// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is /// usable in `const` contexts.
macro_rules! const_try {
($e:expr) => { match $e {
Ok(value) => value,
Err(error) => {
$crate::hint::cold_path(); return Err(error);
}
}
};
}
/// Try to unwrap an expression, returning if not possible. /// /// This is identical to `?` in terms of behavior, but marks the error path as cold. #[cfg(any(feature = "formatting", feature = "parsing"))]
macro_rules! try_likely_ok {
($e:expr) => { match $e {
Ok(value) => value,
Err(error) => {
$crate::hint::cold_path(); return Err(error.into());
}
}
};
}
/// Try to unwrap an expression, returning if not possible. /// /// This is similar to the `?` operator, but is usable in `const` contexts.
macro_rules! const_try_opt {
($e:expr) => { match $e {
Some(value) => value,
None => {
$crate::hint::cold_path(); return None;
}
}
};
}
/// `unreachable!()`, but better. #[cfg(any(feature = "formatting", feature = "parsing"))]
macro_rules! bug {
() => {
compile_error!("provide an error message to help fix a possible bug")
};
($descr:literal) => {
panic!(concat!("internal error: ", $descr))
};
}
#[cfg(any(feature = "formatting", feature = "parsing"))] pub(crate) use {bug, try_likely_ok}; pub(crate) use {carry, cascade, const_try, const_try_opt, div_floor, ensure_ranged};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.