Compare commits
8 Commits
daa42d2d07
...
a3fece24fc
| Author | SHA1 | Date | |
|---|---|---|---|
| a3fece24fc | |||
| cc82e990ba | |||
| a9fef01950 | |||
| da7ba47505 | |||
| 00b3dcd9a6 | |||
| 08be61966c | |||
| db2bf1bffd | |||
| dfdcd8ae46 |
@@ -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/
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -4,7 +4,7 @@ members = [
|
|||||||
"codegen",
|
"codegen",
|
||||||
"protos",
|
"protos",
|
||||||
"benches",
|
"benches",
|
||||||
"roto-tonic", "test_grpc_project",
|
"roto-tonic",
|
||||||
"examples/hello_world",
|
"examples/hello_world",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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!"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,3 +27,4 @@ http-body = "1.0"
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tonic-build = "0.12"
|
tonic-build = "0.12"
|
||||||
|
roto-codegen = { path = "../../codegen" }
|
||||||
|
|||||||
@@ -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
|
||||||
|
```
|
||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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?;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user