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",
|
"term 1.1.0",
|
||||||
"termsize",
|
"termsize",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
|
"to_snake_case_string",
|
||||||
|
"to_snake_case_trait",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
@@ -2511,6 +2513,20 @@ dependencies = [
|
|||||||
"zerovec",
|
"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]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.47.1"
|
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