From ea86b6a98a242e603ca7350c8150205ab6db39bb Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:56:20 +0200 Subject: [PATCH] feat: add wasm32 arch, implement check --- .github/workflows/ci.yml | 9 ++++++++- src/arch/mod.rs | 3 +++ src/arch/wasm32.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/arch/wasm32.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06283d5..ea7364e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,15 @@ jobs: strategy: fail-fast: false matrix: - target: [aarch64-unknown-linux-gnu, i686-unknown-linux-gnu, x86_64-unknown-linux-gnu] + target: + - aarch64-unknown-linux-gnu + - i686-unknown-linux-gnu + - x86_64-unknown-linux-gnu + - wasm32-wasip1 rust: [nightly, stable, 1.64] + exclude: + - target: wasm32-wasip1 + rust: 1.64 timeout-minutes: 30 steps: - uses: actions/checkout@v4 diff --git a/src/arch/mod.rs b/src/arch/mod.rs index e614e3c..e223620 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -13,6 +13,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_arch = "aarch64")] { pub(crate) mod aarch64; pub(crate) use aarch64 as imp; + } else if #[cfg(target_arch = "wasm32")] { + pub(crate) mod wasm32; + pub(crate) use wasm32 as imp; } else { pub(crate) use generic as imp; } diff --git a/src/arch/wasm32.rs b/src/arch/wasm32.rs new file mode 100644 index 0000000..b3107c8 --- /dev/null +++ b/src/arch/wasm32.rs @@ -0,0 +1,40 @@ +use super::generic; +use core::arch::wasm32::*; + +pub(crate) const USE_CHECK_FN: bool = false; + +pub(crate) use generic::{decode_checked, decode_unchecked, encode}; + +#[inline(always)] +fn is_available() -> bool { + cfg!(target_feature = "simd128") +} + +#[inline] +pub(crate) fn check(input: &[u8]) -> bool { + if !is_available() { + return generic::check(input); + } + unsafe { check_simd128(input) } +} + +#[target_feature(enable = "simd128")] +unsafe fn check_simd128(input: &[u8]) -> bool { + generic::check_unaligned_chunks(input, |chunk: v128| { + let ge0 = u8x16_ge(chunk, u8x16_splat(b'0')); + let le9 = u8x16_le(chunk, u8x16_splat(b'9')); + let valid_digit = v128_and(ge0, le9); + + let geua = u8x16_ge(chunk, u8x16_splat(b'A')); + let leuf = u8x16_le(chunk, u8x16_splat(b'F')); + let valid_upper = v128_and(geua, leuf); + + let gela = u8x16_ge(chunk, u8x16_splat(b'a')); + let lelf = u8x16_le(chunk, u8x16_splat(b'f')); + let valid_lower = v128_and(gela, lelf); + + let valid_letter = v128_or(valid_lower, valid_upper); + let valid = v128_or(valid_digit, valid_letter); + u8x16_all_true(valid) + }) +}