wolfcrypt-ring-compat 1.16.4

wolfcrypt-ring-compat is a cryptographic library using wolfSSL for its cryptographic operations. This library strives to be API-compatible with the popular Rust library named ring.
#[cfg(not(feature = "std"))]
use crate::prelude::*;

/// Converts bytes to a lower-case hex string
#[allow(clippy::missing_panics_doc)]
pub fn encode<T: AsRef<[u8]>>(bytes: T) -> String {
    let bytes = bytes.as_ref();
    let mut encoding = String::with_capacity(2 * bytes.len());
    for byte in bytes {
        let upper_val = byte >> 4u8;
        let lower_val = byte & 0x0f;
        // DON'T PANIC: it shouldn't be possible to panic because only bottom 4 bits can be set.
        encoding.push(char::from_digit(u32::from(upper_val), 16).unwrap());
        encoding.push(char::from_digit(u32::from(lower_val), 16).unwrap());
    }
    encoding
}

/// Converts bytes to an upper-case hex string
pub fn encode_upper<T: AsRef<[u8]>>(bytes: T) -> String {
    encode(bytes).to_ascii_uppercase()
}

/// Converts a hex string to a vector of bytes
/// # Errors
/// Returns an error if `hex_str` contains a non-hex digit.
#[allow(clippy::missing_panics_doc)]
pub fn decode(hex_str: &str) -> Result<Vec<u8>, String> {
    let mut bytes = Vec::<u8>::with_capacity(hex_str.len() / 2 + 1);
    let mut current_byte = b'\0';
    let mut index: usize = 0;
    for ch in hex_str.chars() {
        if !ch.is_ascii_hexdigit() {
            return Err("Invalid hex string".to_string());
        }
        #[allow(clippy::cast_possible_truncation)]
        // DON'T PANIC: it should not be possible to panic because we verify above that the character is a
        // hex digit.
        let value = ch.to_digit(16).unwrap() as u8;
        if index % 2 == 0 {
            current_byte = value << 4;
        } else {
            current_byte |= value;
            bytes.push(current_byte);
        }
        index += 1;
    }
    if index % 2 == 1 {
        bytes.push(current_byte);
    }
    Ok(bytes)
}

/// Converts a hex string to a vector of bytes.
/// It ignores any characters that are not valid hex digits.
///
/// # Panics
///
/// Cannot panic in practice: the input is filtered to hex digits before
/// decoding, so `decode` always returns `Ok`.
#[must_use]
pub fn decode_dirty(hex_str: &str) -> Vec<u8> {
    let clean: String = hex_str.chars().filter(char::is_ascii_hexdigit).collect();
    decode(clean.as_str()).unwrap()
}