zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
// &str    -> String  | String::from(s) or s.to_string() or s.to_owned()
// &str    -> &[u8]   | s.as_bytes()
// &str    -> Vec<u8> | s.as_bytes().to_vec() or s.as_bytes().to_owned()
// String  -> &str    | &s if possible* else s.as_str()
// String  -> &[u8]   | s.as_bytes()
// String  -> Vec<u8> | s.into_bytes()
// &[u8]   -> &str    | s.to_vec() or s.to_owned()
// &[u8]   -> String  | std::str::from_utf8(s).unwrap(), but don't**
// &[u8]   -> Vec<u8> | String::from_utf8(s).unwrap(), but don't**
// Vec<u8> -> &str    | &s if possible* else s.as_slice()
// Vec<u8> -> String  | std::str::from_utf8(&s).unwrap(), but don't**
// Vec<u8> -> &[u8]   | String::from_utf8(s).unwrap(), but don't**

use prefixed_api_key::PrefixedApiKeyController;
use rand::Rng;
use sha2::Sha256;

use crate::core::error2::Result;

use super::Error;

pub fn to_string<T>(val: T) -> String
where
    T: std::fmt::Display,
{
    format!("{}", val)
}

pub fn bytes_to_string(b: Vec<u8>) -> Result<String> {
    String::from_utf8(b.to_vec()).map_err(Error::run_time)
}

pub fn split_str(str_val: &str, pat: String) -> Vec<&str> {
    str_val.trim().split(&pat).collect::<Vec<&str>>()
}

// 随机生成 16 字节长度的字符串
pub fn generate_random_16_string() -> String {
    let mut rng = rand::rng();

    (0..16)
        .map(|_| {
            let ch = rng.sample(rand::distr::Alphanumeric) as char;

            if rng.random_bool(0.05) {
                '_'
            } else if rng.random_bool(0.01) {
                ')'
            } else {
                ch
            } // 10% 概率变成 '_'
        })
        .collect()
}

// 随机生成 32 字节长度的字符串
pub fn generate_random_32_string() -> String {
    let mut rng = rand::rng();

    (0..32)
        .map(|_| {
            let ch = rng.sample(rand::distr::Alphanumeric) as char;

            if rng.random_bool(0.05) {
                '_'
            } else if rng.random_bool(0.01) {
                ')'
            } else {
                ch
            } // 10% 概率变成 '_'
        })
        .collect()
}

// Prefixed API Key
// mycompany ..._...  BRTRKFsL ..._...  51FwqftsmMDHHbJAMEXXHCgG
// ^                  ^                 ^
// Prefix             Short Token       Long Token
pub fn generate_api_key(prefix: &str) -> String {
    let builder_result = PrefixedApiKeyController::<_, Sha256>::configure()
        .prefix(prefix.to_owned())
        .rng_osrng()
        .short_token_length(16)
        .long_token_length(32)
        .finalize();

    match builder_result {
        Ok(builder_result) => {
            let controller = builder_result;

            // Generate a new PrefixedApiKey
            let (pak, _hash) = controller.generate_key_and_hash();

            // Assert that the returned key matches the hash
            // assert!(controller.check_hash(&pak, &hash));

            pak.to_string()
        }
        Err(e) => {
            log::error!("generate_apk_key: error={:?}", e);
            "".to_string()
        }
    }
}