| Crates.io | easy-macros-helpers |
| lib.rs | easy-macros-helpers |
| version | 0.1.0 |
| created_at | 2025-11-15 15:46:13.979089+00 |
| updated_at | 2025-11-15 15:46:13.979089+00 |
| description | Easy Macros support library |
| homepage | https://github.com/LimitLost/easy-macros |
| repository | https://github.com/LimitLost/easy-macros |
| max_upload_size | |
| id | 1934482 |
| size | 106,996 |
Use the parent crate instead.
Easy Macros Helpers is a collection of utility functions provided and used by the Easy Macros crate
context! - Generate context strings for error handling with automatic file/line informationTokensBuilder - Accumulate and combine token streams with methods insidereadable_token_stream - Format token strings for better readabilitytoken_stream_to_consistent_string - Normalize token representation across contextsparse_macro_input! - Enhanced version of syn's macro that returns Ok(TokenStream) on parse errors (instead of TokenStream)expr_error_wrap with CompileErrorProvider trait - Wrap expressions with compile-time error reportingindexed_name - Generate indexed identifiers (field0, field1, etc.)find_crate - Locate crate references for generated code (supports renaming)find_crate_list - Try multiple crates, return first foundcontext! for Error Handlinguse std::fs;
fn load_config() -> anyhow::Result<String> {
// Context with a custom message - this will be the failing operation
fs::read_to_string("settings.json")
.with_context(context!("Failed to load application settings"))
}
let result = load_config();
assert!(result.is_err());
let error_msg = format!("{:?}", result.unwrap_err());
assert!(
error_msg.contains(
format!(
"src/examples.rs:{}\r\nFailed to load application settings",
line!() - 11 // context! is called 11 lines above
)
.as_str()
)
);
TokensBuilder for Token Accumulationlet mut result = TokensBuilder::default();
// Add multiple token streams
result.add(quote! {
println!("Hello");
});
result.add(quote! {
println!("World");
});
// Wrap everything in braces
result.braced();
// Get final result
let tokens = result.finalize();
assert_eq!(
readable_token_stream(&tokens.to_string()),
"{ println!(\"Hello\"); println!(\"World\"); }"
);
Result<TokenStream, ...> with parse_macro_input!#[proc_macro]
#[anyhow_result]
fn my_macro(input: TokenStream) -> anyhow::Result<TokenStream> {
//This doesn't return TokenStream on compile errors, but Ok(TokenStream) with compile_error! inside
let parsed = parse_macro_input!(input as syn::DeriveInput);
// Process parsed input...
Ok(quote::quote! {
// Generated code
}.into())
}
let field_names = indexed_name(syn::parse_quote!(field), 3);
let output = quote! {
struct MyStruct {
#(#field_names: i32,)*
}
};
assert_eq!(
readable_token_stream(&output.to_string()),
"struct MyStruct { field0: i32, field1: i32, field2: i32, }"
);
let mut errors = Vec::<String>::new();
let mut expr = syn::parse_quote!(some_expression);
// Add some errors
errors.push("This field is required".to_string());
errors.push("Invalid type specified".to_string());
// Wrap expression with compile errors
expr_error_wrap(&mut expr, &mut errors);
assert_eq!(
quote! { #expr }.to_string(),
quote! {
{
compile_error!("This field is required");
compile_error!("Invalid type specified");
some_expression
}
}
.to_string()
);
if let Some(path) = find_crate("serde", quote!(::Serialize)) {
// Use path in generated code
}
// Handles renamed crates automatically
// If Cargo.toml has: serde_renamed = { package = "serde", version = "1.0" }
// The above will return: serde_renamed::Serialize
// Try multiple crates with fallbacks
let async_crates = &[
("tokio", quote!(::runtime::Runtime)),
("async-std", quote!(::task)),
("smol", quote!()),
];
if let Some(async_path) = find_crate_list(async_crates) {
// Uses first available async runtime
}