From 062048ef6e3e060bcf841ea2ec92e026f09d8da0 Mon Sep 17 00:00:00 2001 From: eichlan Date: Tue, 23 Jun 2026 15:31:51 -0700 Subject: Roorganized into workspace and packages. This is to accomidate a new proc_macro package, which can't have anything else in it. --- derive/Cargo.toml | 10 +++++++ derive/src/lib.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ derive/tests/basic.rs | 15 +++++++++++ 3 files changed, 100 insertions(+) create mode 100644 derive/Cargo.toml create mode 100644 derive/src/lib.rs create mode 100644 derive/tests/basic.rs (limited to 'derive') diff --git a/derive/Cargo.toml b/derive/Cargo.toml new file mode 100644 index 0000000..65f3a75 --- /dev/null +++ b/derive/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "derive" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true + +[dev-dependencies] +crimtag = { path = "../crimtag"} diff --git a/derive/src/lib.rs b/derive/src/lib.rs new file mode 100644 index 0000000..f9c9180 --- /dev/null +++ b/derive/src/lib.rs @@ -0,0 +1,75 @@ +extern crate proc_macro; +use proc_macro::{TokenStream,TokenTree,Ident,Delimiter}; + +#[proc_macro_derive(CrimtagMappable)] +pub fn derive_crimtag_mappable(s: TokenStream) -> TokenStream { + let mut i = s.into_iter(); + while let Some(t) = i.next() { + if let TokenTree::Ident(ident) = t && + ident.to_string() == "struct" { + break; + } + } + let name = if let Some(TokenTree::Ident(ident)) = i.next() { + ident.to_string() + } else { + panic!("No name found in struct."); + }; + + // TODO: Expand this to include the generic parameters and the where? at + // least the parameters. + println!("struct name: {:?}", name); + + let mut newfunc = format!( +r#"impl<'a> crimtag::MappedStructure<'a> for {} {{ + fn get_value(&'a self, id: &str) -> Option> {{ + match id {{ +"#, name); + + // We're going to cheat. Every field name is followed directly by a colon, + // so all we really need to do is hunt for colons and then take the + // previous item. + + while let Some(n) = i.next() { + if let TokenTree::Group(g) = &n && + g.delimiter() == Delimiter::Brace { + // Operate on the struct members. + let mut gi = g.stream().into_iter(); + let mut cur = 0usize; + let mut tok = [gi.next(), gi.next()]; + loop { + if let Some(TokenTree::Punct(ch)) = &tok[(cur+1)%2] && + ch.as_char() == ':' && + let Some(TokenTree::Ident(id)) = &tok[cur] { + println!("!!!!!!!!!! -> {}", id); + newfunc.push_str(&format!( +r#" "{}" => Some(self.{}.into()), +"#, id, id)); + } + println!(" - {:?} {:?}", tok[cur], tok[(cur+1)%2] ); + // Update next. + if let Some(ni) = gi.next() { + tok[cur].replace( ni ); + cur = (cur+1)%2; + } else { + break; + } + } + } + } + + newfunc.push_str( +r#" _ => None, + } + } +}"#); + + println!(); + println!(); + println!("{}", newfunc); + println!(); + println!(); + + newfunc.parse().unwrap() +} + diff --git a/derive/tests/basic.rs b/derive/tests/basic.rs new file mode 100644 index 0000000..18fc366 --- /dev/null +++ b/derive/tests/basic.rs @@ -0,0 +1,15 @@ +use derive::*; +use crimtag::*; + +#[derive(CrimtagMappable)] +pub struct Test { + number: i32, + something: f64, + inner_thing: String, +} + + + +#[test] +fn it_works() { +} -- cgit v1.2.3