From 546b74149ea74d16d62d3cf02f9d85c7fb738fbb Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 15 May 2026 14:13:18 -0700 Subject: [PATCH] Fix code generator and add compilation test Correct module paths and accessor usage in the generator to ensure generated code builds. Add a test that verifies this by compiling the generated code in a temporary project. --- .gitignore | 1 + Cargo.lock | 17 ++++++ Cargo.toml | 1 + codegen/helloworld.desc | Bin 0 -> 688 bytes codegen/src/generator.rs | 29 +++++----- codegen/tests/helloworld.desc | Bin 0 -> 688 bytes codegen/tests/test_helloworld_build.rs | 76 +++++++++++++++++++++++++ helloworld.desc | Bin 0 -> 688 bytes 8 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 codegen/helloworld.desc create mode 100644 codegen/tests/helloworld.desc create mode 100644 codegen/tests/test_helloworld_build.rs create mode 100644 helloworld.desc diff --git a/.gitignore b/.gitignore index cabfbbc..18b2942 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ test_types_gen_project test_map_gen_project test_grpc_project artifacts/ +temp_test_project/ diff --git a/Cargo.lock b/Cargo.lock index bf461d3..bba7556 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1352,6 +1352,23 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +[[package]] +name = "temp_test_project" +version = "0.1.0" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "roto-codegen", + "roto-runtime", + "roto-tonic", + "tokio-stream", + "tonic", + "tower 0.4.13", +] + [[package]] name = "tempfile" version = "3.27.0" diff --git a/Cargo.toml b/Cargo.toml index 422753a..be7fc0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "protos", "benches", "roto-tonic", + "temp_test_project", "examples/hello_world", ] diff --git a/codegen/helloworld.desc b/codegen/helloworld.desc new file mode 100644 index 0000000000000000000000000000000000000000..aa9c185dfdf6163ca33213cc23e2ea5471c1f533 GIT binary patch literal 688 zcmZva-%7(U6vmhS*}5~)8c@Q#8M{)%j@3&+uv%8J=!nYD8`-+(2DPbaMST!ozUUU+EpQr5kCKtTqoe4`*{=`K( z_OyUuuCzZ4up?!_7_4k~&j@Ov%{tXJUIH{Gh7=G*V@0>blw?qJt7t?lNe)FLMH#Ur z*%W1pQc{&Jsr>Mvyy5{ z^A&+9X<^_l*a=U$(4m+8jfHc(LuH{eXS)ZsW?Tn5hz|}=+=?m((eXv-BJ6+_#FwFK z;2M}TJaSD8P`wJ{_-x=>%Gsk~c (Stri match field_type { 9 => ( "&'a str".to_string(), - "str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), + "std::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(), "\"\"".to_string(), ), // TYPE_STRING 1 => ( @@ -117,7 +117,7 @@ fn write_enum(enum_proto: &EnumDescriptorProto, output: &mut String) { let accessor = ProtoAccessor::new(val_data).expect("Failed to parse EnumValueDescriptorProto"); let (name_bytes, _) = accessor.get_value(1).expect("Enum value name missing"); - let name = str::from_utf8(name_bytes).expect("Enum value name invalid utf8"); + let name = std::str::from_utf8(name_bytes).expect("Enum value name invalid utf8"); let (num_bytes, _) = accessor.get_value(2).expect("Enum value number missing"); let (num, _) = roto_runtime::read_varint(num_bytes).expect("Enum value number invalid varint"); @@ -147,7 +147,7 @@ fn write_enum(enum_proto: &EnumDescriptorProto, output: &mut String) { let accessor = ProtoAccessor::new(val_data).expect("Failed to parse EnumValueDescriptorProto"); let (name_bytes, _) = accessor.get_value(1).expect("Enum value name missing"); - let name = str::from_utf8(name_bytes).expect("Enum value name invalid utf8"); + let name = std::str::from_utf8(name_bytes).expect("Enum value name invalid utf8"); let (num_bytes, _) = accessor.get_value(2).expect("Enum value number missing"); let (num, _) = roto_runtime::read_varint(num_bytes).expect("Enum value number invalid varint"); @@ -170,6 +170,7 @@ fn write_enum(enum_proto: &EnumDescriptorProto, output: &mut String) { fn write_message(msg_proto: &DescriptorProto, output: &mut String) { let msg_name = to_pascal_case(msg_proto.name().unwrap()); + let mod_name = to_snake_case(msg_proto.name().unwrap()); let mut fields_info = Vec::new(); for field_res in msg_proto.field() { @@ -332,10 +333,12 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { let pascal_oneof_name = to_pascal_case(oneof_name); let snake_oneof_name = to_snake_case(oneof_name); - output.push_str(&format!( - " pub fn which_{}(&self) -> roto_runtime::Result>> {{\n", - snake_oneof_name, msg_name, pascal_oneof_name - )); + let return_type = format!("{}::{}<'a>", mod_name, pascal_oneof_name); + let signature = format!( + " pub fn which_{}(&self) -> roto_runtime::Result > {{\n", + snake_oneof_name, return_type + ); + output.push_str(&signature); for (field_name, _tag, _f_type, _f_label, f_oneof_index, _is_map) in &fields_info { if *f_oneof_index == Some(oneof_index as i32) { let safe_field_name = if field_name == "type" { @@ -348,8 +351,8 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { field_name )); output.push_str(&format!( - " return Ok(Some({}::{} (self.{}()?)));\n", - pascal_oneof_name, safe_field_name, safe_field_name + " return Ok(Some({}::{}::{} (self.{}()?)));\n", + mod_name, pascal_oneof_name, safe_field_name, safe_field_name )); output.push_str(" }\n"); } @@ -414,7 +417,7 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) { " pub fn with(mut self, msg: &{}<'_>) -> roto_runtime::Result {{\n", msg_name )); - output.push_str(" for item in msg.raw_fields() {\n"); + output.push_str(" for item in msg.accessor.raw_fields() {\n"); output.push_str(" let (field_number, raw_bytes) = item?;\n"); output.push_str(" let is_written = match field_number {\n"); for (field_name, _, tag, _, _) in &builder_fields { @@ -563,7 +566,7 @@ pub fn generate_rust_code( for dep_res in file_proto.dependency() { let (dep_data, _) = dep_res.expect("Failed to iterate dependency"); - let dep_name = str::from_utf8(dep_data).expect("Dependency name invalid utf8"); + let dep_name = std::str::from_utf8(dep_data).expect("Dependency name invalid utf8"); let dep_mod_path = dep_name.replace(".proto", "").replace('/', "::"); output.push_str(&format!("use crate::{};\n", dep_mod_path)); } @@ -725,9 +728,7 @@ fn write_service(svc_proto: &ServiceDescriptorProto, output: &mut String) { output.push_str(" let mut buf = pool.get();\n"); output.push_str(" let mut stream = body;\n"); output.push_str(" while let Some(frame_result) = stream.frame().await {\n"); - output.push_str(" let frame = frame_result.map_err(|e| {\n"); - output.push_str(" panic!(\"Body frame error: {}\", e);\n"); - output.push_str(" })?;\n"); + output.push_str(" let frame = frame_result.expect(\"Body frame error\");\n"); output.push_str(" if let Some(data) = frame.data_ref() {\n"); output.push_str(" buf.put(data.clone());\n"); output.push_str(" }\n"); diff --git a/codegen/tests/helloworld.desc b/codegen/tests/helloworld.desc new file mode 100644 index 0000000000000000000000000000000000000000..aa9c185dfdf6163ca33213cc23e2ea5471c1f533 GIT binary patch literal 688 zcmZva-%7(U6vmhS*}5~)8c@Q#8M{)%j@3&+uv%8J=!nYD8`-+(2DPbaMST!ozUUU+EpQr5kCKtTqoe4`*{=`K( z_OyUuuCzZ4up?!_7_4k~&j@Ov%{tXJUIH{Gh7=G*V@0>blw?qJt7t?lNe)FLMH#Ur z*%W1pQc{&Jsr>Mvyy5{ z^A&+9X<^_l*a=U$(4m+8jfHc(LuH{eXS)ZsW?Tn5hz|}=+=?m((eXv-BJ6+_#FwFK z;2M}TJaSD8P`wJ{_-x=>%Gsk~cUUU+EpQr5kCKtTqoe4`*{=`K( z_OyUuuCzZ4up?!_7_4k~&j@Ov%{tXJUIH{Gh7=G*V@0>blw?qJt7t?lNe)FLMH#Ur z*%W1pQc{&Jsr>Mvyy5{ z^A&+9X<^_l*a=U$(4m+8jfHc(LuH{eXS)ZsW?Tn5hz|}=+=?m((eXv-BJ6+_#FwFK z;2M}TJaSD8P`wJ{_-x=>%Gsk~c