# AI Prompt: Convert V Language Specs to Rust Hero Models ## Objective Convert V language model specifications (`.v` files) to Rust hero models that integrate with the heromodels framework. The generated Rust models should follow the established patterns for base data embedding, indexing, fluent builder APIs, and Rhai scripting integration. ## V Language Input Structure Analysis ### V Spec Patterns to Recognize: 1. **Module Declaration**: `module circle` or `module group` 2. **Base Embedding**: `core.Base` - represents the base model data 3. **Index Fields**: Fields marked with `@[index]` comments 4. **Mutability**: Fields declared with `pub mut:` 5. **Enums**: `pub enum Status { active, inactive, suspended }` 6. **Nested Structs**: Embedded configuration or related data structures 7. **Collections**: `[]u32`, `[]string`, `map[string]string` 8. **References**: `u32` fields typically represent foreign key references ### Example V Spec Structure: ```v module circle import freeflowuniverse.herolib.hero.models.core pub struct User { core.Base pub mut: username string @[index] // Unique username email []string @[index] // Multiple email addresses status UserStatus // Enum reference profile UserProfile // Nested struct metadata map[string]string // Key-value pairs } pub enum UserStatus { active inactive suspended } pub struct UserProfile { pub mut: full_name string bio string links map[string]string } ``` ## Rust Hero Model Conversion Rules ### 1. File Structure and Imports ```rust use heromodels_core::{Model, BaseModelData, IndexKey}; use heromodels_derive::model; use rhai::CustomType; use rhailib_derive::RhaiApi; use serde::{Deserialize, Serialize}; use chrono::{DateTime, Utc}; ``` ### 2. Base Data Embedding - **V**: `core.Base` - **Rust**: `pub base_data: BaseModelData,` ### 3. Index Field Conversion - **V**: `field_name string @[index]` - **Rust**: `#[index] pub field_name: String,` ### 4. Type Mappings | V Type | Rust Type | |--------|-----------| | `string` | `String` | | `[]string` | `Vec` | | `[]u32` | `Vec` | | `u32` | `u32` | | `u64` | `u64` | | `f64` | `f64` | | `bool` | `bool` | | `map[string]string` | `std::collections::HashMap` | ### 5. Struct Declaration Pattern ```rust /// Documentation comment describing the model #[model] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType, Default, RhaiApi)] pub struct ModelName { /// Base model data pub base_data: BaseModelData, #[index] pub indexed_field: String, pub regular_field: String, pub optional_field: Option, pub nested_struct: NestedType, pub collection: Vec, pub metadata: std::collections::HashMap, } ``` ### 6. Enum Conversion ```rust #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum UserStatus { Active, Inactive, Suspended, } ``` ### 7. Fluent Builder Implementation Every model must implement a fluent builder pattern: ```rust impl ModelName { /// Create a new instance pub fn new(id: u32) -> Self { Self { base_data: BaseModelData::new(id), indexed_field: String::new(), regular_field: String::new(), optional_field: None, nested_struct: NestedType::new(), collection: Vec::new(), metadata: std::collections::HashMap::new(), } } /// Set indexed field (fluent) pub fn indexed_field(mut self, value: impl ToString) -> Self { self.indexed_field = value.to_string(); self } /// Set regular field (fluent) pub fn regular_field(mut self, value: impl ToString) -> Self { self.regular_field = value.to_string(); self } /// Set optional field (fluent) pub fn optional_field(mut self, value: impl ToString) -> Self { self.optional_field = Some(value.to_string()); self } /// Set nested struct (fluent) pub fn nested_struct(mut self, value: NestedType) -> Self { self.nested_struct = value; self } /// Add to collection (fluent) pub fn add_to_collection(mut self, value: u32) -> Self { self.collection.push(value); self } /// Set entire collection (fluent) pub fn collection(mut self, value: Vec) -> Self { self.collection = value; self } /// Add metadata entry (fluent) pub fn add_metadata(mut self, key: impl ToString, value: impl ToString) -> Self { self.metadata.insert(key.to_string(), value.to_string()); self } /// Build the final instance pub fn build(self) -> Self { self } } ``` ### 8. Model Trait Implementation ```rust impl Model for ModelName { fn db_prefix() -> &'static str { "modelname" } fn get_id(&self) -> u32 { self.base_data.id } fn base_data_mut(&mut self) -> &mut BaseModelData { &mut self.base_data } fn db_keys(&self) -> Vec { let mut keys = Vec::new(); // Add index keys for fields marked with #[index] keys.push(IndexKey::new("indexed_field", &self.indexed_field)); // Add additional index keys as needed keys } } ``` ### 9. Nested Struct Builder Pattern For embedded types, implement similar builder patterns: ```rust #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct NestedType { pub field1: String, pub field2: String, } impl NestedType { pub fn new() -> Self { Self { field1: String::new(), field2: String::new(), } } pub fn field1(mut self, value: impl ToString) -> Self { self.field1 = value.to_string(); self } pub fn field2(mut self, value: impl ToString) -> Self { self.field2 = value.to_string(); self } pub fn build(self) -> Self { self } } ``` ## Conversion Steps 1. **Analyze V Spec Structure** - Identify the module name and main structs - Note which fields are marked with `@[index]` - Identify nested structs and enums - Map field types from V to Rust 2. **Create Rust File Structure** - Add appropriate imports - Convert enums first (they're often referenced by structs) - Convert nested structs before main structs 3. **Implement Main Struct** - Add `#[model]` macro and derives - Embed `BaseModelData` as `base_data` - Mark indexed fields with `#[index]` - Convert field types according to mapping table 4. **Implement Builder Pattern** - Add `new(id: u32)` constructor - Add fluent setter methods for each field - Handle optional fields appropriately - Add collection manipulation methods 5. **Implement Model Trait** - Define appropriate `db_prefix` - Implement required trait methods - Add index keys for searchable fields 6. **Add Documentation** - Document the struct and its purpose - Document each field's meaning - Add usage examples in comments ## Example Usage After Conversion ```rust let user = User::new(1) .username("john_doe") .add_email("john@example.com") .add_email("john.doe@company.com") .status(UserStatus::Active) .profile( UserProfile::new() .full_name("John Doe") .bio("Software developer") .build() ) .add_metadata("department", "engineering") .build(); ``` ## Notes and Best Practices 1. **Field Naming**: Convert V snake_case to Rust snake_case (usually no change needed) 2. **Optional Fields**: Use `Option` for fields that may be empty in V 3. **Collections**: Always provide both `add_item` and `set_collection` methods 4. **Error Handling**: Builder methods should not panic; use appropriate defaults 5. **Documentation**: Include comprehensive documentation for public APIs 6. **Testing**: Consider adding unit tests for builder patterns 7. **Validation**: Add validation logic in builder methods if needed ## File Organization Place the converted Rust models in the appropriate subdirectory under `heromodels/src/models/` based on the domain (e.g., `user/`, `finance/`, `governance/`, etc.).