Add no_std test example and update alloc gating

Update codegen to make `bytes` imports conditional on the `alloc`
feature and add a test example for the `thumbv7em-none-eabihf`
target.
This commit is contained in:
2026-05-18 08:43:22 -07:00
parent fa4d8cca83
commit 6910f11d69
9 changed files with 770 additions and 25 deletions
+5 -13
View File
@@ -6,7 +6,7 @@ use roto_runtime::ProtoAccessor;
use std::collections::{HashMap, HashSet};
use std::str;
const DATA_IMPORTS: &str = "use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator, RotoMessage};\nuse core::str;\nuse bytes::{Bytes, BytesMut, Buf, BufMut};\n";
const DATA_IMPORTS: &str = "use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator, RotoMessage};\nuse core::str;\n#[cfg(feature = \"alloc\")]\nuse bytes::{Bytes, BytesMut, Buf, BufMut};\n";
const SERVICE_IMPORTS: &str = "use tonic::{Request, Response, Status};\nuse tokio_stream::Stream;\nuse std::pin::Pin;\nuse std::sync::Arc;\nuse std::task::{Context, Poll};\nuse std::future::Future;\nuse tonic::body::BoxBody;\nuse tower::Service;\nuse futures_util::StreamExt;\nuse http_body_util::BodyExt;\nuse http_body::Body;\nuse crate::{BufferPool, StatusBody};\n";
pub fn to_pascal_case(s: &str) -> String {
@@ -54,7 +54,7 @@ fn map_type_to_rust_accessor(field_type: i32, label: i32, is_map: bool) -> (Stri
match field_type {
9 => (
"&'a str".to_string(),
"std::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(),
"core::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)".to_string(),
"\"\"".to_string(),
), // TYPE_STRING
1 => (
@@ -665,7 +665,7 @@ pub fn generate_service_code(
set,
files_to_generate,
generate_mod_files,
SERVICE_IMPORTS,
"",
|file_proto, output| {
let package = file_proto.package().unwrap_or("").to_string();
// Services
@@ -727,21 +727,13 @@ pub fn generate_rust_code(
}
fn strip_boilerplate(content: &str) -> String {
// Find the first occurrence of a service definition or a trait
// In our case, the services start after the dependency imports and a newline.
if let Some(idx) = content.find("pub trait ") {
return content[idx..].to_string();
}
if let Some(idx) = content.find("pub struct ") {
// This might be a message, but generate_service_code only generates services (and their server structs)
return content[idx..].to_string();
}
content.to_string()
}
fn write_service(svc_proto: &ServiceDescriptorProto, package: &str, output: &mut String) {
output.push_str(SERVICE_IMPORTS);
let svc_name = to_pascal_case(svc_proto.name().unwrap());
output.push_str(&format!("#[tonic::async_trait]\npub trait {}: Send + Sync + 'static {{\n", svc_name));
output.push_str(&format!("#[async_trait::async_trait]\npub trait {}: Send + Sync + 'static {{\n", svc_name));
for method_res in svc_proto.method() {
let (method_data, _) = method_res.expect("Failed to iterate method");