From a2a5c12235254abfffebf71bc97e30f1c7572d67 Mon Sep 17 00:00:00 2001 From: charles Date: Sun, 3 May 2026 14:00:20 -0700 Subject: [PATCH] Escape 'type' keyword in generated Rust code Use raw identifiers for fields named "type" to avoid conflicts with the Rust keyword. Fix field number indexing in tests. --- AGENTS.md | 19 +++++++++++++++++++ src/generator.rs | 8 +++++--- src/lib.rs | 2 +- 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a409916 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,19 @@ +## Ask for clarification + +Unless the request is extremely clear, assemble a list of questions up front. After you begin work, +you should be able to work without user assistance. + +## Coding + +If you are writing code, write tests first. The tests must pass for your work to be complete. + +## Special instructions + +### Fork + +If the users asks you to fork off and work on something, this means that you should: + +1. Create a temporary directory using `mktemp -d` +2. Create a new branch to work on +3. Use git worktree to extract that branch to the temporary directory (i.e., `git worktree add $TMP_DIR -- $BRANCH) +4. Work from that directory (i.e., `cd $TMP_DIR`) diff --git a/src/generator.rs b/src/generator.rs index 1cf25c0..12944dd 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -224,11 +224,12 @@ pub fn generate_rust_code(set: &FileDescriptorSet) -> String { // Field Accessors for (field_name, tag, f_type, f_label) in fields_info { let (rust_type, logic) = map_type_to_rust_accessor(f_type, f_label); + let safe_name = if field_name == "type" { format!("r#{}", field_name) } else { field_name.clone() }; if f_label == 3 { output.push_str(&format!( " pub fn {}(&self) -> {} {{\n", - field_name, rust_type + safe_name, rust_type )); output.push_str(&format!( " match (self.{}_start, self.{}_end) {{\n", @@ -246,7 +247,7 @@ pub fn generate_rust_code(set: &FileDescriptorSet) -> String { } else { output.push_str(&format!( " pub fn {}(&self) -> Result<{}> {{\n", - field_name, rust_type + safe_name, rust_type )); output.push_str(&format!( " let offset = self.{}_offset.ok_or(RotoError::FieldNotFound)?;\n", @@ -275,6 +276,7 @@ pub fn generate_rust_code(set: &FileDescriptorSet) -> String { let (field_data, _) = field_res.expect("Failed to iterate field"); let field_proto = FieldDescriptorProto::new(field_data).expect("Failed to parse FieldDescriptorProto"); let field_name = field_proto.name().unwrap(); + let safe_name = if field_name == "type" { format!("r#{}", field_name) } else { field_name.to_string() }; let tag = field_proto.number().unwrap(); let f_type = field_proto.field_type().unwrap() as i32; @@ -283,7 +285,7 @@ pub fn generate_rust_code(set: &FileDescriptorSet) -> String { output.push_str(&format!( " pub fn {}(mut self, value: {}) -> Result {{\n self.builder.{}({}, value)?;\n Ok(self)\n }}\n\n", - field_name, rust_type, method, tag + safe_name, rust_type, method, tag )); } diff --git a/src/lib.rs b/src/lib.rs index 22baed7..945519f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -520,7 +520,7 @@ mod tests { // Validate that fields appear in the expected relative order let field_numbers: Vec = acc.fields() - .map(|r| r.expect("Failed to decode field").0.field_number) + .map(|r| r.expect("Failed to decode field").1.field_number) .collect(); let essential_fields = [1, 2, 3, 14, 16, 20];