Add tools that help with making code `const`
There are various challenges when making code `const`: making it conditional, awkward copying of slices... This change adds tools that help dealing with these challenges.
This commit is contained in:
parent
3d6151b9e1
commit
f17c0402b7
|
@ -0,0 +1,92 @@
|
||||||
|
//! Contains tools (workarounds) to make implementing `const fn`s easier.
|
||||||
|
|
||||||
|
/// Copies first `$len` bytes from `$slice` and returns them as an array.
|
||||||
|
///
|
||||||
|
/// Returns `None` if `$len > $slice.len()`. `$len` must be (obviously) statically known.
|
||||||
|
/// Calling from non-const context doesn't affect performance.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! copy_byte_array_from_slice {
|
||||||
|
($slice:expr, $len:expr) => {
|
||||||
|
if $len > $slice.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let mut array = [0u8; $len];
|
||||||
|
// Note: produces same assemble as copy_from_slice
|
||||||
|
let mut i = 0;
|
||||||
|
while i < $len {
|
||||||
|
array[i] = $slice[i];
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
Some(array)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub use copy_byte_array_from_slice;
|
||||||
|
|
||||||
|
/// Concatenates two byte slices or byte arrays (or combination) to a single array.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This macro panics if `$len` is not equal to the sum of `$a.len()` and `$b.len()`.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! concat_bytes_to_arr {
|
||||||
|
($a:expr, $b:expr, $len:expr) => {{
|
||||||
|
// avoid repeated eval
|
||||||
|
let a = $a;
|
||||||
|
let b = $b;
|
||||||
|
|
||||||
|
#[allow(unconditional_panic)]
|
||||||
|
let _ = [(); 1][($len != a.len() + b.len()) as usize];
|
||||||
|
|
||||||
|
let mut output = [0u8; $len];
|
||||||
|
let mut i = 0;
|
||||||
|
while i < a.len() {
|
||||||
|
output[i] = $a[i];
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
while i < a.len() + b.len() {
|
||||||
|
output[i] = b[i - a.len()];
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
pub use concat_bytes_to_arr;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
/// Enables const fn in specified Rust version
|
||||||
|
macro_rules! cond_const {
|
||||||
|
($($(#[$attr:meta])* $vis:vis const(in $ver:ident $(= $human_ver:literal)?) fn $name:ident$(<$($gen:tt)*>)?($($args:tt)*) $(-> $ret:ty)? $body:block)+ ) => {
|
||||||
|
$(
|
||||||
|
#[cfg($ver)]
|
||||||
|
$(#[$attr])*
|
||||||
|
$(
|
||||||
|
#[doc = "\nNote: the function is only `const` in Rust "]
|
||||||
|
#[doc = $human_ver]
|
||||||
|
#[doc = "."]
|
||||||
|
)?
|
||||||
|
$vis const fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body
|
||||||
|
|
||||||
|
#[cfg(not($ver))]
|
||||||
|
$(#[$attr])*
|
||||||
|
$vis fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
($($(#[$attr:meta])* $vis:vis const(in $ver:ident $(= $human_ver:literal)?) unsafe fn $name:ident$(<$($gen:tt)*>)?($($args:tt)*) $(-> $ret:ty)? $body:block)+ ) => {
|
||||||
|
$(
|
||||||
|
#[cfg($ver)]
|
||||||
|
$(#[$attr])*
|
||||||
|
$(
|
||||||
|
#[doc = "\nNote: the function is only `const` in Rust "]
|
||||||
|
#[doc = $human_ver]
|
||||||
|
#[doc = " and newer."]
|
||||||
|
)?
|
||||||
|
$vis const unsafe fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body
|
||||||
|
|
||||||
|
#[cfg(not($ver))]
|
||||||
|
$(#[$attr])*
|
||||||
|
$vis unsafe fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub use cond_const;
|
|
@ -20,6 +20,7 @@ extern crate alloc;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
|
pub mod const_tools;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
|
Loading…
Reference in New Issue