sark-gen 0.29.0

Sark proc-macro generators
Documentation
use syn::ext::IdentExt;

pub(crate) fn marker(handler: &syn::Ident) -> syn::Ident {
    encoded("__SarkHandler", handler)
}

pub(crate) fn route(mut route: syn::TypePath) -> syn::TypePath {
    if let Some(segment) = route.path.segments.last_mut()
        && is_function_name(&segment.ident)
    {
        segment.ident = marker(&segment.ident);
    }
    route
}

pub(crate) fn is_function_name(ident: &syn::Ident) -> bool {
    let source = ident.to_string();
    let visible = match source.strip_prefix("r#") {
        Some(visible) => visible,
        None => &source,
    };
    !visible.starts_with("__Sark")
        && visible
            .as_bytes()
            .first()
            .is_some_and(|byte| byte.is_ascii_lowercase() || *byte == b'_')
}

pub(crate) fn encoded(prefix: &str, handler: &syn::Ident) -> syn::Ident {
    const HEX: &[u8; 16] = b"0123456789ABCDEF";

    let source = handler.unraw().to_string();
    let mut name = String::from(prefix);
    let mut upper = true;
    for ch in source.chars() {
        if ch == '_' {
            upper = true;
        } else if upper {
            name.extend(ch.to_uppercase());
            upper = false;
        } else {
            name.push(ch);
        }
    }
    name.push('X');
    for byte in source.bytes() {
        name.push(char::from(HEX[usize::from(byte >> 4)]));
        name.push(char::from(HEX[usize::from(byte & 0x0f)]));
    }
    syn::Ident::new(&name, handler.span())
}