bintext 0.1.3

Encode and decodes binary encoded text into aligned binary blobs using SIMD
Documentation
#![allow(dead_code)]

use super::{alloc, DecodeError, HEX_ENCODE, HEX_NIBBLE_DECODE};

#[inline(always)]
pub fn decode(input: &str) -> Result<Vec<u8>, DecodeError> {
    use DecodeError::*;

    let l = input.len();
    if l & 1 != 0 {
        Err(OddLength)?
    }

    let mut v = alloc(l >> 1);
    decode_noalloc(input.as_bytes(), &mut v[..])?;

    Ok(v)
}

pub fn decode_noalloc(input: &[u8], output: &mut [u8]) -> Result<(), DecodeError> {
    use DecodeError::*;

    let len = input.len();

    let mut i = 0;
    let mut j = 0;

    while i < len {
        unsafe {
            let msn = *HEX_NIBBLE_DECODE.get_unchecked(*input.get_unchecked(i) as usize);
            if msn > 0xf {
                Err(InvalidCharAt(i))?
            }

            let lsn = *HEX_NIBBLE_DECODE.get_unchecked(*input.get_unchecked(i + 1) as usize);
            if lsn > 0xf {
                Err(InvalidCharAt(i + 1))?
            }

            *output.get_unchecked_mut(j) = (msn << 4) | lsn;
            i += 2;
            j += 1;
        }
    }

    Ok(())
}

#[inline(always)]
pub fn encode(input: &[u8]) -> String {
    let mut i = 0usize;
    let mut v = alloc(input.len() << 1);
    unsafe {
        for b in input {
            let j = (*b as usize) << 1;
            *v.get_unchecked_mut(i) = *HEX_ENCODE.get_unchecked(j);
            *v.get_unchecked_mut(i | 1) = *HEX_ENCODE.get_unchecked(j | 1);
            i += 2;
        }
        String::from_utf8_unchecked(v)
    }
}

#[inline(always)]
#[allow(dead_code)]
pub fn meet_requirements() -> bool {
    return true;
}

crate::tests_hex!(super::encode, super::decode, super::meet_requirements);