feat: add to_snake_case_string and to_snake_case_trait dependencies
This commit is contained in:
committed by
Andrew Phillips (aider)
parent
90fd8d013d
commit
091634433b
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -1368,6 +1368,8 @@ dependencies = [
|
||||
"term 1.1.0",
|
||||
"termsize",
|
||||
"thiserror 1.0.69",
|
||||
"to_snake_case_string",
|
||||
"to_snake_case_trait",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
@@ -2511,6 +2513,20 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "to_snake_case_string"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.105",
|
||||
"to_snake_case_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "to_snake_case_trait"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.47.1"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
[package]
|
||||
name = "to_snake_case_string"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
to_snake_case_trait = { path = "../to_snake_case_trait" }
|
||||
@@ -1,79 +0,0 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, Data, DeriveInput};
|
||||
|
||||
/// This is the derive macro function.
|
||||
/// The `#[proc_macro_derive(ToSnakeCaseString)]` attribute tells the compiler
|
||||
/// that this function implements the derive macro for the `ToSnakeCaseString` trait.
|
||||
#[proc_macro_derive(ToSnakeCaseString)]
|
||||
pub fn to_snake_case_string_derive(input: TokenStream) -> TokenStream {
|
||||
// Parse the input tokens into a syntax tree
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
// Get the name of the enum we're deriving for
|
||||
let name = &ast.ident;
|
||||
|
||||
// Ensure we're working with an enum
|
||||
let data_enum = match ast.data {
|
||||
Data::Enum(data) => data,
|
||||
_ => panic!("ToSnakeCaseString can only be derived for enums"),
|
||||
};
|
||||
|
||||
// Iterate over the enum variants and generate a match arm for each one
|
||||
let match_arms = data_enum.variants.iter().map(|variant| {
|
||||
let variant_ident = &variant.ident;
|
||||
// Convert the PascalCase variant name to snake_case for the string literal
|
||||
let snake_case_string = to_snake_case(variant_ident.to_string());
|
||||
|
||||
// Generate the code for a single match arm, e.g.,
|
||||
// `Self::MyVariant => "my_variant".to_string(),`
|
||||
// We ignore variant fields (e.g., `MyVariant(u32)`) by using `..`
|
||||
quote! {
|
||||
#name::#variant_ident { .. } => #snake_case_string.to_string(),
|
||||
}
|
||||
});
|
||||
|
||||
// Generate the full implementation of the trait for the enum
|
||||
let generated = quote! {
|
||||
// This is the implementation of our custom trait
|
||||
impl to_snake_case_trait::ToSnakeCaseString for #name {
|
||||
// This is the implementation of the trait's method
|
||||
fn to_snake_case(&self) -> String {
|
||||
match self {
|
||||
// Expand the generated match arms inside the match block
|
||||
#( #match_arms )*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can also optionally implement the standard `ToString` or `Display` trait
|
||||
impl std::string::ToString for #name {
|
||||
fn to_string(&self) -> String {
|
||||
self.to_snake_case()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for #name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.to_snake_case())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Return the generated code as a TokenStream
|
||||
generated.into()
|
||||
}
|
||||
|
||||
/// Helper function to convert a PascalCase string to a snake_case string.
|
||||
fn to_snake_case(pascal_case: String) -> String {
|
||||
let mut snake = String::new();
|
||||
for (i, ch) in pascal_case.chars().enumerate() {
|
||||
if i > 0 && ch.is_uppercase() {
|
||||
snake.push('_');
|
||||
}
|
||||
snake.push(ch.to_ascii_lowercase());
|
||||
}
|
||||
snake
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[package]
|
||||
name = "to_snake_case_trait"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
@@ -1,3 +0,0 @@
|
||||
pub trait ToSnakeCaseString {
|
||||
fn to_snake_case(&self) -> String;
|
||||
}
|
||||
Reference in New Issue
Block a user