tape-base64 0.1.0

Fast base64 encoding and decoding
Documentation
//! The x86-64 codec: AVX2 or AVX-512VBMI, chosen by asking the processor

use crate::alphabet::Alphabet;

mod avx2;
mod avx512;
mod dispatch;

pub(crate) use dispatch::Path;

#[cfg(feature = "internals")]
pub use dispatch::{available, force, force_stream_floor, AVX2, PORTABLE, UNKNOWN, WIDE};

/// Below this no cache is small enough for streaming, so one compare settles it
#[cfg(not(miri))]
const STREAM_CANDIDATE: usize = 1 << 16;

/// Low enough that an interpreted run reaches the streaming store at all
#[cfg(miri)]
const STREAM_CANDIDATE: usize = 1 << 10;

/// Convert `groups` whole groups, returning how many were converted
pub(crate) fn encode_bulk<A: Alphabet>(input: &[u8], out: &mut [u8], groups: usize) -> usize {
    match dispatch::path() {
        // SAFETY: cpuid reported the path, so the instructions are present.
        Path::Wide => unsafe { avx512::encode_bulk::<A>(input, out, groups) },
        Path::Avx2 => {
            // Asked here, so the ordinary form has neither the test nor the frame it would need.
            let is_streaming = input.len() >= STREAM_CANDIDATE
                && input.len() >= dispatch::stream_floor()
                && out.as_ptr().align_offset(16) == 0;
            // SAFETY: cpuid reported the path, and streaming is chosen only on an aligned output.
            unsafe {
                if is_streaming {
                    avx2::encode_bulk::<A, true>(input, out, groups)
                } else {
                    avx2::encode_bulk::<A, false>(input, out, groups)
                }
            }
        }
        Path::Portable => 0,
    }
}

/// Convert `quads` whole groups, returning how many were converted
pub(crate) fn decode_bulk<A: Alphabet>(input: &[u8], out: &mut [u8], quads: usize) -> usize {
    match dispatch::path() {
        // SAFETY: cpuid reported the path, so the instructions are present.
        Path::Wide => unsafe { avx512::decode_bulk::<A>(input, out, quads) },
        // SAFETY: cpuid reported the path, so the instructions are present.
        Path::Avx2 => unsafe { avx2::decode_bulk::<A>(input, out, quads) },
        Path::Portable => 0,
    }
}