diff --git a/Cargo.lock b/Cargo.lock index 40c1b99..7ce5459 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1168,10 +1168,18 @@ dependencies = [ name = "roto-codegen" version = "0.1.0" dependencies = [ + "bytes", "clap", "env_logger", + "futures-util", + "http-body", + "http-body-util", "log", "roto-runtime", + "roto-tonic", + "tokio-stream", + "tonic", + "tower 0.4.13", ] [[package]] @@ -1186,9 +1194,13 @@ name = "roto-tonic" version = "0.1.0" dependencies = [ "bytes", + "futures-util", + "http-body", + "http-body-util", "prost", "roto-runtime", "tonic", + "tower 0.4.13", ] [[package]] @@ -1352,19 +1364,6 @@ dependencies = [ "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]] name = "tinytemplate" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 48bd71e..422753a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = [ "codegen", "protos", "benches", - "roto-tonic", "test_grpc_project", + "roto-tonic", "examples/hello_world", ] diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index d7c36a7..f10c40c 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -5,6 +5,14 @@ edition = "2024" [dependencies] roto-runtime = { path = "../runtime" } +roto-tonic = { path = "../roto-tonic" } clap = { version = "4", features = ["derive"] } log = "0.4" 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" diff --git a/codegen/src/generator.rs b/codegen/src/generator.rs index f093759..81f2b78 100644 --- a/codegen/src/generator.rs +++ b/codegen/src/generator.rs @@ -547,10 +547,19 @@ pub fn generate_rust_code( 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 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 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() { 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"); + + let server_name = format!("{}Server", svc_name); + output.push_str(&format!("pub struct {} {{\n", server_name)); + output.push_str(&format!(" inner: Arc,\n", svc_name)); + output.push_str(" pool: Arc,\n"); + output.push_str("}\n\n"); + + output.push_str(&format!("impl {} {{\n", server_name)); + output.push_str(&format!(" pub fn new(inner: Arc, pool: Arc) -> 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> for {} {{\n", server_name)); + output.push_str(" type Response = http::Response;\n"); + output.push_str(" type Error = std::convert::Infallible;\n"); + output.push_str(" type Future = Pin> + Send>>;\n\n"); + + output.push_str(" fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> {\n"); + output.push_str(" Poll::Ready(Ok(()))\n"); + output.push_str(" }\n\n"); + + output.push_str(" fn call(&mut self, req: http::Request) -> 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 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 path = req.uri().path();\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"); } diff --git a/codegen/src/google/protobuf/compiler/plugin.rs b/codegen/src/google/protobuf/compiler/plugin.rs index 4a2213a..7f46172 100644 --- a/codegen/src/google/protobuf/compiler/plugin.rs +++ b/codegen/src/google/protobuf/compiler/plugin.rs @@ -1,8 +1,21 @@ // @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 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; @@ -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 { + Ok(OwnedVersion { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct CodeGeneratorRequest<'a> { accessor: roto_runtime::ProtoAccessor<'a>, file_to_generate_start: Option, @@ -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 { + Ok(OwnedCodeGeneratorRequest { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct CodeGeneratorResponse<'a> { accessor: roto_runtime::ProtoAccessor<'a>, error_offset: Option, @@ -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 { + Ok(OwnedCodeGeneratorResponse { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod code_generator_response { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedFile { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } diff --git a/codegen/src/google/protobuf/descriptor.rs b/codegen/src/google/protobuf/descriptor.rs index 5ca11a4..e57b526 100644 --- a/codegen/src/google/protobuf/descriptor.rs +++ b/codegen/src/google/protobuf/descriptor.rs @@ -1,8 +1,21 @@ // @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 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)] @@ -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 { + Ok(OwnedFileDescriptorSet { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct FileDescriptorProto<'a> { accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, @@ -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 { + Ok(OwnedFileDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct DescriptorProto<'a> { accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, @@ -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 { + Ok(OwnedDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod descriptor_proto { pub struct ExtensionRange<'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 { + Ok(OwnedExtensionRange { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct ReservedRange<'a> { accessor: roto_runtime::ProtoAccessor<'a>, start_offset: Option, @@ -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 { + Ok(OwnedReservedRange { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedExtensionRangeOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod extension_range_options { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedDeclaration { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedFieldDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod field_descriptor_proto { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedOneofDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct EnumDescriptorProto<'a> { accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, @@ -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 { + Ok(OwnedEnumDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod enum_descriptor_proto { pub struct EnumReservedRange<'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 { + Ok(OwnedEnumReservedRange { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedEnumValueDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct ServiceDescriptorProto<'a> { accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, @@ -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 { + Ok(OwnedServiceDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct MethodDescriptorProto<'a> { accessor: roto_runtime::ProtoAccessor<'a>, name_offset: Option, @@ -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 { + Ok(OwnedMethodDescriptorProto { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct FileOptions<'a> { accessor: roto_runtime::ProtoAccessor<'a>, java_package_offset: Option, @@ -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 { + Ok(OwnedFileOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod file_options { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedMessageOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct FieldOptions<'a> { accessor: roto_runtime::ProtoAccessor<'a>, ctype_offset: Option, @@ -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 { + Ok(OwnedFieldOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod field_options { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedEditionDefault { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct FeatureSupport<'a> { accessor: roto_runtime::ProtoAccessor<'a>, edition_introduced_offset: Option, @@ -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 { + Ok(OwnedFeatureSupport { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedOneofOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct EnumOptions<'a> { accessor: roto_runtime::ProtoAccessor<'a>, allow_alias_offset: Option, @@ -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 { + Ok(OwnedEnumOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct EnumValueOptions<'a> { accessor: roto_runtime::ProtoAccessor<'a>, deprecated_offset: Option, @@ -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 { + Ok(OwnedEnumValueOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct ServiceOptions<'a> { accessor: roto_runtime::ProtoAccessor<'a>, features_offset: Option, @@ -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 { + Ok(OwnedServiceOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub struct MethodOptions<'a> { accessor: roto_runtime::ProtoAccessor<'a>, deprecated_offset: Option, @@ -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 { + Ok(OwnedMethodOptions { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod method_options { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedUninterpretedOption { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod uninterpreted_option { pub struct NamePart<'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 { + Ok(OwnedNamePart { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedFeatureSet { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod feature_set { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedVisibilityFeature { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod visibility_feature { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedProtoLimitsFeature { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod proto_limits_feature { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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 { + Ok(OwnedFeatureSetDefaults { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod feature_set_defaults { pub struct FeatureSetEditionDefault<'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 { + Ok(OwnedFeatureSetEditionDefault { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedSourceCodeInfo { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod source_code_info { pub struct Location<'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 { + Ok(OwnedLocation { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + } 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 { + Ok(OwnedGeneratedCodeInfo { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod generated_code_info { pub struct Annotation<'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 { + Ok(OwnedAnnotation { data: buf }) + } + + fn bytes(&self) -> bytes::Bytes { + self.data.clone() + } +} + pub mod annotation { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(i32)] diff --git a/examples/hello_world/proto/hello.rs b/examples/hello_world/proto/hello.rs deleted file mode 100644 index fa6bf2a..0000000 --- a/examples/hello_world/proto/hello.rs +++ /dev/null @@ -1,210 +0,0 @@ -// @generated by protoc-gen-roto — do not edit -#[allow(unused_imports)] - -use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator}; -use std::str; -use bytes::Bytes; -use tonic::{Request, Response, Status}; -use tokio_stream::Stream; -use std::pin::Pin; - - -pub struct HelloRequest<'a> { - accessor: roto_runtime::ProtoAccessor<'a>, - name_offset: Option, -} - -impl<'a> HelloRequest<'a> { - pub fn new(data: &'a [u8]) -> roto_runtime::Result { - let accessor = roto_runtime::ProtoAccessor::new(data)?; - let mut name_offset = None; - for item in accessor.fields() { - let (offset, tag, _) = item?; - if tag.field_number == 1 { name_offset = Some(offset); } - } - - Ok(Self { - accessor, -name_offset, - }) - } - - pub fn name(&self) -> roto_runtime::Result<&'a str> { - let offset = self.name_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?; - let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) - } - - pub fn name_or_default(&self) -> roto_runtime::Result<&'a str> { - self.name().or(Ok("")) - } - - pub fn has_name(&self) -> bool { self.name_offset.is_some() } - - pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { - self.accessor.raw_fields() - } - -} - -pub struct HelloRequestBuilder<'b> { - builder: roto_runtime::ProtoBuilder<'b>, - name_written: bool, -} - -impl<'b> HelloRequestBuilder<'b> { - pub fn builder(buf: &mut [u8]) -> HelloRequestBuilder<'_> { - HelloRequestBuilder { - builder: roto_runtime::ProtoBuilder::new(buf), - name_written: false, - } - } - - pub fn name(mut self, value: &str) -> roto_runtime::Result { - self.builder.write_string(1, value)?; - self.name_written = true; - Ok(self) - } - - pub fn with(mut self, msg: &HelloRequest<'_>) -> roto_runtime::Result { - for item in msg.raw_fields() { - let (field_number, raw_bytes) = item?; - let is_written = match field_number { - 1 => self.name_written, - _ => false, - }; - if !is_written { - self.builder.write_raw(raw_bytes)?; - } - } - Ok(self) - } - - pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { - self.builder.finish() - } -} - -pub struct OwnedHelloRequest { - pub data: bytes::Bytes, -} - -impl roto_runtime::RotoOwned for OwnedHelloRequest { - type Reader<'a> = HelloRequest<'a>; - fn reader(&self) -> HelloRequest<'_> { - HelloRequest::new(&self.data).expect("failed to create reader") - } -} - -impl roto_runtime::RotoMessage for OwnedHelloRequest { - fn decode(buf: bytes::Bytes) -> roto_runtime::Result { - Ok(OwnedHelloRequest { data: buf }) - } - - fn bytes(&self) -> bytes::Bytes { - self.data.clone() - } -} - -pub struct HelloResponse<'a> { - accessor: roto_runtime::ProtoAccessor<'a>, - message_offset: Option, -} - -impl<'a> HelloResponse<'a> { - pub fn new(data: &'a [u8]) -> roto_runtime::Result { - let accessor = roto_runtime::ProtoAccessor::new(data)?; - let mut message_offset = None; - for item in accessor.fields() { - let (offset, tag, _) = item?; - if tag.field_number == 1 { message_offset = Some(offset); } - } - - Ok(Self { - accessor, -message_offset, - }) - } - - pub fn message(&self) -> roto_runtime::Result<&'a str> { - let offset = self.message_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?; - let (bytes, _) = self.accessor.get_value_at(offset)?; - str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation) - } - - pub fn message_or_default(&self) -> roto_runtime::Result<&'a str> { - self.message().or(Ok("")) - } - - pub fn has_message(&self) -> bool { self.message_offset.is_some() } - - pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> { - self.accessor.raw_fields() - } - -} - -pub struct HelloResponseBuilder<'b> { - builder: roto_runtime::ProtoBuilder<'b>, - message_written: bool, -} - -impl<'b> HelloResponseBuilder<'b> { - pub fn builder(buf: &mut [u8]) -> HelloResponseBuilder<'_> { - HelloResponseBuilder { - builder: roto_runtime::ProtoBuilder::new(buf), - message_written: false, - } - } - - pub fn message(mut self, value: &str) -> roto_runtime::Result { - self.builder.write_string(1, value)?; - self.message_written = true; - Ok(self) - } - - pub fn with(mut self, msg: &HelloResponse<'_>) -> roto_runtime::Result { - for item in msg.raw_fields() { - let (field_number, raw_bytes) = item?; - let is_written = match field_number { - 1 => self.message_written, - _ => false, - }; - if !is_written { - self.builder.write_raw(raw_bytes)?; - } - } - Ok(self) - } - - pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> { - self.builder.finish() - } -} - -pub struct OwnedHelloResponse { - pub data: bytes::Bytes, -} - -impl roto_runtime::RotoOwned for OwnedHelloResponse { - type Reader<'a> = HelloResponse<'a>; - fn reader(&self) -> HelloResponse<'_> { - HelloResponse::new(&self.data).expect("failed to create reader") - } -} - -impl roto_runtime::RotoMessage for OwnedHelloResponse { - fn decode(buf: bytes::Bytes) -> roto_runtime::Result { - Ok(OwnedHelloResponse { data: buf }) - } - - fn bytes(&self) -> bytes::Bytes { - self.data.clone() - } -} - -#[tonic::async_trait] -pub trait HelloWorldService: Send + Sync + 'static { - async fn hello_world(&self, request: Request) -> std::result::Result, Status>; -} - diff --git a/examples/hello_world/src/bin/client.rs b/examples/hello_world/src/bin/client.rs index 5e4eaaa..fe3e1b0 100644 --- a/examples/hello_world/src/bin/client.rs +++ b/examples/hello_world/src/bin/client.rs @@ -6,7 +6,7 @@ use std::task::{Context, Poll}; use tower::Service; pub mod hello { - include!("../../proto/hello.rs"); + include!(concat!(env!("OUT_DIR"), "/hello.rs")); } struct ReadyService(S); diff --git a/examples/hello_world/src/bin/server.rs b/examples/hello_world/src/bin/server.rs index b49080b..9aa1486 100644 --- a/examples/hello_world/src/bin/server.rs +++ b/examples/hello_world/src/bin/server.rs @@ -14,7 +14,7 @@ use http_body_util::BodyExt; use http_body::Body; pub mod hello { - include!("../../proto/hello.rs"); + include!(concat!(env!("OUT_DIR"), "/hello.rs")); } struct BufferPool { diff --git a/roto-tonic/Cargo.toml b/roto-tonic/Cargo.toml index 9b13476..e962ee1 100644 --- a/roto-tonic/Cargo.toml +++ b/roto-tonic/Cargo.toml @@ -8,3 +8,7 @@ roto-runtime = { path = "../runtime" } tonic = "0.12" bytes = "1.7" prost = "0.13" +http-body = "1.0" +http-body-util = "0.1" +tower = "0.4" +futures-util = "0.3" diff --git a/roto-tonic/src/lib.rs b/roto-tonic/src/lib.rs index 9e17ff0..46168e3 100644 --- a/roto-tonic/src/lib.rs +++ b/roto-tonic/src/lib.rs @@ -1,7 +1,12 @@ use std::marker::PhantomData; use tonic::codec::{Codec, Decoder, Encoder, DecodeBuf, EncodeBuf}; -use bytes::{Buf, BufMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; 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 { _phantom: PhantomData<(T, U)>, @@ -70,3 +75,46 @@ where } } } + +pub struct BufferPool { + pool: Mutex>, + 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(crate) Option); + +impl Body for StatusBody { + type Data = Bytes; + type Error = tonic::Status; + + fn poll_frame( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll, Self::Error>>> { + if let Some(data) = self.0.take() { + Poll::Ready(Some(Ok(http_body::Frame::data(data)))) + } else { + Poll::Ready(None) + } + } +}