Support no_std in roto-runtime
Add #![no_std] to the runtime crate and introduce optional std and alloc features. Update the code generator to be compatible and add a no_std_test example. Remove the generator binary.
This commit is contained in:
Generated
+7
@@ -832,6 +832,13 @@ version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
|
||||
|
||||
[[package]]
|
||||
name = "no_std_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"roto-runtime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
|
||||
@@ -6,8 +6,15 @@ members = [
|
||||
"benches",
|
||||
"roto-tonic",
|
||||
"examples/hello_world",
|
||||
"examples/no_std_test",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
"test_gen_project"
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
use clap::Parser;
|
||||
use roto_codegen::generator::generate_rust_code;
|
||||
use roto_codegen::google::protobuf::descriptor::FileDescriptorSet;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
author,
|
||||
version,
|
||||
about = "Generates Rust accessor and builder code from a protobuf descriptor set"
|
||||
)]
|
||||
struct Args {
|
||||
/// Path to the descriptor set file (.desc)
|
||||
#[arg(short, long)]
|
||||
input: PathBuf,
|
||||
|
||||
/// Path to the output directory
|
||||
#[arg(short, long)]
|
||||
output: PathBuf,
|
||||
|
||||
/// Files to generate. If omitted, all files are generated.
|
||||
#[arg(short, long, value_delimiter = ',')]
|
||||
files: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args = Args::parse();
|
||||
let data = fs::read(&args.input)?;
|
||||
let set = FileDescriptorSet::new(&data).expect("Failed to parse FileDescriptorSet");
|
||||
|
||||
let files = generate_rust_code(&set, args.files.as_deref(), true);
|
||||
|
||||
for (filename, content) in files {
|
||||
let path = args.output.join(filename);
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::write(path, content)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -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 std::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;\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 {
|
||||
@@ -440,18 +440,18 @@ fn write_message(msg_proto: &DescriptorProto, output: &mut String) {
|
||||
|
||||
output.push_str(&format!(" pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> {{\n self.builder.finish()\n }}\n}}\n\n"));
|
||||
|
||||
output.push_str(&format!("pub struct Owned{} {{\n", msg_name));
|
||||
output.push_str(&format!("#[cfg(feature = \"alloc\")]\npub struct Owned{} {{\n", msg_name));
|
||||
output.push_str(" pub data: bytes::Bytes,\n");
|
||||
output.push_str("}\n\n");
|
||||
|
||||
output.push_str(&format!("impl roto_runtime::RotoOwned for Owned{} {{\n", msg_name));
|
||||
output.push_str(&format!("#[cfg(feature = \"alloc\")]\nimpl roto_runtime::RotoOwned for Owned{} {{\n", msg_name));
|
||||
output.push_str(&format!(" type Reader<'a> = {}<'a>;\n", msg_name));
|
||||
output.push_str(&format!(" fn reader(&self) -> {}<'_> {{\n", msg_name));
|
||||
output.push_str(&format!(" {}::new(&self.data).expect(\"failed to create reader\")\n", msg_name));
|
||||
output.push_str(" }\n");
|
||||
output.push_str("}\n\n");
|
||||
|
||||
output.push_str(&format!("impl roto_runtime::RotoMessage for Owned{} {{\n", msg_name));
|
||||
output.push_str(&format!("#[cfg(feature = \"alloc\")]\nimpl roto_runtime::RotoMessage for Owned{} {{\n", msg_name));
|
||||
output.push_str(" fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {\n");
|
||||
output.push_str(&format!(" Ok(Owned{} {{ data: buf }})\n", msg_name));
|
||||
output.push_str(" }\n\n");
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "no_std_test"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
roto-runtime = { path = "../../runtime", default-features = false }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
@@ -0,0 +1,16 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use roto_runtime::ProtoAccessor;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
let _data = [0u8; 0];
|
||||
let _ = ProtoAccessor::new(&_data);
|
||||
loop {}
|
||||
}
|
||||
+6
-1
@@ -4,4 +4,9 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.7"
|
||||
bytes = { version = "1.7", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std", "alloc"]
|
||||
std = []
|
||||
alloc = []
|
||||
|
||||
+9
-3
@@ -1,4 +1,9 @@
|
||||
use std::fmt;
|
||||
#![no_std]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
use core::fmt;
|
||||
use bytes::BufMut;
|
||||
|
||||
pub struct MapFieldIterator<'a> {
|
||||
@@ -51,9 +56,10 @@ impl fmt::Display for RotoError {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for RotoError {}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, RotoError>;
|
||||
pub type Result<T> = core::result::Result<T, RotoError>;
|
||||
|
||||
pub trait RotoOwned {
|
||||
type Reader<'a> where Self: 'a;
|
||||
@@ -686,7 +692,7 @@ mod tests {
|
||||
.iter_repeated(18)
|
||||
.map(|r| {
|
||||
let (val, _) = r.expect("Failed to decode repeated string");
|
||||
std::str::from_utf8(val).expect("Invalid utf8")
|
||||
core::str::from_utf8(val).expect("Invalid utf8")
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(repeated_strings, vec!["one", "two", "three"]);
|
||||
|
||||
Reference in New Issue
Block a user