bindex: contained fjall code

This commit is contained in:
nym21
2025-01-27 23:25:28 +01:00
parent 90a5c4fbf8
commit d68c6f9f2e
172 changed files with 397 additions and 254 deletions

View File

@@ -0,0 +1,17 @@
[package]
name = "struct_iterable_derive"
version = "0.1.0"
authors = ["André de Moraes <deco.moraes@icloud.com>"]
edition = "2021"
description = "An internal crate for struct_iterable"
license = "MIT"
[lib]
proc-macro = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
syn = "2.0.85"
quote = "1.0.37"
proc-macro2 = "1.0.89"
struct_iterable_internal = { path = "../struct_iterable_internal" }

View File

@@ -0,0 +1,7 @@
# Struct Iterable Derive
This crate is a supporting library for the `struct_iterable` crate. It provides the proc macro `Iterable` which is used in conjunction with the `struct_iterable_internal` crate to provide an easy way to make a struct iterable in Rust.
**Please note:** This crate is not intended to be used directly. If you want to make your structs iterable, please use the `struct_iterable` crate instead.
Please visit the [`struct_iterable` crate on crates.io](https://crates.io/crates/struct_iterable) for more information and usage examples.

View File

@@ -0,0 +1,88 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
/// The `Iterable` proc macro.
///
/// Deriving this macro for your struct will make it "iterable". An iterable struct allows you to iterate over its fields, returning a tuple containing the field name as a static string and a reference to the field's value as `dyn Any`.
///
/// # Limitations
///
/// - Only structs are supported, not enums or unions.
/// - Only structs with named fields are supported.
///
/// # Usage
///
/// Add the derive attribute (`#[derive(Iterable)]`) above your struct definition.
///
/// ```
/// use struct_iterable::Iterable;
///
/// #[derive(Iterable)]
/// struct MyStruct {
/// field1: i32,
/// field2: String,
/// }
/// ```
///
/// You can now call the `iter` method on instances of your struct to get an iterator over its fields:
///
/// ```
/// let my_instance = MyStruct {
/// field1: 42,
/// field2: "Hello, world!".to_string(),
/// };
///
/// for (field_name, field_value) in my_instance.iter() {
/// println!("{}: {:?}", field_name, field_value);
/// }
/// ```
#[proc_macro_derive(Iterable)]
pub fn derive_iterable(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let struct_name = input.ident;
let fields = match input.data {
Data::Struct(data_struct) => match data_struct.fields {
Fields::Named(fields_named) => fields_named.named,
_ => panic!("Only structs with named fields are supported"),
},
_ => panic!("Only structs are supported"),
};
let fields_iter = fields.iter().map(|field| {
let field_ident = &field.ident;
let field_name = field_ident.as_ref().unwrap().to_string();
quote! {
(#field_name, &(self.#field_ident) as &dyn std::any::Any)
}
});
let fields_iter_mut = fields.iter().map(|field| {
let field_ident = &field.ident;
let field_name = field_ident.as_ref().unwrap().to_string();
quote! {
(#field_name, &mut (self.#field_ident) as &mut dyn std::any::Any)
}
});
let expanded = quote! {
impl Iterable for #struct_name {
fn iter<'a>(&'a self) -> std::vec::IntoIter<(&'static str, &'a dyn std::any::Any)> {
vec![
#(#fields_iter),*
].into_iter()
}
fn iter_mut<'a>(&'a mut self) -> std::vec::IntoIter<(&'static str, &'a mut dyn std::any::Any)> {
vec![
#(#fields_iter_mut),*
].into_iter()
}
}
};
TokenStream::from(expanded)
}