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.
This commit is contained in:
2026-05-15 14:13:18 -07:00
parent 372eab94d4
commit 546b74149e
8 changed files with 110 additions and 14 deletions
+15 -14
View File
@@ -51,7 +51,7 @@ fn map_type_to_rust_accessor(field_type: i32, label: i32, is_map: bool) -> (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<Option<{}::{}<'a>>> {{\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<Option<{}> > {{\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<Self> {{\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");