use crate::{Alphabet, DecodeError, scalar};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum DecodeBackend {
Scalar,
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
Avx512Vbmi,
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
Avx2,
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
Ssse3Sse41,
#[cfg(all(
feature = "simd",
feature = "std",
target_arch = "aarch64",
target_endian = "little"
))]
Neon,
}
#[must_use]
pub(crate) fn active_decode_backend() -> DecodeBackend {
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
{
if crate::simd::avx512_decode_available() {
return DecodeBackend::Avx512Vbmi;
}
if crate::simd::avx2_decode_available() {
return DecodeBackend::Avx2;
}
if crate::simd::ssse3_sse41_decode_available() {
return DecodeBackend::Ssse3Sse41;
}
}
#[cfg(all(
feature = "simd",
feature = "std",
target_arch = "aarch64",
target_endian = "little"
))]
{
if crate::simd::neon_available() {
return DecodeBackend::Neon;
}
}
DecodeBackend::Scalar
}
pub(crate) fn decode_slice<A, const PAD: bool>(
input: &[u8],
output: &mut [u8],
) -> Result<usize, DecodeError>
where
A: Alphabet,
{
match active_decode_backend() {
DecodeBackend::Scalar => scalar::decode_slice::<A, PAD>(input, output),
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
DecodeBackend::Avx512Vbmi => crate::simd::decode_slice_avx512::<A, PAD>(input, output),
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
DecodeBackend::Avx2 => crate::simd::decode_slice_avx2::<A, PAD>(input, output),
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
DecodeBackend::Ssse3Sse41 => crate::simd::decode_slice_ssse3_sse41::<A, PAD>(input, output),
#[cfg(all(
feature = "simd",
feature = "std",
target_arch = "aarch64",
target_endian = "little"
))]
DecodeBackend::Neon => crate::simd::decode_slice_neon::<A, PAD>(input, output),
}
}
#[cfg(test)]
mod tests {
use super::{DecodeBackend, active_decode_backend};
#[test]
fn boundary_uses_only_admitted_backends() {
let backend = active_decode_backend();
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
if backend == DecodeBackend::Avx512Vbmi {
assert!(crate::simd::avx512_decode_available());
return;
}
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
if backend == DecodeBackend::Avx2 {
assert!(crate::simd::avx2_decode_available());
return;
}
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
if backend == DecodeBackend::Ssse3Sse41 {
assert!(crate::simd::ssse3_sse41_decode_available());
return;
}
#[cfg(all(
feature = "simd",
feature = "std",
target_arch = "aarch64",
target_endian = "little"
))]
if backend == DecodeBackend::Neon {
assert!(crate::simd::neon_available());
return;
}
assert_eq!(backend, DecodeBackend::Scalar);
}
}