pub use std::{
self, any, borrow::Cow, default::Default, iter::FromIterator, option::Option::*, sync::OnceLock,
};
use std::{borrow::Borrow, fmt::Debug};
pub use crate::{
bench::{BenchArgs, BenchOptions},
entry::{
BenchEntry, BenchEntryRunner, EntryConst, EntryList, EntryLocation, EntryMeta, EntryType,
GenericBenchEntry, GroupEntry, BENCH_ENTRIES, GROUP_ENTRIES,
},
time::IntoDuration,
};
pub struct ToStringHelper<'a, T: 'static>(pub &'a T);
impl<T: Debug> ToString for ToStringHelper<'_, T> {
#[inline]
fn to_string(&self) -> String {
format!("{:?}", self.0)
}
}
impl<T: ToString> ToStringHelper<'_, T> {
#[allow(clippy::inherent_to_string)]
#[inline]
pub fn to_string(&self) -> String {
self.0.to_string()
}
}
pub trait Arg<T> {
fn get(self) -> T;
}
impl<T> Arg<T> for T {
#[inline]
fn get(self) -> T {
self
}
}
impl<'a, T: ?Sized> Arg<&'a T> for &'a Cow<'a, T>
where
T: ToOwned,
{
#[inline]
fn get(self) -> &'a T {
self
}
}
impl<'a> Arg<&'a str> for &'a String {
#[inline]
fn get(self) -> &'a str {
self
}
}
impl<T: Copy> Arg<T> for &T {
#[inline]
fn get(self) -> T {
*self
}
}
impl<T: Copy> Arg<T> for &&T {
#[inline]
fn get(self) -> T {
**self
}
}
impl<T: Copy> Arg<T> for &&&T {
#[inline]
fn get(self) -> T {
***self
}
}
pub trait IntoThreads<const IMP: u32> {
fn into_threads(self) -> Cow<'static, [usize]>;
}
impl IntoThreads<0> for usize {
#[inline]
fn into_threads(self) -> Cow<'static, [usize]> {
let counts = match self {
0 => &[0],
1 => &[1],
2 => &[2],
_ => return Cow::Owned(vec![self]),
};
Cow::Borrowed(counts)
}
}
impl IntoThreads<0> for bool {
#[inline]
fn into_threads(self) -> Cow<'static, [usize]> {
let counts = if self {
&[0]
} else {
&[1]
};
Cow::Borrowed(counts)
}
}
impl<I> IntoThreads<1> for I
where
I: IntoIterator,
I::Item: Borrow<usize>,
{
#[inline]
fn into_threads(self) -> Cow<'static, [usize]> {
let mut options: Vec<usize> = self.into_iter().map(|i| *i.borrow()).collect();
options.sort_unstable();
options.dedup();
Cow::Owned(options)
}
}
#[inline]
pub fn new_counter_set() -> crate::counter::CounterSet {
Default::default()
}
pub const fn shrink_array<T, const IN: usize, const OUT: usize>(
array: [T; IN],
) -> Option<[T; OUT]> {
use std::mem::ManuallyDrop;
#[repr(C)]
union Transmute<F, I> {
from: ManuallyDrop<F>,
into: ManuallyDrop<I>,
}
let from = ManuallyDrop::new(array);
if OUT <= IN {
Some(unsafe { ManuallyDrop::into_inner(Transmute { from }.into) })
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn into_threads() {
macro_rules! test {
($value:expr, $expected:expr) => {
assert_eq!(IntoThreads::into_threads($value).as_ref(), $expected);
};
}
test!(true, &[0]);
test!(false, &[1]);
test!(0, &[0]);
test!(1, &[1]);
test!(42, &[42]);
test!([0; 0], &[]);
test!([0], &[0]);
test!([0, 0], &[0]);
test!([0, 2, 3, 1], &[0, 1, 2, 3]);
test!([0, 0, 2, 3, 2, 1, 3], &[0, 1, 2, 3]);
}
#[test]
fn shrink_array() {
let values = [1, 2, 3, 4, 5];
let equal: Option<[i32; 5]> = super::shrink_array(values);
assert_eq!(equal, Some(values));
let smaller: Option<[i32; 3]> = super::shrink_array(values);
assert_eq!(smaller, Some([1, 2, 3]));
let larger: Option<[i32; 100]> = super::shrink_array(values);
assert_eq!(larger, None);
}
}