doido-controller-macros 0.0.20

Proc-macros for Doido's controller and helper attributes, before_action/after_action filters, and the routes! routing DSL.
Documentation
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse2, ItemStruct, Result};

/// PascalCase/CamelCase → snake_case (`PostsHelper` → `posts_helper`).
fn to_snake_case(s: &str) -> String {
    let mut out = String::with_capacity(s.len() + 4);
    for (i, ch) in s.chars().enumerate() {
        if ch.is_ascii_uppercase() {
            if i != 0 {
                out.push('_');
            }
            out.push(ch.to_ascii_lowercase());
        } else {
            out.push(ch);
        }
    }
    out
}

pub fn expand_helper(_attr: TokenStream, item: TokenStream) -> Result<TokenStream> {
    let input: ItemStruct = parse2(item)?;
    let ident = &input.ident;
    let name = to_snake_case(&ident.to_string());

    Ok(quote! {
        #input

        impl ::doido_controller::Helper for #ident {
            fn helper_name() -> &'static str {
                #name
            }
        }

        impl #ident {
            /// The snake_case helper name (generated by `#[helper]`).
            pub fn helper_name() -> &'static str {
                #name
            }
        }
    })
}