#![allow(non_snake_case)]
#![allow(clippy::tabs_in_doc_comments)]
#![allow(clippy::needless_doctest_main)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![no_std]
#[cfg_attr(docsrs, doc(cfg(feature = "const_buf")))]
#[cfg(any(test, feature = "const_buf"))]
pub mod buf;
#[cfg_attr(docsrs, doc(cfg(feature = "const_data")))]
#[cfg(any(test, feature = "const_data"))]
mod const_data;
#[track_caller]
pub const fn concat_slice_arrays_or_panic<T, const R_LEN: usize>(
a: &'_ [T],
b: &'_ [T],
) -> [T; R_LEN]
where
T: Copy,
{
#[track_caller]
#[inline(never)]
#[cold]
const fn _cold_panic(message: &str) -> ! {
panic!("{}", message)
}
let a_len = a.len();
if R_LEN < (a_len + b.len()) {
_cold_panic("The array size is not enough to accommodate two arrays.");
}
#[cfg_attr(docsrs, doc(cfg(feature = "clufulltransmute")))]
#[cfg(feature = "clufulltransmute")]
{
use cluFullTransmute::transmute_unchecked;
use core::mem::MaybeUninit;
let mut result: [MaybeUninit<T>; R_LEN] = [MaybeUninit::uninit(); R_LEN];
let mut i = 0usize;
while a_len > i {
result[i].write(a[i]);
i += 1;
}
while R_LEN > i {
result[i].write(b[i - a_len]);
i += 1;
}
unsafe { transmute_unchecked(result) }
}
#[cfg_attr(docsrs, doc(cfg(not(feature = "clufulltransmute"))))]
#[cfg(not(feature = "clufulltransmute"))]
{
let mut result: [T; R_LEN] = unsafe { core::mem::zeroed() };
let mut i = 0usize;
while a_len > i {
result[i] = a[i];
i += 1;
}
while R_LEN > i {
result[i] = b[i - a_len];
i += 1;
}
result
}
}
#[doc(hidden)]
pub const unsafe fn debug_validate_then_cast_str(array: &[u8]) -> &str {
debug_assert!(core::str::from_utf8(array).is_ok());
unsafe { core::str::from_utf8_unchecked(array) }
}
#[macro_export]
macro_rules! concat_bytes {
[ $a: expr $(,)?
] => {
$a
};
[ $a: expr $(,)?
] => {
$a
};
[$a: expr $(, $b: expr)* $(,)?] => { $crate::concat_array! {
:&[u8] = $a, $($b),*
}
};
}
#[macro_export]
macro_rules! concat_array {
[ $(:&[$type:ty])? $a: expr $(,)?
] => {
$a
};
[ $(:[$type:ty])? $a: expr $(,)?
] => {
$a
};
[:[$type:ty] = $a: expr, $b: expr $(,)?] => {{ const _A_ARRAY: &[$type] = $a;
const _B_ARRAY: &[$type] = $b;
const _HIDDEN: [$type; {_A_ARRAY.len() + _B_ARRAY.len()}] = $crate::concat_slice_arrays_or_panic::<
$type,
{_A_ARRAY.len() + _B_ARRAY.len()},
>(_A_ARRAY, _B_ARRAY);
_HIDDEN
}};
[:[$type:ty] = $a: expr $(,$b: expr)+ $(,)?] => {{ const _B2: &[$type] = &$crate::concat_array!(:[$type] = $($b),*);
$crate::concat_array! {
:[$type] = $a, _B2
}
}};
[:&[$type:ty] = $a: expr $(, $b: expr)* $(,)?] => { &$crate::concat_array! {
:[$type] = $a $(, $b)*
} as &[_]
};
}
#[macro_export]
macro_rules! concat_str {
[ $a: expr $(,)?
] => {
$a
};
[$a: expr, $b: expr $(,)?] => {{ const _A_STR: &[u8] = core::primitive::str::as_bytes($a);
const _B_STR: &[u8] = core::primitive::str::as_bytes($b);
const _HIDDEN: &str = unsafe {
$crate::debug_validate_then_cast_str(
$crate::concat_array! { :&[u8] =
_A_STR,
_B_STR
}
)
};
_HIDDEN
}};
[$a: expr $(, $b: expr)+ $(,)?] => {{ const _STRINEND: &str = $crate::concat_str!($($b),*);
$crate::concat_str! {
$a, _STRINEND
}
}};
}