diff --git a/Cargo.lock b/Cargo.lock index 5fe6ec4..ac9311d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 422753a..557325a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/codegen/src/bin/generator.rs b/codegen/src/bin/generator.rs deleted file mode 100644 index fe0f0de..0000000 --- a/codegen/src/bin/generator.rs +++ /dev/null @@ -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>, -} - -fn main() -> Result<(), Box> { - 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(()) -} diff --git a/codegen/src/generator.rs b/codegen/src/generator.rs index c9e2cf5..4522635 100644 --- a/codegen/src/generator.rs +++ b/codegen/src/generator.rs @@ -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 {\n"); output.push_str(&format!(" Ok(Owned{} {{ data: buf }})\n", msg_name)); output.push_str(" }\n\n"); diff --git a/examples/no_std_test/Cargo.toml b/examples/no_std_test/Cargo.toml new file mode 100644 index 0000000..84cfd5b --- /dev/null +++ b/examples/no_std_test/Cargo.toml @@ -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" diff --git a/examples/no_std_test/src/main.rs b/examples/no_std_test/src/main.rs new file mode 100644 index 0000000..14f006a --- /dev/null +++ b/examples/no_std_test/src/main.rs @@ -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 {} +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8fc0e66..2ab111e 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -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 = [] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 1e675f3..56a902b 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -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 = std::result::Result; +pub type Result = core::result::Result; 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"]);