basenc 1.0.0-alpha.1

High-performance SIMD-accelerated Base64, Base32, and hex encoding and decoding with no_std support.
Documentation
use core::arch::wasm32::*;

use super::*;

#[inline]
#[target_feature(enable = "simd128")]
unsafe fn encode_block(src: *const u8, base: &Base64) -> v128 {
	let input = v128_load(src as *const v128);
	let zero = u8x16_splat(0);
	let words = u8x16_shuffle::<2, 1, 0, 16, 5, 4, 3, 16, 8, 7, 6, 16, 11, 10, 9, 16>(input, zero);
	let mask = u32x4_splat(0x3f);
	let i0 = u32x4_shr(words, 18);
	let i1 = i32x4_shl(v128_and(u32x4_shr(words, 12), mask), 8);
	let i2 = i32x4_shl(v128_and(u32x4_shr(words, 6), mask), 16);
	let i3 = i32x4_shl(v128_and(words, mask), 24);
	lookup(v128_or(v128_or(i0, i1), v128_or(i2, i3)), base)
}

#[inline]
#[target_feature(enable = "simd128")]
fn lookup(indices: v128, base: &Base64) -> v128 {
	let upper = u8x16_add(indices, u8x16_splat(b'A'));
	let lower = u8x16_add(indices, u8x16_splat(b'a' - 26));
	let digits = u8x16_add(indices, u8x16_splat(b'0'.wrapping_sub(52)));
	let lower_mask = u8x16_ge(indices, u8x16_splat(26));
	let digit_mask = u8x16_ge(indices, u8x16_splat(52));
	let char62_mask = u8x16_eq(indices, u8x16_splat(62));
	let char63_mask = u8x16_eq(indices, u8x16_splat(63));
	let ascii = v128_bitselect(lower, upper, lower_mask);
	let ascii = v128_bitselect(digits, ascii, digit_mask);
	let ascii = v128_bitselect(u8x16_splat(base.charset[62]), ascii, char62_mask);
	v128_bitselect(u8x16_splat(base.charset[63]), ascii, char63_mask)
}

#[target_feature(enable = "simd128")]
pub unsafe fn encode(mut bytes: &[u8], base: &Base64, pad: Padding, mut dest: *mut u8) -> *mut u8 {
	while bytes.len() >= 16 {
		v128_store(dest as *mut v128, encode_block(bytes.as_ptr(), base));
		bytes = bytes.get_unchecked(12..);
		dest = dest.add(16);
	}
	scalar::encode(bytes, base, pad, dest)
}