Compare commits

...

8 Commits

Author SHA1 Message Date
charles a3fece24fc Update Orchestrator persona to use subagent tool 2026-05-15 10:52:07 -07:00
charles cc82e990ba Update generated code build test
Use absolute paths for the test project, add roto-tonic and other
dependencies, and capture build output on failure.
2026-05-15 10:49:56 -07:00
charles a9fef01950 Update orchestrator persona instructions
Require the orchestrator to tell subagents which persona they are and
provide the path to the persona file.
2026-05-15 10:30:21 -07:00
charles da7ba47505 Fix generated code and update example integration
Resolve `Result` ambiguity and lifetime issues in generated services.
Use `file_stem` for proto filenames. Make `StatusBody` public in
`roto-tonic` and update the `hello_world` build process.
2026-05-15 10:29:54 -07:00
charles 00b3dcd9a6 Add agent personas for task orchestration
Define roles and workflows for the Orchestrator, Researcher,
Coordinator, and Codemonkey agents, and ignore the artifacts directory.
2026-05-15 09:38:50 -07:00
charles 08be61966c Fix stuff 2026-05-13 23:08:21 -07:00
charles db2bf1bffd Implement buffer pooling in hello_world example
Introduce BufferPool to reuse BytesMut allocations for requests and
responses. Update AGENTS.md to require build and test success.
2026-05-13 09:45:27 -07:00
charles dfdcd8ae46 Add README for hello_world example 2026-05-12 14:16:27 -07:00
21 changed files with 1315 additions and 63 deletions
+1
View File
@@ -3,3 +3,4 @@ test_gen_project
test_types_gen_project test_types_gen_project
test_map_gen_project test_map_gen_project
test_grpc_project test_grpc_project
artifacts/
+2
View File
@@ -7,6 +7,8 @@ you should be able to work without user assistance.
If you are writing code, write tests first. The tests must pass for your work to be complete. If you are writing code, write tests first. The tests must pass for your work to be complete.
Before considering a task complete, make sure that all target build, and all tests suceed.
## Special instructions ## Special instructions
### Fork ### Fork
Generated
+13 -13
View File
@@ -552,6 +552,7 @@ dependencies = [
"http-body", "http-body",
"http-body-util", "http-body-util",
"prost", "prost",
"roto-codegen",
"roto-runtime", "roto-runtime",
"roto-tonic", "roto-tonic",
"tokio", "tokio",
@@ -1168,10 +1169,18 @@ dependencies = [
name = "roto-codegen" name = "roto-codegen"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bytes",
"clap", "clap",
"env_logger", "env_logger",
"futures-util",
"http-body",
"http-body-util",
"log", "log",
"roto-runtime", "roto-runtime",
"roto-tonic",
"tokio-stream",
"tonic",
"tower 0.4.13",
] ]
[[package]] [[package]]
@@ -1186,9 +1195,13 @@ name = "roto-tonic"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-util",
"http-body",
"http-body-util",
"prost", "prost",
"roto-runtime", "roto-runtime",
"tonic", "tonic",
"tower 0.4.13",
] ]
[[package]] [[package]]
@@ -1352,19 +1365,6 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "test_grpc_project"
version = "0.1.0"
dependencies = [
"bytes",
"prost",
"roto-runtime",
"roto-tonic",
"tokio",
"tokio-stream",
"tonic",
]
[[package]] [[package]]
name = "tinytemplate" name = "tinytemplate"
version = "1.2.1" version = "1.2.1"
+1 -1
View File
@@ -4,7 +4,7 @@ members = [
"codegen", "codegen",
"protos", "protos",
"benches", "benches",
"roto-tonic", "test_grpc_project", "roto-tonic",
"examples/hello_world", "examples/hello_world",
] ]
+8
View File
@@ -5,6 +5,14 @@ edition = "2024"
[dependencies] [dependencies]
roto-runtime = { path = "../runtime" } roto-runtime = { path = "../runtime" }
roto-tonic = { path = "../roto-tonic" }
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
log = "0.4" log = "0.4"
env_logger = "0.11" env_logger = "0.11"
bytes = "1.7"
http-body = "1.0"
http-body-util = "0.1"
tower = "0.4"
tonic = "0.12"
tokio-stream = "0.1"
futures-util = "0.3"
+117 -4
View File
@@ -540,17 +540,26 @@ pub fn generate_rust_code(
} }
} }
let rust_file_name = format!("{}.rs", proto_name.replace(".proto", "")); let rust_file_name = format!("{}.rs", std::path::Path::new(proto_name).file_stem().unwrap().to_str().unwrap());
let mut output = String::new(); let mut output = String::new();
output.push_str("// @generated by protoc-gen-roto — do not edit\n"); output.push_str("// @generated by protoc-gen-roto — do not edit\n");
output.push_str("#[allow(unused_imports)]\n\n"); output.push_str("#[allow(unused_imports)]\n\n");
output.push_str("use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator};\n"); output.push_str("use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator, RotoMessage};\n");
output.push_str("use std::str;\n"); output.push_str("use std::str;\n");
output.push_str("use bytes::Bytes;\n"); output.push_str("use bytes::{Bytes, BytesMut, Buf, BufMut};\n");
output.push_str("use tonic::{Request, Response, Status};\n"); output.push_str("use tonic::{Request, Response, Status};\n");
output.push_str("use tokio_stream::Stream;\n"); output.push_str("use tokio_stream::Stream;\n");
output.push_str("use std::pin::Pin;\n\n"); output.push_str("use std::pin::Pin;\n");
output.push_str("use std::sync::Arc;\n");
output.push_str("use std::task::{Context, Poll};\n");
output.push_str("use std::future::Future;\n");
output.push_str("use tonic::body::BoxBody;\n");
output.push_str("use tower::Service;\n");
output.push_str("use futures_util::StreamExt;\n");
output.push_str("use http_body_util::BodyExt;\n");
output.push_str("use http_body::Body;\n");
output.push_str("use roto_tonic::{BufferPool, StatusBody};\n\n");
for dep_res in file_proto.dependency() { for dep_res in file_proto.dependency() {
let (dep_data, _) = dep_res.expect("Failed to iterate dependency"); let (dep_data, _) = dep_res.expect("Failed to iterate dependency");
@@ -681,4 +690,108 @@ fn write_service(svc_proto: &ServiceDescriptorProto, output: &mut String) {
)); ));
} }
output.push_str("}\n\n"); output.push_str("}\n\n");
let server_name = format!("{}Server", svc_name);
output.push_str(&format!("pub struct {} {{\n", server_name));
output.push_str(&format!(" inner: Arc<dyn {}>,\n", svc_name));
output.push_str(" pool: Arc<BufferPool>,\n");
output.push_str("}\n\n");
output.push_str(&format!("impl {} {{\n", server_name));
output.push_str(&format!(" pub fn new(inner: Arc<dyn {}>, pool: Arc<BufferPool>) -> Self {{\n", svc_name));
output.push_str(" Self { inner, pool }\n");
output.push_str(" }\n");
output.push_str("}\n\n");
output.push_str(&format!("impl tonic::server::NamedService for {} {{\n", server_name));
output.push_str(&format!(" const NAME: &'static str = \"{}\";\n", svc_proto.name().unwrap()));
output.push_str("}\n\n");
output.push_str(&format!("impl Service<http::Request<BoxBody>> for {} {{\n", server_name));
output.push_str(" type Response = http::Response<BoxBody>;\n");
output.push_str(" type Error = std::convert::Infallible;\n");
output.push_str(" type Future = Pin<Box<dyn Future<Output = std::result::Result<Self::Response, Self::Error>> + Send>>;\n\n");
output.push_str(" fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<std::result::Result<(), Self::Error>> {\n");
output.push_str(" Poll::Ready(Ok(()))\n");
output.push_str(" }\n\n");
output.push_str(" fn call(&mut self, req: http::Request<BoxBody>) -> Self::Future {\n");
output.push_str(" let inner = self.inner.clone();\n");
output.push_str(" let pool = self.pool.clone();\n");
output.push_str(" Box::pin(async move {\n");
output.push_str(" let path = req.uri().path().to_string();\n");
output.push_str(" let body = req.into_body();\n");
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(" if let Some(data) = frame.data_ref() {\n");
output.push_str(" buf.put(data.clone());\n");
output.push_str(" }\n");
output.push_str(" }\n\n");
output.push_str(" let total_len = buf.len();\n");
output.push_str(" let bytes_vec = buf.split_to(total_len).freeze();\n");
output.push_str(" pool.put(buf);\n");
output.push_str(" if bytes_vec.len() < 5 {\n");
output.push_str(" let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));\n");
output.push_str(" return Ok(http::Response::builder().status(200).body(res_body).unwrap());\n");
output.push_str(" }\n\n");
output.push_str(" let payload = bytes_vec.slice(5..);\n");
output.push_str(" let mut routed = false;\n\n");
let mut methods = Vec::new();
for method_res in svc_proto.method() {
let (method_data, _) = method_res.expect("Failed to iterate method");
let method_proto = MethodDescriptorProto::new(method_data).expect("Failed to parse MethodDescriptorProto");
let method_name = to_snake_case(method_proto.name().unwrap());
let input_full_name = method_proto.input_type().unwrap();
let input_type = input_full_name.split('.').last().unwrap();
let input_owned = format!("Owned{}", input_type);
methods.push((method_name, input_owned));
}
for (method_name, input_owned) in methods {
output.push_str(&format!(" if path == \"/{}/{}\" {{\n", svc_proto.name().unwrap(), method_name));
output.push_str(&format!(" let request_msg = match {}::decode(payload) {{\n", input_owned));
output.push_str(" Ok(msg) => msg,\n");
output.push_str(" Err(e) => {\n");
output.push_str(" let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));\n");
output.push_str(" return Ok(http::Response::builder().status(200).body(res_body).unwrap());\n");
output.push_str(" }\n");
output.push_str(" };\n\n");
output.push_str(&format!(" let response = match inner.{}(Request::new(request_msg)).await {{\n", method_name));
output.push_str(" Ok(res) => res,\n");
output.push_str(" Err(e) => {\n");
output.push_str(" let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));\n");
output.push_str(" return Ok(http::Response::builder().status(200).body(res_body).unwrap());\n");
output.push_str(" }\n");
output.push_str(" };\n\n");
output.push_str(" let response_msg = response.into_inner();\n");
output.push_str(" let response_bytes = response_msg.bytes();\n");
output.push_str(" let mut res_buf = pool.get();\n");
output.push_str(" res_buf.put_u8(0);\n");
output.push_str(" let len = response_bytes.len() as u32;\n");
output.push_str(" res_buf.put_slice(&len.to_be_bytes());\n");
output.push_str(" res_buf.put_slice(&response_bytes);\n");
output.push_str(" let frame_len = res_buf.len();\n");
output.push_str(" let frame = res_buf.split_to(frame_len).freeze();\n");
output.push_str(" pool.put(res_buf);\n");
output.push_str(" let res_body = BoxBody::new(StatusBody(Some(frame)));\n");
output.push_str(" routed = true;\n");
output.push_str(" return Ok(http::Response::builder().status(200).header(\"content-type\", \"application/grpc\").body(res_body).unwrap());\n");
output.push_str(" }\n");
}
output.push_str(" if !routed {\n");
output.push_str(" let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));\n");
output.push_str(" return Ok(http::Response::builder().status(200).body(res_body).unwrap());\n");
output.push_str(" }\n");
output.push_str(" Ok(http::Response::builder().status(200).body(BoxBody::new(StatusBody(None))).unwrap())\n");
output.push_str(" })\n");
output.push_str(" }\n");
output.push_str("}\n");
} }
+98 -1
View File
@@ -1,8 +1,21 @@
// @generated by protoc-gen-roto — do not edit // @generated by protoc-gen-roto — do not edit
#![allow(unused_imports)] #[allow(unused_imports)]
use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator}; use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator};
use std::str; use std::str;
use bytes::{Bytes, BytesMut, Buf, BufMut};
use tonic::{Request, Response, Status};
use tokio_stream::Stream;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::future::Future;
use tonic::body::BoxBody;
use tower::Service;
use futures_util::StreamExt;
use http_body_util::BodyExt;
use http_body::Body;
use roto_tonic::{BufferPool, StatusBody};
use crate::google::protobuf::descriptor; use crate::google::protobuf::descriptor;
@@ -157,6 +170,27 @@ impl<'b> VersionBuilder<'b> {
} }
} }
pub struct OwnedVersion {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedVersion {
type Reader<'a> = Version<'a>;
fn reader(&self) -> Version<'_> {
Version::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedVersion {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedVersion { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct CodeGeneratorRequest<'a> { pub struct CodeGeneratorRequest<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
file_to_generate_start: Option<usize>, file_to_generate_start: Option<usize>,
@@ -333,6 +367,27 @@ impl<'b> CodeGeneratorRequestBuilder<'b> {
} }
} }
pub struct OwnedCodeGeneratorRequest {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedCodeGeneratorRequest {
type Reader<'a> = CodeGeneratorRequest<'a>;
fn reader(&self) -> CodeGeneratorRequest<'_> {
CodeGeneratorRequest::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedCodeGeneratorRequest {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedCodeGeneratorRequest { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct CodeGeneratorResponse<'a> { pub struct CodeGeneratorResponse<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
error_offset: Option<usize>, error_offset: Option<usize>,
@@ -509,6 +564,27 @@ impl<'b> CodeGeneratorResponseBuilder<'b> {
} }
} }
pub struct OwnedCodeGeneratorResponse {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedCodeGeneratorResponse {
type Reader<'a> = CodeGeneratorResponse<'a>;
fn reader(&self) -> CodeGeneratorResponse<'_> {
CodeGeneratorResponse::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedCodeGeneratorResponse {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedCodeGeneratorResponse { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod code_generator_response { pub mod code_generator_response {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -680,5 +756,26 @@ impl<'b> FileBuilder<'b> {
} }
} }
pub struct OwnedFile {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFile {
type Reader<'a> = File<'a>;
fn reader(&self) -> File<'_> {
File::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFile {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFile { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
+749 -1
View File
@@ -1,8 +1,21 @@
// @generated by protoc-gen-roto — do not edit // @generated by protoc-gen-roto — do not edit
#![allow(unused_imports)] #[allow(unused_imports)]
use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator}; use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator};
use std::str; use std::str;
use bytes::{Bytes, BytesMut, Buf, BufMut};
use tonic::{Request, Response, Status};
use tokio_stream::Stream;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::future::Future;
use tonic::body::BoxBody;
use tower::Service;
use futures_util::StreamExt;
use http_body_util::BodyExt;
use http_body::Body;
use roto_tonic::{BufferPool, StatusBody};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -141,6 +154,27 @@ impl<'b> FileDescriptorSetBuilder<'b> {
} }
} }
pub struct OwnedFileDescriptorSet {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFileDescriptorSet {
type Reader<'a> = FileDescriptorSet<'a>;
fn reader(&self) -> FileDescriptorSet<'_> {
FileDescriptorSet::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFileDescriptorSet {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFileDescriptorSet { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct FileDescriptorProto<'a> { pub struct FileDescriptorProto<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
name_offset: Option<usize>, name_offset: Option<usize>,
@@ -542,6 +576,27 @@ impl<'b> FileDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedFileDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFileDescriptorProto {
type Reader<'a> = FileDescriptorProto<'a>;
fn reader(&self) -> FileDescriptorProto<'_> {
FileDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFileDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFileDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct DescriptorProto<'a> { pub struct DescriptorProto<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
name_offset: Option<usize>, name_offset: Option<usize>,
@@ -868,6 +923,27 @@ impl<'b> DescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedDescriptorProto {
type Reader<'a> = DescriptorProto<'a>;
fn reader(&self) -> DescriptorProto<'_> {
DescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod descriptor_proto { pub mod descriptor_proto {
pub struct ExtensionRange<'a> { pub struct ExtensionRange<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
@@ -995,6 +1071,27 @@ impl<'b> ExtensionRangeBuilder<'b> {
} }
} }
pub struct OwnedExtensionRange {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedExtensionRange {
type Reader<'a> = ExtensionRange<'a>;
fn reader(&self) -> ExtensionRange<'_> {
ExtensionRange::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedExtensionRange {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedExtensionRange { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct ReservedRange<'a> { pub struct ReservedRange<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
start_offset: Option<usize>, start_offset: Option<usize>,
@@ -1096,6 +1193,27 @@ impl<'b> ReservedRangeBuilder<'b> {
} }
} }
pub struct OwnedReservedRange {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedReservedRange {
type Reader<'a> = ReservedRange<'a>;
fn reader(&self) -> ReservedRange<'_> {
ReservedRange::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedReservedRange {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedReservedRange { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct ExtensionRangeOptions<'a> { pub struct ExtensionRangeOptions<'a> {
@@ -1249,6 +1367,27 @@ impl<'b> ExtensionRangeOptionsBuilder<'b> {
} }
} }
pub struct OwnedExtensionRangeOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedExtensionRangeOptions {
type Reader<'a> = ExtensionRangeOptions<'a>;
fn reader(&self) -> ExtensionRangeOptions<'_> {
ExtensionRangeOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedExtensionRangeOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedExtensionRangeOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod extension_range_options { pub mod extension_range_options {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -1443,6 +1582,27 @@ impl<'b> DeclarationBuilder<'b> {
} }
} }
pub struct OwnedDeclaration {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedDeclaration {
type Reader<'a> = Declaration<'a>;
fn reader(&self) -> Declaration<'_> {
Declaration::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedDeclaration {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedDeclaration { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct FieldDescriptorProto<'a> { pub struct FieldDescriptorProto<'a> {
@@ -1771,6 +1931,27 @@ impl<'b> FieldDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedFieldDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFieldDescriptorProto {
type Reader<'a> = FieldDescriptorProto<'a>;
fn reader(&self) -> FieldDescriptorProto<'_> {
FieldDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFieldDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFieldDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod field_descriptor_proto { pub mod field_descriptor_proto {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -1945,6 +2126,27 @@ impl<'b> OneofDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedOneofDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedOneofDescriptorProto {
type Reader<'a> = OneofDescriptorProto<'a>;
fn reader(&self) -> OneofDescriptorProto<'_> {
OneofDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedOneofDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedOneofDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct EnumDescriptorProto<'a> { pub struct EnumDescriptorProto<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
name_offset: Option<usize>, name_offset: Option<usize>,
@@ -2146,6 +2348,27 @@ impl<'b> EnumDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedEnumDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedEnumDescriptorProto {
type Reader<'a> = EnumDescriptorProto<'a>;
fn reader(&self) -> EnumDescriptorProto<'_> {
EnumDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedEnumDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedEnumDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod enum_descriptor_proto { pub mod enum_descriptor_proto {
pub struct EnumReservedRange<'a> { pub struct EnumReservedRange<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
@@ -2248,6 +2471,27 @@ impl<'b> EnumReservedRangeBuilder<'b> {
} }
} }
pub struct OwnedEnumReservedRange {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedEnumReservedRange {
type Reader<'a> = EnumReservedRange<'a>;
fn reader(&self) -> EnumReservedRange<'_> {
EnumReservedRange::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedEnumReservedRange {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedEnumReservedRange { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct EnumValueDescriptorProto<'a> { pub struct EnumValueDescriptorProto<'a> {
@@ -2376,6 +2620,27 @@ impl<'b> EnumValueDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedEnumValueDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedEnumValueDescriptorProto {
type Reader<'a> = EnumValueDescriptorProto<'a>;
fn reader(&self) -> EnumValueDescriptorProto<'_> {
EnumValueDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedEnumValueDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedEnumValueDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct ServiceDescriptorProto<'a> { pub struct ServiceDescriptorProto<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
name_offset: Option<usize>, name_offset: Option<usize>,
@@ -2502,6 +2767,27 @@ impl<'b> ServiceDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedServiceDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedServiceDescriptorProto {
type Reader<'a> = ServiceDescriptorProto<'a>;
fn reader(&self) -> ServiceDescriptorProto<'_> {
ServiceDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedServiceDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedServiceDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct MethodDescriptorProto<'a> { pub struct MethodDescriptorProto<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
name_offset: Option<usize>, name_offset: Option<usize>,
@@ -2703,6 +2989,27 @@ impl<'b> MethodDescriptorProtoBuilder<'b> {
} }
} }
pub struct OwnedMethodDescriptorProto {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedMethodDescriptorProto {
type Reader<'a> = MethodDescriptorProto<'a>;
fn reader(&self) -> MethodDescriptorProto<'_> {
MethodDescriptorProto::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedMethodDescriptorProto {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedMethodDescriptorProto { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct FileOptions<'a> { pub struct FileOptions<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
java_package_offset: Option<usize>, java_package_offset: Option<usize>,
@@ -3279,6 +3586,27 @@ impl<'b> FileOptionsBuilder<'b> {
} }
} }
pub struct OwnedFileOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFileOptions {
type Reader<'a> = FileOptions<'a>;
fn reader(&self) -> FileOptions<'_> {
FileOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFileOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFileOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod file_options { pub mod file_options {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -3528,6 +3856,27 @@ impl<'b> MessageOptionsBuilder<'b> {
} }
} }
pub struct OwnedMessageOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedMessageOptions {
type Reader<'a> = MessageOptions<'a>;
fn reader(&self) -> MessageOptions<'_> {
MessageOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedMessageOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedMessageOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct FieldOptions<'a> { pub struct FieldOptions<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
ctype_offset: Option<usize>, ctype_offset: Option<usize>,
@@ -3929,6 +4278,27 @@ impl<'b> FieldOptionsBuilder<'b> {
} }
} }
pub struct OwnedFieldOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFieldOptions {
type Reader<'a> = FieldOptions<'a>;
fn reader(&self) -> FieldOptions<'_> {
FieldOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFieldOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFieldOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod field_options { pub mod field_options {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -4121,6 +4491,27 @@ impl<'b> EditionDefaultBuilder<'b> {
} }
} }
pub struct OwnedEditionDefault {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedEditionDefault {
type Reader<'a> = EditionDefault<'a>;
fn reader(&self) -> EditionDefault<'_> {
EditionDefault::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedEditionDefault {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedEditionDefault { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct FeatureSupport<'a> { pub struct FeatureSupport<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
edition_introduced_offset: Option<usize>, edition_introduced_offset: Option<usize>,
@@ -4297,6 +4688,27 @@ impl<'b> FeatureSupportBuilder<'b> {
} }
} }
pub struct OwnedFeatureSupport {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFeatureSupport {
type Reader<'a> = FeatureSupport<'a>;
fn reader(&self) -> FeatureSupport<'_> {
FeatureSupport::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFeatureSupport {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFeatureSupport { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct OneofOptions<'a> { pub struct OneofOptions<'a> {
@@ -4400,6 +4812,27 @@ impl<'b> OneofOptionsBuilder<'b> {
} }
} }
pub struct OwnedOneofOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedOneofOptions {
type Reader<'a> = OneofOptions<'a>;
fn reader(&self) -> OneofOptions<'_> {
OneofOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedOneofOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedOneofOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct EnumOptions<'a> { pub struct EnumOptions<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
allow_alias_offset: Option<usize>, allow_alias_offset: Option<usize>,
@@ -4576,6 +5009,27 @@ impl<'b> EnumOptionsBuilder<'b> {
} }
} }
pub struct OwnedEnumOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedEnumOptions {
type Reader<'a> = EnumOptions<'a>;
fn reader(&self) -> EnumOptions<'_> {
EnumOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedEnumOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedEnumOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct EnumValueOptions<'a> { pub struct EnumValueOptions<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
deprecated_offset: Option<usize>, deprecated_offset: Option<usize>,
@@ -4752,6 +5206,27 @@ impl<'b> EnumValueOptionsBuilder<'b> {
} }
} }
pub struct OwnedEnumValueOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedEnumValueOptions {
type Reader<'a> = EnumValueOptions<'a>;
fn reader(&self) -> EnumValueOptions<'_> {
EnumValueOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedEnumValueOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedEnumValueOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct ServiceOptions<'a> { pub struct ServiceOptions<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
features_offset: Option<usize>, features_offset: Option<usize>,
@@ -4878,6 +5353,27 @@ impl<'b> ServiceOptionsBuilder<'b> {
} }
} }
pub struct OwnedServiceOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedServiceOptions {
type Reader<'a> = ServiceOptions<'a>;
fn reader(&self) -> ServiceOptions<'_> {
ServiceOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedServiceOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedServiceOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub struct MethodOptions<'a> { pub struct MethodOptions<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
deprecated_offset: Option<usize>, deprecated_offset: Option<usize>,
@@ -5029,6 +5525,27 @@ impl<'b> MethodOptionsBuilder<'b> {
} }
} }
pub struct OwnedMethodOptions {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedMethodOptions {
type Reader<'a> = MethodOptions<'a>;
fn reader(&self) -> MethodOptions<'_> {
MethodOptions::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedMethodOptions {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedMethodOptions { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod method_options { pub mod method_options {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -5277,6 +5794,27 @@ impl<'b> UninterpretedOptionBuilder<'b> {
} }
} }
pub struct OwnedUninterpretedOption {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedUninterpretedOption {
type Reader<'a> = UninterpretedOption<'a>;
fn reader(&self) -> UninterpretedOption<'_> {
UninterpretedOption::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedUninterpretedOption {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedUninterpretedOption { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod uninterpreted_option { pub mod uninterpreted_option {
pub struct NamePart<'a> { pub struct NamePart<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
@@ -5379,6 +5917,27 @@ impl<'b> NamePartBuilder<'b> {
} }
} }
pub struct OwnedNamePart {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedNamePart {
type Reader<'a> = NamePart<'a>;
fn reader(&self) -> NamePart<'_> {
NamePart::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedNamePart {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedNamePart { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct FeatureSet<'a> { pub struct FeatureSet<'a> {
@@ -5657,6 +6216,27 @@ impl<'b> FeatureSetBuilder<'b> {
} }
} }
pub struct OwnedFeatureSet {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFeatureSet {
type Reader<'a> = FeatureSet<'a>;
fn reader(&self) -> FeatureSet<'_> {
FeatureSet::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFeatureSet {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFeatureSet { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod feature_set { pub mod feature_set {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -5846,6 +6426,27 @@ impl<'b> VisibilityFeatureBuilder<'b> {
} }
} }
pub struct OwnedVisibilityFeature {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedVisibilityFeature {
type Reader<'a> = VisibilityFeature<'a>;
fn reader(&self) -> VisibilityFeature<'_> {
VisibilityFeature::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedVisibilityFeature {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedVisibilityFeature { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod visibility_feature { pub mod visibility_feature {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -5923,6 +6524,27 @@ impl<'b> ProtoLimitsFeatureBuilder<'b> {
} }
} }
pub struct OwnedProtoLimitsFeature {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedProtoLimitsFeature {
type Reader<'a> = ProtoLimitsFeature<'a>;
fn reader(&self) -> ProtoLimitsFeature<'_> {
ProtoLimitsFeature::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedProtoLimitsFeature {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedProtoLimitsFeature { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod proto_limits_feature { pub mod proto_limits_feature {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
@@ -6073,6 +6695,27 @@ impl<'b> FeatureSetDefaultsBuilder<'b> {
} }
} }
pub struct OwnedFeatureSetDefaults {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFeatureSetDefaults {
type Reader<'a> = FeatureSetDefaults<'a>;
fn reader(&self) -> FeatureSetDefaults<'_> {
FeatureSetDefaults::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFeatureSetDefaults {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFeatureSetDefaults { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod feature_set_defaults { pub mod feature_set_defaults {
pub struct FeatureSetEditionDefault<'a> { pub struct FeatureSetEditionDefault<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
@@ -6200,6 +6843,27 @@ impl<'b> FeatureSetEditionDefaultBuilder<'b> {
} }
} }
pub struct OwnedFeatureSetEditionDefault {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedFeatureSetEditionDefault {
type Reader<'a> = FeatureSetEditionDefault<'a>;
fn reader(&self) -> FeatureSetEditionDefault<'_> {
FeatureSetEditionDefault::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedFeatureSetEditionDefault {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedFeatureSetEditionDefault { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct SourceCodeInfo<'a> { pub struct SourceCodeInfo<'a> {
@@ -6278,6 +6942,27 @@ impl<'b> SourceCodeInfoBuilder<'b> {
} }
} }
pub struct OwnedSourceCodeInfo {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedSourceCodeInfo {
type Reader<'a> = SourceCodeInfo<'a>;
fn reader(&self) -> SourceCodeInfo<'_> {
SourceCodeInfo::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedSourceCodeInfo {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedSourceCodeInfo { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod source_code_info { pub mod source_code_info {
pub struct Location<'a> { pub struct Location<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
@@ -6455,6 +7140,27 @@ impl<'b> LocationBuilder<'b> {
} }
} }
pub struct OwnedLocation {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedLocation {
type Reader<'a> = Location<'a>;
fn reader(&self) -> Location<'_> {
Location::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedLocation {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedLocation { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
} }
pub struct GeneratedCodeInfo<'a> { pub struct GeneratedCodeInfo<'a> {
@@ -6533,6 +7239,27 @@ impl<'b> GeneratedCodeInfoBuilder<'b> {
} }
} }
pub struct OwnedGeneratedCodeInfo {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedGeneratedCodeInfo {
type Reader<'a> = GeneratedCodeInfo<'a>;
fn reader(&self) -> GeneratedCodeInfo<'_> {
GeneratedCodeInfo::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedGeneratedCodeInfo {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedGeneratedCodeInfo { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod generated_code_info { pub mod generated_code_info {
pub struct Annotation<'a> { pub struct Annotation<'a> {
accessor: roto_runtime::ProtoAccessor<'a>, accessor: roto_runtime::ProtoAccessor<'a>,
@@ -6710,6 +7437,27 @@ impl<'b> AnnotationBuilder<'b> {
} }
} }
pub struct OwnedAnnotation {
pub data: bytes::Bytes,
}
impl roto_runtime::RotoOwned for OwnedAnnotation {
type Reader<'a> = Annotation<'a>;
fn reader(&self) -> Annotation<'_> {
Annotation::new(&self.data).expect("failed to create reader")
}
}
impl roto_runtime::RotoMessage for OwnedAnnotation {
fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
Ok(OwnedAnnotation { data: buf })
}
fn bytes(&self) -> bytes::Bytes {
self.data.clone()
}
}
pub mod annotation { pub mod annotation {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
+17 -10
View File
@@ -37,8 +37,9 @@ fn test_generated_code_builds() {
); );
// 2. Setup a temporary Cargo project to verify the code builds // 2. Setup a temporary Cargo project to verify the code builds
let root = std::env::current_dir().expect("Failed to get current directory"); let codegen_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let temp_project_dir = root.join("test_gen_project"); let project_root = codegen_root.parent().expect("Failed to get project root");
let temp_project_dir = std::path::PathBuf::from("/tmp/roto_test_gen_project");
// Clean up previous runs // Clean up previous runs
if temp_project_dir.exists() { if temp_project_dir.exists() {
@@ -47,8 +48,7 @@ fn test_generated_code_builds() {
// Create new library project // Create new library project
let status = Command::new("cargo") let status = Command::new("cargo")
.args(["new", "--lib", "test_gen_project"]) .args(["new", "--lib", temp_project_dir.to_str().expect("Invalid path")])
.current_dir(&root)
.status() .status()
.expect("Failed to run cargo new"); .expect("Failed to run cargo new");
assert!(status.success(), "cargo new failed"); assert!(status.success(), "cargo new failed");
@@ -58,8 +58,11 @@ fn test_generated_code_builds() {
let cargo_toml_content = let cargo_toml_content =
fs::read_to_string(&cargo_toml_path).expect("Failed to read Cargo.toml"); fs::read_to_string(&cargo_toml_path).expect("Failed to read Cargo.toml");
let updated_cargo_toml = format!( let updated_cargo_toml = format!(
"{}\n\nroto-codegen = {{ path = \"..\" }}\nroto-runtime = {{ path = \"../../runtime\" }}\nbytes = \"1.7\"\ntonic = \"0.12\"\ntokio-stream = \"0.1\"\n\n[workspace]\n", "{}\n\nroto-codegen = {{ path = \"{}\" }}\nroto-runtime = {{ path = \"{}\" }}\nroto-tonic = {{ path = \"{}\" }}\nbytes = \"1.7\"\ntonic = \"0.12\"\ntokio-stream = \"0.1\"\ntower = \"0.4\"\nfutures-util = \"0.3\"\nhttp-body-util = \"0.1\"\nhttp-body = \"1.0\"\n\n[workspace]\n",
cargo_toml_content cargo_toml_content,
codegen_root.to_string_lossy(),
project_root.join("runtime").to_string_lossy(),
project_root.join("roto-tonic").to_string_lossy()
); );
fs::write(cargo_toml_path, updated_cargo_toml).expect("Failed to write Cargo.toml"); fs::write(cargo_toml_path, updated_cargo_toml).expect("Failed to write Cargo.toml");
@@ -75,14 +78,18 @@ fn test_generated_code_builds() {
fs::write(lib_path, all_code).expect("Failed to write generated code to src/lib.rs"); fs::write(lib_path, all_code).expect("Failed to write generated code to src/lib.rs");
// 5. Attempt to build the project // 5. Attempt to build the project
let build_status = Command::new("cargo") let build_output = Command::new("cargo")
.args(["--offline", "build"]) .args(["build"])
.current_dir(&temp_project_dir) .current_dir(&temp_project_dir)
.status() .output()
.expect("Failed to run cargo build"); .expect("Failed to run cargo build");
if !build_output.status.success() {
eprintln!("Cargo build failed output:\n{}", String::from_utf8_lossy(&build_output.stderr));
}
assert!( assert!(
build_status.success(), build_output.status.success(),
"The generated Rust code failed to build in a standalone project!" "The generated Rust code failed to build in a standalone project!"
); );
} }
+1
View File
@@ -27,3 +27,4 @@ http-body = "1.0"
[build-dependencies] [build-dependencies]
tonic-build = "0.12" tonic-build = "0.12"
roto-codegen = { path = "../../codegen" }
+20
View File
@@ -0,0 +1,20 @@
# Hello World Example
This example demonstrates a simple gRPC service using `roto`.
## Running the server
```bash
cargo run --bin server
```
## Calling the service
You can use `grpc_cli` to call the `HelloWorld` RPC:
```bash
grpc_cli call [::1]:50051 hello.HelloWorldService.HelloWorld 'name: "World"' \
--protofiles examples/hello_world/proto/hello.proto \
--proto_path examples/hello_world/proto \
--channel_creds_type insecure
```
+3 -3
View File
@@ -4,9 +4,9 @@ fn main() {
let dest_path = std::path::Path::new(&out_dir).join("hello.rs"); let dest_path = std::path::Path::new(&out_dir).join("hello.rs");
// Find the protoc-gen-roto binary // Find the protoc-gen-roto binary
// In a real scenario, this should be passed as an environment variable or found in PATH // Since we added roto-codegen to build-dependencies, it will be built.
// For this example, we'll try to find it in the target directory let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let target_dir = std::env::current_dir().unwrap().join("../../target/debug"); let target_dir = std::path::Path::new(&manifest_dir).join("../../target/debug");
let plugin_path = target_dir.join("protoc-gen-roto"); let plugin_path = target_dir.join("protoc-gen-roto");
if !plugin_path.exists() { if !plugin_path.exists() {
+101 -1
View File
@@ -3,10 +3,19 @@
use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator}; use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator};
use std::str; use std::str;
use bytes::Bytes; use bytes::{Bytes, BytesMut, Buf, BufMut};
use tonic::{Request, Response, Status}; use tonic::{Request, Response, Status};
use tokio_stream::Stream; use tokio_stream::Stream;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::future::Future;
use tonic::body::BoxBody;
use tower::Service;
use futures_util::StreamExt;
use http_body_util::BodyExt;
use http_body::Body;
use roto_tonic::{BufferPool, StatusBody};
pub struct HelloRequest<'a> { pub struct HelloRequest<'a> {
@@ -208,3 +217,94 @@ pub trait HelloWorldService: Send + Sync + 'static {
async fn hello_world(&self, request: Request<OwnedHelloRequest>) -> std::result::Result<Response<OwnedHelloResponse>, Status>; async fn hello_world(&self, request: Request<OwnedHelloRequest>) -> std::result::Result<Response<OwnedHelloResponse>, Status>;
} }
pub struct HelloWorldServiceServer {
inner: Arc<dyn HelloWorldService>,
pool: Arc<BufferPool>,
}
impl HelloWorldServiceServer {
pub fn new(inner: Arc<dyn HelloWorldService>, pool: Arc<BufferPool>) -> Self {
Self { inner, pool }
}
}
impl tonic::server::NamedService for HelloWorldServiceServer {
const NAME: &'static str = "HelloWorldService";
}
impl Service<http::Request<BoxBody>> for HelloWorldServiceServer {
type Response = http::Response<BoxBody>;
type Error = std::convert::Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: http::Request<BoxBody>) -> Self::Future {
let inner = self.inner.clone();
let pool = self.pool.clone();
Box::pin(async move {
let body = req.into_body();
let mut buf = pool.get();
let mut stream = body;
while let Some(frame_result) = stream.frame().await {
let frame = frame_result.map_err(|e| {
panic!("Body frame error: {}", e);
})?;
if let Some(data) = frame.data_ref() {
buf.put(data.clone());
}
}
let total_len = buf.len();
let bytes_vec = buf.split_to(total_len).freeze();
pool.put(buf);
if bytes_vec.len() < 5 {
let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder().status(200).body(res_body).unwrap());
}
let payload = bytes_vec.slice(5..);
let path = req.uri().path();
let mut routed = false;
if path == "/HelloWorldService/hello_world" {
let request_msg = match OwnedHelloRequest::decode(payload) {
Ok(msg) => msg,
Err(e) => {
let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder().status(200).body(res_body).unwrap());
}
}};
let response = match inner.hello_world(Request::new(request_msg)).await {
Ok(res) => res,
Err(e) => {
let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder().status(200).body(res_body).unwrap());
}
}};
let response_msg = response.into_inner();
let response_bytes = response_msg.bytes();
let mut res_buf = pool.get();
res_buf.put_u8(0);
let len = response_bytes.len() as u32;
res_buf.put_slice(&len.to_be_bytes());
res_buf.put_slice(&response_bytes);
let frame_len = res_buf.len();
let frame = res_buf.split_to(frame_len).freeze();
pool.put(res_buf);
let res_body = BoxBody::new(StatusBody(Some(frame)));
routed = true;
return Ok(http::Response::builder().status(200).header("content-type", "application/grpc").body(res_body).unwrap());
}
if !routed {
let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder().status(200).body(res_body).unwrap());
}
Ok(http::Response::builder().status(200).body(BoxBody::new(StatusBody(None))).unwrap())
})
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ use std::task::{Context, Poll};
use tower::Service; use tower::Service;
pub mod hello { pub mod hello {
include!("../../proto/hello.rs"); include!(concat!(env!("OUT_DIR"), "/hello.rs"));
} }
struct ReadyService<S>(S); struct ReadyService<S>(S);
+82 -27
View File
@@ -1,12 +1,12 @@
use std::pin::Pin; use std::pin::Pin;
use std::future::Future; use std::future::Future;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::sync::Arc; use std::sync::{Arc, Mutex};
use tonic::{transport::Server, Request, Response, Status}; use tonic::{transport::Server, Request, Response, Status};
use roto_tonic::RotoCodec; use roto_tonic::RotoCodec;
use hello::{HelloWorldService, OwnedHelloRequest, OwnedHelloResponse}; use hello::{HelloWorldService, OwnedHelloRequest, OwnedHelloResponse};
use tower::Service; use tower::Service;
use bytes::{Bytes, Buf, BufMut}; use bytes::{Bytes, BytesMut, Buf, BufMut};
use tonic::body::BoxBody; use tonic::body::BoxBody;
use futures_util::StreamExt; use futures_util::StreamExt;
use roto_runtime::{RotoOwned, RotoMessage}; use roto_runtime::{RotoOwned, RotoMessage};
@@ -14,11 +14,44 @@ use http_body_util::BodyExt;
use http_body::Body; use http_body::Body;
pub mod hello { pub mod hello {
include!("../../proto/hello.rs"); include!(concat!(env!("OUT_DIR"), "/hello.rs"));
} }
#[derive(Default, Clone)] struct BufferPool {
pub struct MyHelloWorld {} pool: Mutex<Vec<BytesMut>>,
default_capacity: usize,
}
impl BufferPool {
fn new(default_capacity: usize) -> Self {
Self {
pool: Mutex::new(Vec::new()),
default_capacity,
}
}
fn get(&self) -> BytesMut {
self.pool.lock().unwrap().pop().unwrap_or_else(|| BytesMut::with_capacity(self.default_capacity))
}
fn put(&self, mut buf: BytesMut) {
buf.clear();
if buf.capacity() >= self.default_capacity {
self.pool.lock().unwrap().push(buf);
}
}
}
#[derive(Clone)]
pub struct MyHelloWorld {
pool: Arc<BufferPool>,
}
impl MyHelloWorld {
pub fn new(pool: Arc<BufferPool>) -> Self {
Self { pool }
}
}
#[tonic::async_trait] #[tonic::async_trait]
impl HelloWorldService for MyHelloWorld { impl HelloWorldService for MyHelloWorld {
@@ -30,13 +63,18 @@ impl HelloWorldService for MyHelloWorld {
let reader = req.reader(); let reader = req.reader();
let name = reader.name().unwrap_or("Unknown"); let name = reader.name().unwrap_or("Unknown");
let mut buf = vec![0u8; 1024]; let mut buf = self.pool.get();
let slice = hello::HelloResponseBuilder::builder(&mut buf) buf.resize(1024, 0);
let slice = hello::HelloResponseBuilder::builder(&mut buf[..])
.message(&format!("Hello {}!", name)).unwrap() .message(&format!("Hello {}!", name)).unwrap()
.finish().unwrap(); .finish().unwrap();
let res_len = slice.len();
let response_bytes = buf.split_to(res_len).freeze();
self.pool.put(buf);
let reply = OwnedHelloResponse { let reply = OwnedHelloResponse {
data: bytes::Bytes::copy_from_slice(slice), data: response_bytes,
}; };
Ok(Response::new(reply)) Ok(Response::new(reply))
@@ -48,11 +86,12 @@ impl HelloWorldService for MyHelloWorld {
#[derive(Clone)] #[derive(Clone)]
pub struct HelloWorldServer { pub struct HelloWorldServer {
inner: Arc<MyHelloWorld>, inner: Arc<MyHelloWorld>,
pool: Arc<BufferPool>,
} }
impl HelloWorldServer { impl HelloWorldServer {
pub fn new(inner: MyHelloWorld) -> Self { pub fn new(inner: MyHelloWorld, pool: Arc<BufferPool>) -> Self {
Self { inner: Arc::new(inner) } Self { inner: Arc::new(inner), pool }
} }
} }
@@ -89,32 +128,43 @@ impl Service<http::Request<BoxBody>> for HelloWorldServer {
fn call(&mut self, req: http::Request<BoxBody>) -> Self::Future { fn call(&mut self, req: http::Request<BoxBody>) -> Self::Future {
let inner = self.inner.clone(); let inner = self.inner.clone();
let pool = self.pool.clone();
println!("Server received request: {} {}", req.method(), req.uri()); println!("Server received request: {} {}", req.method(), req.uri());
Box::pin(async move { Box::pin(async move {
let body = req.into_body(); let body = req.into_body();
let bytes_vec = body.collect().await.map_err(|e| { let mut buf = pool.get();
println!("Body collect error: {}", e); let mut stream = body;
panic!("Body collect error: {}", e); while let Some(frame_result) = stream.frame().await {
})?.to_bytes(); let frame = frame_result.map_err(|e| {
println!("Body frame error: {}", e);
panic!("Body frame error: {}", e);
})?;
if let Some(data) = frame.data_ref() {
buf.put(data.clone());
}
}
let total_len = buf.len();
let bytes_vec = buf.split_to(total_len).freeze();
pool.put(buf);
println!("Collected body bytes: {} bytes", bytes_vec.len()); println!("Collected body bytes: {} bytes", bytes_vec.len());
if bytes_vec.len() < 5 { if bytes_vec.len() < 5 {
println!("Body too short: {} bytes", bytes_vec.len()); println!("Body too short: {} bytes", bytes_vec.len());
let res_body = BoxBody::new(StatusBody(Some(Bytes::from(vec![0, 0, 0, 0, 0])))); let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder() return Ok(http::Response::builder()
.status(200) .status(200)
.body(res_body) .body(res_body)
.unwrap()); .unwrap());
} }
let data = &bytes_vec[5..]; println!("Decoding request from {} bytes", bytes_vec.len() - 5);
println!("Decoding request from {} bytes", data.len()); let request_msg = match OwnedHelloRequest::decode(bytes_vec.slice(5..)) {
let request_msg = match OwnedHelloRequest::decode(Bytes::copy_from_slice(data)) {
Ok(msg) => msg, Ok(msg) => msg,
Err(e) => { Err(e) => {
println!("Decode error: {}", e); println!("Decode error: {}", e);
let res_body = BoxBody::new(StatusBody(Some(Bytes::from(vec![0, 0, 0, 0, 0])))); let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder().status(200).body(res_body).unwrap()); return Ok(http::Response::builder().status(200).body(res_body).unwrap());
} }
}; };
@@ -124,7 +174,7 @@ impl Service<http::Request<BoxBody>> for HelloWorldServer {
Ok(res) => res, Ok(res) => res,
Err(e) => { Err(e) => {
println!("Service error: {}", e); println!("Service error: {}", e);
let res_body = BoxBody::new(StatusBody(Some(Bytes::from(vec![0, 0, 0, 0, 0])))); let res_body = BoxBody::new(StatusBody(Some(Bytes::from_static(&[0, 0, 0, 0, 0]))));
return Ok(http::Response::builder().status(200).body(res_body).unwrap()); return Ok(http::Response::builder().status(200).body(res_body).unwrap());
} }
}; };
@@ -133,13 +183,17 @@ impl Service<http::Request<BoxBody>> for HelloWorldServer {
let response_bytes = response_msg.bytes(); let response_bytes = response_msg.bytes();
println!("Service responded with {} bytes", response_bytes.len()); println!("Service responded with {} bytes", response_bytes.len());
let mut res_buf = vec![0u8; 5 + response_bytes.len()]; let mut res_buf = pool.get();
res_buf[0] = 0; res_buf.put_u8(0);
let len = response_bytes.len() as u32; let len = response_bytes.len() as u32;
res_buf[1..5].copy_from_slice(&len.to_be_bytes()); res_buf.put_slice(&len.to_be_bytes());
res_buf[5..].copy_from_slice(&response_bytes); res_buf.put_slice(&response_bytes);
let res_body = BoxBody::new(StatusBody(Some(Bytes::from(res_buf)))); let frame_len = res_buf.len();
let frame = res_buf.split_to(frame_len).freeze();
pool.put(res_buf);
let res_body = BoxBody::new(StatusBody(Some(frame)));
Ok(http::Response::builder() Ok(http::Response::builder()
.status(200) .status(200)
.header("content-type", "application/grpc") .header("content-type", "application/grpc")
@@ -152,12 +206,13 @@ impl Service<http::Request<BoxBody>> for HelloWorldServer {
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr: std::net::SocketAddr = "[::1]:50051".parse()?; let addr: std::net::SocketAddr = "[::1]:50051".parse()?;
let hello = MyHelloWorld::default(); let pool = Arc::new(BufferPool::new(1024));
let hello = MyHelloWorld::new(pool.clone());
println!("Server listening on {}", addr); println!("Server listening on {}", addr);
Server::builder() Server::builder()
.add_service(HelloWorldServer::new(hello)) .add_service(HelloWorldServer::new(hello, pool))
.serve(addr) .serve(addr)
.await?; .await?;
+12
View File
@@ -0,0 +1,12 @@
You are the Codemonkey. Your role is the pure implementation of technical tasks.
Your workflow:
1. Review the implementation plan in the `artifacts/` directory.
2. Implement the changes in the codebase following the provided plan and established coding standards.
3. After every significant change, you MUST:
- Ensure the codebase compiles without errors.
- Run all relevant tests to ensure no regressions were introduced.
- If tests fail, fix the issues before proceeding.
4. Document your progress and the final outcome in a verification report in the `artifacts/` directory (e.g., `artifacts/verification_report.md`). This report should list the tasks completed and provide evidence (e.g., test output) that the solution works as intended.
5. Do not deviate from the plan without consulting the Orchestrator.
6. Once the tasks are complete and verified, notify the Orchestrator that the codebase is updated and the verification report artifact is ready.
+9
View File
@@ -0,0 +1,9 @@
You are the Coordinator. Your role is to transform high-level problem statements and research data into a concrete, executable implementation plan.
Your workflow:
1. Review the problem statement and the `artifacts/research_report.md` produced by the Research agent.
2. Break down the overall goal into a sequence of small, manageable, and independent tasks.
3. For each task, specify the expected outcome and any dependencies on previous tasks.
4. Ensure the plan is logically ordered and covers all edge cases identified during research.
5. Save the final plan as `artifacts/implementation_plan.md` for human review and as a guide for the Codemonkey.
6. Notify the Orchestrator that the implementation plan artifact is ready.
+14
View File
@@ -0,0 +1,14 @@
You are the Orchestrator. Your role is to manage the end-to-end resolution of a complex technical problem. Make extensive use of the
subagent tool.
Your workflow:
1. Analyze the initial problem statement.
2. Delegate research to the Research agent. Ensure the Research agent produces a `artifacts/research_report.md` for human review.
3. Coordinate with the Coordinator agent to break down the findings into a detailed plan. Ensure the Coordinator produces a `artifacts/implementation_plan.md` for human review.
4. Delegate the implementation of these steps to the Codemonkey agent. Ensure the Codemonkey produces a `artifacts/verification_report.md` upon completion.
5. Review the artifacts in the `artifacts/` directory and the results from the Codemonkey agent, ensuring all requirements are met and the solution is correct.
6. If issues arise, loop back to the Research or Coordinator agents as needed, updating the relevant artifacts.
Your goal is to act as the central hub of communication and decision-making, ensuring a systematic and verified approach to the problem.
You must tell subagents what persona they are, and provide them the path of the persona file they should read.
+13
View File
@@ -0,0 +1,13 @@
You are the Researcher. Your role is to conduct a comprehensive initial analysis of a problem to identify the best technical approach.
Your workflow:
1. Analyze the problem statement to identify key technical requirements and unknown areas.
2. Use available tools (such as SearXNG and web search) to research existing libraries, frameworks, APIs, and best practices relevant to the problem.
3. Explore the current codebase to understand how the new functionality fits in or what existing patterns should be followed.
4. Compile a detailed report including:
- Recommended tools and libraries.
- Potential challenges or pitfalls.
- Suggested architectural approach.
- Relevant documentation links.
5. Save this report as `artifacts/research_report.md` for human review.
6. Notify the Orchestrator that the research report artifact is ready.
+4
View File
@@ -8,3 +8,7 @@ roto-runtime = { path = "../runtime" }
tonic = "0.12" tonic = "0.12"
bytes = "1.7" bytes = "1.7"
prost = "0.13" prost = "0.13"
http-body = "1.0"
http-body-util = "0.1"
tower = "0.4"
futures-util = "0.3"
+49 -1
View File
@@ -1,7 +1,12 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use tonic::codec::{Codec, Decoder, Encoder, DecodeBuf, EncodeBuf}; use tonic::codec::{Codec, Decoder, Encoder, DecodeBuf, EncodeBuf};
use bytes::{Buf, BufMut}; use bytes::{Buf, BufMut, Bytes, BytesMut};
use roto_runtime::RotoMessage; use roto_runtime::RotoMessage;
use std::sync::{Arc, Mutex};
use std::pin::Pin;
use std::future::Future;
use std::task::{Context, Poll};
use http_body::Body;
pub struct RotoCodec<T, U> { pub struct RotoCodec<T, U> {
_phantom: PhantomData<(T, U)>, _phantom: PhantomData<(T, U)>,
@@ -70,3 +75,46 @@ where
} }
} }
} }
pub struct BufferPool {
pool: Mutex<Vec<BytesMut>>,
default_capacity: usize,
}
impl BufferPool {
pub fn new(default_capacity: usize) -> Self {
Self {
pool: Mutex::new(Vec::new()),
default_capacity,
}
}
pub fn get(&self) -> BytesMut {
self.pool.lock().unwrap().pop().unwrap_or_else(|| BytesMut::with_capacity(self.default_capacity))
}
pub fn put(&self, mut buf: BytesMut) {
buf.clear();
if buf.capacity() >= self.default_capacity {
self.pool.lock().unwrap().push(buf);
}
}
}
pub struct StatusBody(pub Option<Bytes>);
impl Body for StatusBody {
type Data = Bytes;
type Error = tonic::Status;
fn poll_frame(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
if let Some(data) = self.0.take() {
Poll::Ready(Some(Ok(http_body::Frame::data(data))))
} else {
Poll::Ready(None)
}
}
}