5.5 KiB
Here's an updated full project specification including: 1. ✅ Unified builder for both creation and filtering 2. ✅ with_...() methods used for both creation and filtering 3. ✅ Auto-generated CRUD + list + filter + find methods 4. ✅ Database interface for persistence operations 5. ✅ Auto-generated registration code 6. ✅ 📜 Example Rhai script 7. ✅ 🔍 build.rs should output to src/gen/meeting_builder.rs
⸻
🧾 Project Spec: Rust → Rhai Builder Code Generator
🎯 Goal
Build a build.rs script that parses Rust structs annotated with #[builder] and generates Rhai-compatible unified builders with with_...() methods that populate a single field map used for both creation and filtering. Also generate CRUD operations that use a database interface.
⸻
📥 Input Example: src/models.rs
#[derive(Debug)] pub struct Meeting { pub id: String, pub title: String, pub description: String, pub participants: Vec, pub start: String, }
⸻
📤 Generated Code: src/gen/meeting_builder.rs
✅ 1. MeetingBuilder Struct
#[derive(Clone)] pub struct MeetingBuilder { pub fields: std::collections::HashMap<String, rhai::Dynamic>, }
✅ 2. with_...() Methods (for each field)
impl MeetingBuilder { pub fn with_title(mut self, value: &str) -> Self { self.fields.insert("title".into(), value.into()); self }
pub fn with_participants(mut self, value: Vec<rhai::Dynamic>) -> Self {
self.fields.insert("participants".into(), value.into());
self
}
pub fn get_fields(&mut self) -> rhai::Map {
self.fields.clone()
}
// CRUD operations
pub fn create(&mut self, db: &dyn Database) -> rhai::Dynamic {
db.create("meetings", self.get_fields())
}
pub fn find_by_id(&mut self, db: &dyn Database, id: &str) -> rhai::Dynamic {
db.find_by_id("meetings", id)
}
pub fn update(&mut self, db: &dyn Database, id: &str) -> rhai::Dynamic {
db.update("meetings", id, self.get_fields())
}
pub fn delete(&mut self, db: &dyn Database, id: &str) -> rhai::Dynamic {
db.delete("meetings", id)
}
pub fn list(&mut self, db: &dyn Database) -> rhai::Dynamic {
db.list("meetings")
}
pub fn filter(&mut self, db: &dyn Database) -> rhai::Dynamic {
db.filter("meetings", self.get_fields())
}
pub fn find(&mut self, db: &dyn Database) -> rhai::Dynamic {
db.find("meetings", self.get_fields())
}
}
✅ 3. Database Interface
pub trait Database { fn create(&self, collection: &str, fields: rhai::Map) -> rhai::Dynamic; fn find_by_id(&self, collection: &str, id: &str) -> rhai::Dynamic; fn update(&self, collection: &str, id: &str, fields: rhai::Map) -> rhai::Dynamic; fn delete(&self, collection: &str, id: &str) -> rhai::Dynamic; fn list(&self, collection: &str) -> rhai::Dynamic; fn filter(&self, collection: &str, query: rhai::Map) -> rhai::Dynamic; fn find(&self, collection: &str, query: rhai::Map) -> rhai::Dynamic; }
✅ 4. Rhai Registration
pub fn register_meeting_module(engine: &mut rhai::Engine) { engine.register_type::(); engine.register_fn("meeting", MeetingBuilder::new);
engine.register_fn("with_title", MeetingBuilder::with_title);
engine.register_fn("with_participants", MeetingBuilder::with_participants);
engine.register_fn("get_fields", MeetingBuilder::get_fields);
// Register CRUD operations
engine.register_fn("create", MeetingBuilder::create);
engine.register_fn("find_by_id", MeetingBuilder::find_by_id);
engine.register_fn("update", MeetingBuilder::update);
engine.register_fn("delete", MeetingBuilder::delete);
engine.register_fn("list", MeetingBuilder::list);
engine.register_fn("filter", MeetingBuilder::filter);
engine.register_fn("find", MeetingBuilder::find);
}
⸻
✅ Example Rhai Script
// Create a meeting let meeting_id = meeting() .with_title("Project Sync") .with_description("Check in with the team") .with_participants(["timur", "eda"]) .with_start("2024-06-01T10:00") .create(db);
// Find a meeting by ID let meeting = meeting().find_by_id(db, meeting_id);
// Update a meeting meeting() .with_description("Updated description") .update(db, meeting_id);
// Delete a meeting meeting().delete(db, meeting_id);
// List all meetings let all_meetings = meeting().list(db);
// Filter meetings by description let filtered_meetings = meeting() .with_description("Project Sync") .filter(db);
// Find a specific meeting let found_meeting = meeting() .with_title("Project Sync") .with_start("2024-06-01T10:00") .find(db);
This script uses the same builder for all operations.
⸻
📂 Output File
Write generated code to:
src/gen/meeting_builder.rs
And include it in main.rs:
#[path = "gen/meeting_builder.rs"] mod meeting_builder;
⸻
🔨 build.rs Responsibilities • Use syn to parse src/models.rs • Extract structs and fields • Generate: • MeetingBuilder struct with fields map • All with_...() methods for Rhai • get_fields() method • CRUD + list + filter + find methods • Database trait • register_meeting_module(engine: &mut Engine) function
Output to src/gen/meeting_builder.rs.
⸻
✅ Success Criteria • No duplication between filter/create logic • Fluent API in Rhai • Generated code compiles and integrates • build.rs works as part of standard Rust build pipeline • Easy to extend to more models (e.g., User, Task) • Complete CRUD operations available • Database abstraction for persistence
⸻