terrazzo-terminal 0.2.7

A simple web-based terminal emulator built on Terrazzo.
use std::sync::OnceLock;

use base64::Engine as _;
use base64::prelude::BASE64_STANDARD;
use base64::prelude::BASE64_STANDARD_NO_PAD;
use base64::prelude::BASE64_URL_SAFE;
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
use regex::Regex;

use super::AddConversionFn;
use crate::converter::api::Language;

pub fn add_base64(input: &str, add: &mut impl AddConversionFn) -> bool {
    static BASE64_REGEX: OnceLock<Regex> = OnceLock::new();
    let base64_regex = BASE64_REGEX
        .get_or_init(|| Regex::new(r"^[-_+/A-Za-z0-9 \r\n\t]+(?:=*)[ \r\n\t]*$").unwrap());
    if !base64_regex.is_match(input) {
        return false;
    }
    let input: String = input.split('\n').map(str::trim).collect();
    let Some(input) = parse_base64(&input) else {
        return false;
    };

    let input = &input;
    return [
        add_base64_impl(input, add),
        super::x509::add_x509_base64(input, add),
        super::pkcs7::add_pkcs7(input, add),
        super::asn1::add_asn1(input, add),
    ]
    .into_iter()
    .any(|t| t);
}

fn add_base64_impl(input: &[u8], add: &mut impl AddConversionFn) -> bool {
    let Ok(utf_8) = str::from_utf8(input) else {
        return false;
    };
    add(Language::new("Base 64"), utf_8.into());
    return true;
}

pub(super) fn parse_base64(data: &str) -> Option<Vec<u8>> {
    if !data.contains(['+', '/']) {
        if data.ends_with('=') {
            if let Ok(base64) = BASE64_URL_SAFE.decode(data) {
                return Some(base64);
            }
        } else if let Ok(base64) = BASE64_URL_SAFE_NO_PAD.decode(data) {
            return Some(base64);
        }
    }
    if !data.contains(['-', '_']) {
        if data.ends_with('=') {
            if let Ok(base64) = BASE64_STANDARD.decode(data) {
                return Some(base64);
            }
        } else if let Ok(base64) = BASE64_STANDARD_NO_PAD.decode(data) {
            return Some(base64);
        }
    }
    return None;
}

#[cfg(test)]
mod tests {
    use super::super::tests::GetConversionForTest as _;

    const BASE64: &str = "SGVsbG8gd29ybGQh";

    #[tokio::test]
    async fn base64() {
        let conversion = BASE64.get_conversion("Base 64").await;
        assert_eq!("Hello world!", conversion);
        assert_eq!(vec!["Base 64"], BASE64.get_languages().await);
    }
}