diff --git a/Cargo.toml b/Cargo.toml index f1c3033..e9d6811 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,15 +29,16 @@ futures = "0.3" pin-project = "1" async-trait = "0.1" -# Protobuf. The 0.6 floor matches the regen baseline for the checked-in -# generated code: 0.6.0 adds `with_*` setters for explicit-presence fields, -# `MessageName`/`Serialize` impls on view types, and stops emitting empty -# `__oneof`/`__ext`/`__view_oneof` ancillary files. (connectrpc-build also -# sources the generated `mod.rs` `#[allow(...)]` list from -# `buffa_codegen::ALLOW_LINTS`, present since 0.5.1.) -buffa = { version = "0.6", features = ["json"] } -buffa-types = { version = "0.6", features = ["json"] } -buffa-codegen = { version = "0.6" } +# Protobuf. The 0.7 floor matches the regen baseline for the checked-in +# generated code and the request/stream-item API: 0.7.0 adds the +# `HasMessageView` trait and the generated `FooOwnedView` accessor wrappers +# that `ServiceRequest`/`StreamMessage` are built on, and removes the +# `OwnedView` `Deref` impl that earlier handler signatures relied on. +# (connectrpc-build also sources the generated `mod.rs` `#[allow(...)]` list +# from `buffa_codegen::ALLOW_LINTS`, present since 0.5.1.) +buffa = { version = "0.7", features = ["json"] } +buffa-types = { version = "0.7", features = ["json"] } +buffa-codegen = { version = "0.7" } # Serialization serde = { version = "1", features = ["derive"] } diff --git a/README.md b/README.md index e603691..87a0d92 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,12 @@ Changing the mount point requires regenerating. > The underlying option is `extern_path=.=crate::proto` - same format the > Buf Schema Registry uses when generating Cargo SDKs. `buffa_module=X` -> is shorthand for the `.` catch-all case. +> is shorthand for the `.` catch-all case. Any module an `extern_path` +> points at must be buffa-generated code from buffa 0.7.0 or newer with +> views enabled (buffa-types 0.7+ for the well-known types): the service +> stubs rely on the `HasMessageView` impls and owned-view wrappers that +> buffa generates alongside each message, just as they rely on the JSON +> serialization impls. #### Option B - `build.rs` (generated at build time) @@ -346,8 +351,8 @@ Code generated by `protoc-gen-connect-rust` requires these dependencies: ```toml [dependencies] connectrpc = { version = "0.6", features = ["client"] } -buffa = { version = "0.6", features = ["json"] } -buffa-types = { version = "0.6", features = ["json"] } +buffa = { version = "0.7", features = ["json"] } +buffa-types = { version = "0.7", features = ["json"] } serde = { version = "1", features = ["derive"] } serde_json = "1" http-body = "1" diff --git a/benches/rpc/src/generated/buffa/anthropic.connectrpc.filter.v1.mod.rs b/benches/rpc/src/generated/buffa/anthropic.connectrpc.filter.v1.mod.rs index 9f2b2e1..191faf8 100644 --- a/benches/rpc/src/generated/buffa/anthropic.connectrpc.filter.v1.mod.rs +++ b/benches/rpc/src/generated/buffa/anthropic.connectrpc.filter.v1.mod.rs @@ -28,4 +28,6 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::RecordView; #[doc(inline)] +pub use self::__buffa::view::RecordOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/benches/rpc/src/generated/buffa/bench.__view.rs b/benches/rpc/src/generated/buffa/bench.__view.rs index 599322e..b7d0535 100644 --- a/benches/rpc/src/generated/buffa/bench.__view.rs +++ b/benches/rpc/src/generated/buffa/bench.__view.rs @@ -177,6 +177,114 @@ impl ::buffa::ViewReborrow for EchoRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `EchoRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`EchoRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`EchoRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct EchoRequestOwnedView(::buffa::OwnedView>); +impl EchoRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EchoRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EchoRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::EchoRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EchoRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`EchoRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &EchoRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::EchoRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `message` + #[must_use] + pub fn message(&self) -> &'_ str { + self.0.reborrow().message + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for EchoRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + EchoRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: EchoRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for EchoRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::EchoRequest { + type View<'a> = EchoRequestView<'a>; + type ViewHandle = EchoRequestOwnedView; +} +impl ::serde::Serialize for EchoRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct EchoResponseView<'a> { /// Field 1: `message` @@ -353,6 +461,114 @@ impl ::buffa::ViewReborrow for EchoResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `EchoResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`EchoResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`EchoResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct EchoResponseOwnedView(::buffa::OwnedView>); +impl EchoResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EchoResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EchoResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::EchoResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EchoResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`EchoResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &EchoResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::EchoResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `message` + #[must_use] + pub fn message(&self) -> &'_ str { + self.0.reborrow().message + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for EchoResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + EchoResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: EchoResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for EchoResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::EchoResponse { + type View<'a> = EchoResponseView<'a>; + type ViewHandle = EchoResponseOwnedView; +} +impl ::serde::Serialize for EchoResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Request with a realistic mix of field types. #[derive(Clone, Debug, Default)] pub struct BenchRequestView<'a> { @@ -598,6 +814,127 @@ impl ::buffa::ViewReborrow for BenchRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `BenchRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`BenchRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`BenchRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct BenchRequestOwnedView(::buffa::OwnedView>); +impl BenchRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BenchRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BenchRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::BenchRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BenchRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`BenchRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &BenchRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::BenchRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Control fields + /// + /// for server-stream: how many responses + /// + /// Field 1: `response_count` + #[must_use] + pub fn response_count(&self) -> i32 { + self.0.reborrow().response_count + } + /// Payload: a realistic message with varied field types + /// + /// Field 2: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for BenchRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + BenchRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: BenchRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for BenchRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::BenchRequest { + type View<'a> = BenchRequestView<'a>; + type ViewHandle = BenchRequestOwnedView; +} +impl ::serde::Serialize for BenchRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct BenchResponseView<'a> { /// Field 1: `payload` @@ -803,6 +1140,116 @@ impl ::buffa::ViewReborrow for BenchResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `BenchResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`BenchResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`BenchResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct BenchResponseOwnedView(::buffa::OwnedView>); +impl BenchResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BenchResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BenchResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::BenchResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BenchResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`BenchResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &BenchResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::BenchResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for BenchResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + BenchResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: BenchResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for BenchResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::BenchResponse { + type View<'a> = BenchResponseView<'a>; + type ViewHandle = BenchResponseOwnedView; +} +impl ::serde::Serialize for BenchResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Exercises all major protobuf encoding paths. #[derive(Clone, Debug, Default)] pub struct PayloadView<'a> { @@ -1555,6 +2002,200 @@ impl ::buffa::ViewReborrow for PayloadView<'static> { this } } +/** Self-contained, `'static` owned view of a `Payload` message. + + Wraps [`::buffa::OwnedView`]`<`[`PayloadView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`PayloadView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct PayloadOwnedView(::buffa::OwnedView>); +impl PayloadOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(PayloadOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + PayloadOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Payload, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + PayloadOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`PayloadView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &PayloadView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Payload { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Scalars — varint, fixed-width, floating point + /// + /// Field 1: `id` + #[must_use] + pub fn id(&self) -> i32 { + self.0.reborrow().id + } + /// Field 2: `timestamp_nanos` + #[must_use] + pub fn timestamp_nanos(&self) -> i64 { + self.0.reborrow().timestamp_nanos + } + /// Field 3: `latitude` + #[must_use] + pub fn latitude(&self) -> f64 { + self.0.reborrow().latitude + } + /// Field 4: `longitude` + #[must_use] + pub fn longitude(&self) -> f64 { + self.0.reborrow().longitude + } + /// Field 5: `active` + #[must_use] + pub fn active(&self) -> bool { + self.0.reborrow().active + } + /// Field 6: `trace_id` + #[must_use] + pub fn trace_id(&self) -> u64 { + self.0.reborrow().trace_id + } + /// Strings — UTF-8 validation in proto, no special encoding in JSON + /// + /// Field 7: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// Field 8: `description` + #[must_use] + pub fn description(&self) -> &'_ str { + self.0.reborrow().description + } + /// Field 9: `region` + #[must_use] + pub fn region(&self) -> &'_ str { + self.0.reborrow().region + } + /// Bytes — base64 in JSON, raw in proto (key MessageView optimization target) + /// + /// Field 10: `data` + #[must_use] + pub fn data(&self) -> &'_ [u8] { + self.0.reborrow().data + } + /// Enum — varint in proto, string name in JSON + /// + /// Field 11: `status` + #[must_use] + pub fn status(&self) -> ::buffa::EnumValue { + self.0.reborrow().status + } + /// Nested message — recursive allocation in owned, recursive borrow in view + /// + /// Field 12: `metadata` + #[must_use] + pub fn metadata( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().metadata + } + /// Repeated scalars — packed encoding in proto + /// + /// Field 13: `scores` + #[must_use] + pub fn scores(&self) -> &::buffa::RepeatedView<'_, i32> { + &self.0.reborrow().scores + } + /// Repeated strings — N allocations in owned, N borrows in view + /// + /// Field 14: `tags` + #[must_use] + pub fn tags(&self) -> &::buffa::RepeatedView<'_, &'_ str> { + &self.0.reborrow().tags + } + /// Map — complex encoding in both proto and JSON + /// + /// Field 15: `attributes` (map) + #[must_use] + pub fn attributes(&self) -> &::buffa::MapView<'_, &'_ str, &'_ str> { + &self.0.reborrow().attributes + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for PayloadOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + PayloadOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: PayloadOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for PayloadOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Payload { + type View<'a> = PayloadView<'a>; + type ViewHandle = PayloadOwnedView; +} +impl ::serde::Serialize for PayloadOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct MetadataView<'a> { /// Field 1: `request_id` @@ -1896,6 +2537,127 @@ impl ::buffa::ViewReborrow for MetadataView<'static> { this } } +/** Self-contained, `'static` owned view of a `Metadata` message. + + Wraps [`::buffa::OwnedView`]`<`[`MetadataView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`MetadataView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct MetadataOwnedView(::buffa::OwnedView>); +impl MetadataOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(MetadataOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MetadataOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Metadata, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MetadataOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`MetadataView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &MetadataView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Metadata { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `request_id` + #[must_use] + pub fn request_id(&self) -> &'_ str { + self.0.reborrow().request_id + } + /// Field 2: `user_agent` + #[must_use] + pub fn user_agent(&self) -> &'_ str { + self.0.reborrow().user_agent + } + /// Field 3: `created_at` + #[must_use] + pub fn created_at(&self) -> i64 { + self.0.reborrow().created_at + } + /// Field 4: `headers` (map) + #[must_use] + pub fn headers(&self) -> &::buffa::MapView<'_, &'_ str, &'_ str> { + &self.0.reborrow().headers + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for MetadataOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + MetadataOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: MetadataOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for MetadataOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Metadata { + type View<'a> = MetadataView<'a>; + type ViewHandle = MetadataOwnedView; +} +impl ::serde::Serialize for MetadataOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// String-heavy message modeled after structured log records. /// Many small-to-medium string fields and a map of labels — each one /// is an allocation in owned decode, zero-copy in view decode. @@ -2099,6 +2861,116 @@ impl ::buffa::ViewReborrow for LogRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogRequestOwnedView(::buffa::OwnedView>); +impl LogRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `records` + #[must_use] + pub fn records( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::LogRecordView<'_>> { + &self.0.reborrow().records + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogRequest { + type View<'a> = LogRequestView<'a>; + type ViewHandle = LogRequestOwnedView; +} +impl ::serde::Serialize for LogRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogResponseView<'a> { /// Field 1: `count` @@ -2281,6 +3153,114 @@ impl ::buffa::ViewReborrow for LogResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogResponseOwnedView(::buffa::OwnedView>); +impl LogResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `count` + #[must_use] + pub fn count(&self) -> i32 { + self.0.reborrow().count + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogResponse { + type View<'a> = LogResponseView<'a>; + type ViewHandle = LogResponseOwnedView; +} +impl ::serde::Serialize for LogResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogRecordView<'a> { /// Field 1: `timestamp_nanos` @@ -2794,6 +3774,156 @@ impl ::buffa::ViewReborrow for LogRecordView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogRecord` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogRecordView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogRecordView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogRecordOwnedView(::buffa::OwnedView>); +impl LogRecordOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRecordOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRecordOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogRecord, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRecordOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogRecordView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogRecordView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogRecord { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `timestamp_nanos` + #[must_use] + pub fn timestamp_nanos(&self) -> i64 { + self.0.reborrow().timestamp_nanos + } + /// Field 2: `service_name` + #[must_use] + pub fn service_name(&self) -> &'_ str { + self.0.reborrow().service_name + } + /// Field 3: `instance_id` + #[must_use] + pub fn instance_id(&self) -> &'_ str { + self.0.reborrow().instance_id + } + /// Field 4: `severity` + #[must_use] + pub fn severity(&self) -> ::buffa::EnumValue { + self.0.reborrow().severity + } + /// Field 5: `message` + #[must_use] + pub fn message(&self) -> &'_ str { + self.0.reborrow().message + } + /// Field 6: `labels` (map) + #[must_use] + pub fn labels(&self) -> &::buffa::MapView<'_, &'_ str, &'_ str> { + &self.0.reborrow().labels + } + /// Field 7: `trace_id` + #[must_use] + pub fn trace_id(&self) -> &'_ str { + self.0.reborrow().trace_id + } + /// Field 8: `span_id` + #[must_use] + pub fn span_id(&self) -> &'_ str { + self.0.reborrow().span_id + } + /// Field 9: `source` + #[must_use] + pub fn source( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().source + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogRecordOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogRecordOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogRecordOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogRecordOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogRecord { + type View<'a> = LogRecordView<'a>; + type ViewHandle = LogRecordOwnedView; +} +impl ::serde::Serialize for LogRecordOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogSourceView<'a> { /// Field 1: `file` @@ -3030,6 +4160,124 @@ impl ::buffa::ViewReborrow for LogSourceView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogSource` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogSourceView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogSourceView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogSourceOwnedView(::buffa::OwnedView>); +impl LogSourceOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogSourceOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogSourceOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogSource, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogSourceOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogSourceView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogSourceView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogSource { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `file` + #[must_use] + pub fn file(&self) -> &'_ str { + self.0.reborrow().file + } + /// Field 2: `line` + #[must_use] + pub fn line(&self) -> i32 { + self.0.reborrow().line + } + /// Field 3: `function` + #[must_use] + pub fn function(&self) -> &'_ str { + self.0.reborrow().function + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogSourceOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogSourceOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogSourceOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogSourceOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogSource { + type View<'a> = LogSourceView<'a>; + type ViewHandle = LogSourceOwnedView; +} +impl ::serde::Serialize for LogSourceOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogIngestResponseView<'a> { /// Number of records processed. @@ -3324,3 +4572,139 @@ impl ::buffa::ViewReborrow for LogIngestResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogIngestResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogIngestResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogIngestResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogIngestResponseOwnedView( + ::buffa::OwnedView>, +); +impl LogIngestResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogIngestResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogIngestResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogIngestResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogIngestResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogIngestResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogIngestResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogIngestResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Number of records processed. + /// + /// Field 1: `count` + #[must_use] + pub fn count(&self) -> i32 { + self.0.reborrow().count + } + /// Sum of all message string lengths — proves the handler touched every + /// record's message field (forces varint-length decode + pointer resolve). + /// + /// Field 2: `total_message_bytes` + #[must_use] + pub fn total_message_bytes(&self) -> i64 { + self.0.reborrow().total_message_bytes + } + /// Sum of all label key+value lengths — proves map iteration happened. + /// + /// Field 3: `total_label_bytes` + #[must_use] + pub fn total_label_bytes(&self) -> i64 { + self.0.reborrow().total_label_bytes + } + /// Max severity seen — proves enum-varint decode for every record. + /// + /// Field 4: `max_severity` + #[must_use] + pub fn max_severity(&self) -> i32 { + self.0.reborrow().max_severity + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogIngestResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogIngestResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogIngestResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogIngestResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogIngestResponse { + type View<'a> = LogIngestResponseView<'a>; + type ViewHandle = LogIngestResponseOwnedView; +} +impl ::serde::Serialize for LogIngestResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/benches/rpc/src/generated/buffa/bench.noutf8.v1.mod.rs b/benches/rpc/src/generated/buffa/bench.noutf8.v1.mod.rs index 19aa7f1..dded62c 100644 --- a/benches/rpc/src/generated/buffa/bench.noutf8.v1.mod.rs +++ b/benches/rpc/src/generated/buffa/bench.noutf8.v1.mod.rs @@ -31,10 +31,18 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::LogRequestView; #[doc(inline)] +pub use self::__buffa::view::LogRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogRecordView; #[doc(inline)] +pub use self::__buffa::view::LogRecordOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogSourceView; #[doc(inline)] +pub use self::__buffa::view::LogSourceOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogIngestResponseView; #[doc(inline)] +pub use self::__buffa::view::LogIngestResponseOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/benches/rpc/src/generated/buffa/bench.rs b/benches/rpc/src/generated/buffa/bench.rs index a8d1de3..ab7fcb2 100644 --- a/benches/rpc/src/generated/buffa/bench.rs +++ b/benches/rpc/src/generated/buffa/bench.rs @@ -9,6 +9,20 @@ pub enum Status { STATUS_INACTIVE = 2i32, STATUS_PENDING = 3i32, } +impl Status { + ///Idiomatic alias for [`Self::STATUS_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::STATUS_UNSPECIFIED; + ///Idiomatic alias for [`Self::STATUS_ACTIVE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Active: Self = Self::STATUS_ACTIVE; + ///Idiomatic alias for [`Self::STATUS_INACTIVE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Inactive: Self = Self::STATUS_INACTIVE; + ///Idiomatic alias for [`Self::STATUS_PENDING`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Pending: Self = Self::STATUS_PENDING; +} impl ::core::default::Default for Status { fn default() -> Self { Self::STATUS_UNSPECIFIED @@ -2479,6 +2493,23 @@ pub mod log_record { SEVERITY_WARN = 3i32, SEVERITY_ERROR = 4i32, } + impl Severity { + ///Idiomatic alias for [`Self::SEVERITY_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::SEVERITY_UNSPECIFIED; + ///Idiomatic alias for [`Self::SEVERITY_DEBUG`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Debug: Self = Self::SEVERITY_DEBUG; + ///Idiomatic alias for [`Self::SEVERITY_INFO`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Info: Self = Self::SEVERITY_INFO; + ///Idiomatic alias for [`Self::SEVERITY_WARN`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Warn: Self = Self::SEVERITY_WARN; + ///Idiomatic alias for [`Self::SEVERITY_ERROR`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Error: Self = Self::SEVERITY_ERROR; + } impl ::core::default::Default for Severity { fn default() -> Self { Self::SEVERITY_UNSPECIFIED diff --git a/benches/rpc/src/generated/buffa/bench.v1.mod.rs b/benches/rpc/src/generated/buffa/bench.v1.mod.rs index fd269b4..a0eb40c 100644 --- a/benches/rpc/src/generated/buffa/bench.v1.mod.rs +++ b/benches/rpc/src/generated/buffa/bench.v1.mod.rs @@ -51,46 +51,90 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::EchoRequestView; #[doc(inline)] +pub use self::__buffa::view::EchoRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::EchoResponseView; #[doc(inline)] +pub use self::__buffa::view::EchoResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::BenchRequestView; #[doc(inline)] +pub use self::__buffa::view::BenchRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::BenchResponseView; #[doc(inline)] +pub use self::__buffa::view::BenchResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::PayloadView; #[doc(inline)] +pub use self::__buffa::view::PayloadOwnedView; +#[doc(inline)] pub use self::__buffa::view::MetadataView; #[doc(inline)] +pub use self::__buffa::view::MetadataOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogRequestView; #[doc(inline)] +pub use self::__buffa::view::LogRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogResponseView; #[doc(inline)] +pub use self::__buffa::view::LogResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogRecordView; #[doc(inline)] +pub use self::__buffa::view::LogRecordOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogSourceView; #[doc(inline)] +pub use self::__buffa::view::LogSourceOwnedView; +#[doc(inline)] pub use self::__buffa::view::LogIngestResponseView; #[doc(inline)] +pub use self::__buffa::view::LogIngestResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::BloatEchoView; #[doc(inline)] +pub use self::__buffa::view::BloatEchoOwnedView; +#[doc(inline)] pub use self::__buffa::view::BloatHeaderView; #[doc(inline)] +pub use self::__buffa::view::BloatHeaderOwnedView; +#[doc(inline)] pub use self::__buffa::view::ScalarHeavyView; #[doc(inline)] +pub use self::__buffa::view::ScalarHeavyOwnedView; +#[doc(inline)] pub use self::__buffa::view::FewLargeStringsView; #[doc(inline)] +pub use self::__buffa::view::FewLargeStringsOwnedView; +#[doc(inline)] pub use self::__buffa::view::NestL5View; #[doc(inline)] +pub use self::__buffa::view::NestL5OwnedView; +#[doc(inline)] pub use self::__buffa::view::NestL4View; #[doc(inline)] +pub use self::__buffa::view::NestL4OwnedView; +#[doc(inline)] pub use self::__buffa::view::NestL3View; #[doc(inline)] +pub use self::__buffa::view::NestL3OwnedView; +#[doc(inline)] pub use self::__buffa::view::NestL2View; #[doc(inline)] +pub use self::__buffa::view::NestL2OwnedView; +#[doc(inline)] pub use self::__buffa::view::NestL1View; #[doc(inline)] +pub use self::__buffa::view::NestL1OwnedView; +#[doc(inline)] pub use self::__buffa::view::DeepNestedView; #[doc(inline)] +pub use self::__buffa::view::DeepNestedOwnedView; +#[doc(inline)] pub use self::__buffa::view::MapDominatedView; #[doc(inline)] +pub use self::__buffa::view::MapDominatedOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/benches/rpc/src/generated/buffa/bench_noutf8.__view.rs b/benches/rpc/src/generated/buffa/bench_noutf8.__view.rs index d607089..8b6e81a 100644 --- a/benches/rpc/src/generated/buffa/bench_noutf8.__view.rs +++ b/benches/rpc/src/generated/buffa/bench_noutf8.__view.rs @@ -200,6 +200,116 @@ impl ::buffa::ViewReborrow for LogRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogRequestOwnedView(::buffa::OwnedView>); +impl LogRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `records` + #[must_use] + pub fn records( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::LogRecordView<'_>> { + &self.0.reborrow().records + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogRequest { + type View<'a> = LogRequestView<'a>; + type ViewHandle = LogRequestOwnedView; +} +impl ::serde::Serialize for LogRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogRecordView<'a> { /// Field 1: `timestamp_nanos` @@ -767,6 +877,158 @@ impl ::buffa::ViewReborrow for LogRecordView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogRecord` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogRecordView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogRecordView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogRecordOwnedView(::buffa::OwnedView>); +impl LogRecordOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRecordOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRecordOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogRecord, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogRecordOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogRecordView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogRecordView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogRecord { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `timestamp_nanos` + #[must_use] + pub fn timestamp_nanos(&self) -> ::core::option::Option { + self.0.reborrow().timestamp_nanos + } + /// Field 2: `service_name` + #[must_use] + pub fn service_name(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().service_name + } + /// Field 3: `instance_id` + #[must_use] + pub fn instance_id(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().instance_id + } + /// Field 4: `severity` + #[must_use] + pub fn severity( + &self, + ) -> ::core::option::Option<::buffa::EnumValue> { + self.0.reborrow().severity + } + /// Field 5: `message` + #[must_use] + pub fn message(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().message + } + /// Field 6: `labels` (map) + #[must_use] + pub fn labels(&self) -> &::buffa::MapView<'_, &'_ [u8], &'_ [u8]> { + &self.0.reborrow().labels + } + /// Field 7: `trace_id` + #[must_use] + pub fn trace_id(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().trace_id + } + /// Field 8: `span_id` + #[must_use] + pub fn span_id(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().span_id + } + /// Field 9: `source` + #[must_use] + pub fn source( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().source + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogRecordOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogRecordOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogRecordOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogRecordOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogRecord { + type View<'a> = LogRecordView<'a>; + type ViewHandle = LogRecordOwnedView; +} +impl ::serde::Serialize for LogRecordOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogSourceView<'a> { /// Field 1: `file` @@ -1021,6 +1283,124 @@ impl ::buffa::ViewReborrow for LogSourceView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogSource` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogSourceView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogSourceView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogSourceOwnedView(::buffa::OwnedView>); +impl LogSourceOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogSourceOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogSourceOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogSource, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogSourceOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogSourceView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogSourceView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogSource { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `file` + #[must_use] + pub fn file(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().file + } + /// Field 2: `line` + #[must_use] + pub fn line(&self) -> ::core::option::Option { + self.0.reborrow().line + } + /// Field 3: `function` + #[must_use] + pub fn function(&self) -> ::core::option::Option<&'_ [u8]> { + self.0.reborrow().function + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogSourceOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogSourceOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogSourceOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogSourceOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogSource { + type View<'a> = LogSourceView<'a>; + type ViewHandle = LogSourceOwnedView; +} +impl ::serde::Serialize for LogSourceOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct LogIngestResponseView<'a> { /// Field 1: `count` @@ -1306,3 +1686,130 @@ impl ::buffa::ViewReborrow for LogIngestResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `LogIngestResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`LogIngestResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`LogIngestResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct LogIngestResponseOwnedView( + ::buffa::OwnedView>, +); +impl LogIngestResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogIngestResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogIngestResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::LogIngestResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + LogIngestResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`LogIngestResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &LogIngestResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::LogIngestResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `count` + #[must_use] + pub fn count(&self) -> ::core::option::Option { + self.0.reborrow().count + } + /// Field 2: `total_message_bytes` + #[must_use] + pub fn total_message_bytes(&self) -> ::core::option::Option { + self.0.reborrow().total_message_bytes + } + /// Field 3: `total_label_bytes` + #[must_use] + pub fn total_label_bytes(&self) -> ::core::option::Option { + self.0.reborrow().total_label_bytes + } + /// Field 4: `max_severity` + #[must_use] + pub fn max_severity(&self) -> ::core::option::Option { + self.0.reborrow().max_severity + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for LogIngestResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + LogIngestResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: LogIngestResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for LogIngestResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::LogIngestResponse { + type View<'a> = LogIngestResponseView<'a>; + type ViewHandle = LogIngestResponseOwnedView; +} +impl ::serde::Serialize for LogIngestResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/benches/rpc/src/generated/buffa/bench_noutf8.rs b/benches/rpc/src/generated/buffa/bench_noutf8.rs index 17a35b8..25a8f7c 100644 --- a/benches/rpc/src/generated/buffa/bench_noutf8.rs +++ b/benches/rpc/src/generated/buffa/bench_noutf8.rs @@ -704,6 +704,23 @@ pub mod log_record { SEVERITY_WARN = 3i32, SEVERITY_ERROR = 4i32, } + impl Severity { + ///Idiomatic alias for [`Self::SEVERITY_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::SEVERITY_UNSPECIFIED; + ///Idiomatic alias for [`Self::SEVERITY_DEBUG`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Debug: Self = Self::SEVERITY_DEBUG; + ///Idiomatic alias for [`Self::SEVERITY_INFO`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Info: Self = Self::SEVERITY_INFO; + ///Idiomatic alias for [`Self::SEVERITY_WARN`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Warn: Self = Self::SEVERITY_WARN; + ///Idiomatic alias for [`Self::SEVERITY_ERROR`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Error: Self = Self::SEVERITY_ERROR; + } impl ::core::default::Default for Severity { fn default() -> Self { Self::SEVERITY_UNSPECIFIED diff --git a/benches/rpc/src/generated/buffa/echo_bloat.__view.rs b/benches/rpc/src/generated/buffa/echo_bloat.__view.rs index 13781a9..ac86cf7 100644 --- a/benches/rpc/src/generated/buffa/echo_bloat.__view.rs +++ b/benches/rpc/src/generated/buffa/echo_bloat.__view.rs @@ -743,6 +743,202 @@ impl ::buffa::ViewReborrow for BloatEchoView<'static> { this } } +/** Self-contained, `'static` owned view of a `BloatEcho` message. + + Wraps [`::buffa::OwnedView`]`<`[`BloatEchoView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`BloatEchoView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct BloatEchoOwnedView(::buffa::OwnedView>); +impl BloatEchoOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BloatEchoOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BloatEchoOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::BloatEcho, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BloatEchoOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`BloatEchoView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &BloatEchoView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::BloatEcho { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// 8 plain string fields + /// + /// Field 1: `tenant_id` + #[must_use] + pub fn tenant_id(&self) -> &'_ str { + self.0.reborrow().tenant_id + } + /// Field 2: `trace_id` + #[must_use] + pub fn trace_id(&self) -> &'_ str { + self.0.reborrow().trace_id + } + /// Field 3: `span_id` + #[must_use] + pub fn span_id(&self) -> &'_ str { + self.0.reborrow().span_id + } + /// Field 4: `service` + #[must_use] + pub fn service(&self) -> &'_ str { + self.0.reborrow().service + } + /// Field 5: `region` + #[must_use] + pub fn region(&self) -> &'_ str { + self.0.reborrow().region + } + /// Field 6: `instance_id` + #[must_use] + pub fn instance_id(&self) -> &'_ str { + self.0.reborrow().instance_id + } + /// Field 7: `request_path` + #[must_use] + pub fn request_path(&self) -> &'_ str { + self.0.reborrow().request_path + } + /// Field 8: `user_agent` + #[must_use] + pub fn user_agent(&self) -> &'_ str { + self.0.reborrow().user_agent + } + /// Scalars (round out the field count, low alloc impact) + /// + /// Field 9: `timestamp_nanos` + #[must_use] + pub fn timestamp_nanos(&self) -> i64 { + self.0.reborrow().timestamp_nanos + } + /// Field 10: `status_code` + #[must_use] + pub fn status_code(&self) -> i32 { + self.0.reborrow().status_code + } + /// Repeated strings — N small allocs in owned, N borrows in view + /// + /// Field 11: `tags` + #[must_use] + pub fn tags(&self) -> &::buffa::RepeatedView<'_, &'_ str> { + &self.0.reborrow().tags + } + /// String map — 2N allocs + HashMap insert overhead in owned + /// + /// Field 12: `labels` (map) + #[must_use] + pub fn labels(&self) -> &::buffa::MapView<'_, &'_ str, &'_ str> { + &self.0.reborrow().labels + } + /// Two singular nested sub-messages + /// + /// Field 13: `auth` + #[must_use] + pub fn auth( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().auth + } + /// Field 14: `origin` + #[must_use] + pub fn origin( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().origin + } + /// Repeated nested sub-messages + /// + /// Field 15: `extra_headers` + #[must_use] + pub fn extra_headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::BloatHeaderView<'_>> { + &self.0.reborrow().extra_headers + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for BloatEchoOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + BloatEchoOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: BloatEchoOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for BloatEchoOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::BloatEcho { + type View<'a> = BloatEchoView<'a>; + type ViewHandle = BloatEchoOwnedView; +} +impl ::serde::Serialize for BloatEchoOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct BloatHeaderView<'a> { /// Field 1: `name` @@ -1000,6 +1196,129 @@ impl ::buffa::ViewReborrow for BloatHeaderView<'static> { this } } +/** Self-contained, `'static` owned view of a `BloatHeader` message. + + Wraps [`::buffa::OwnedView`]`<`[`BloatHeaderView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`BloatHeaderView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct BloatHeaderOwnedView(::buffa::OwnedView>); +impl BloatHeaderOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BloatHeaderOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BloatHeaderOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::BloatHeader, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BloatHeaderOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`BloatHeaderView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &BloatHeaderView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::BloatHeader { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// Field 2: `value` + #[must_use] + pub fn value(&self) -> &'_ str { + self.0.reborrow().value + } + /// Field 3: `source` + #[must_use] + pub fn source(&self) -> &'_ str { + self.0.reborrow().source + } + /// Field 4: `note` + #[must_use] + pub fn note(&self) -> &'_ str { + self.0.reborrow().note + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for BloatHeaderOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + BloatHeaderOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: BloatHeaderOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for BloatHeaderOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::BloatHeader { + type View<'a> = BloatHeaderView<'a>; + type ViewHandle = BloatHeaderOwnedView; +} +impl ::serde::Serialize for BloatHeaderOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// ── Shape-sweep messages for the ViewEncode mental-model bench ──────── /// /// Each shape isolates one dimension (alloc count, payload bytes, nesting @@ -1739,6 +2058,199 @@ impl ::buffa::ViewReborrow for ScalarHeavyView<'static> { this } } +/** Self-contained, `'static` owned view of a `ScalarHeavy` message. + + Wraps [`::buffa::OwnedView`]`<`[`ScalarHeavyView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ScalarHeavyView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ScalarHeavyOwnedView(::buffa::OwnedView>); +impl ScalarHeavyOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ScalarHeavyOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ScalarHeavyOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ScalarHeavy, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ScalarHeavyOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ScalarHeavyView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ScalarHeavyView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ScalarHeavy { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> i64 { + self.0.reborrow().a + } + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> i64 { + self.0.reborrow().b + } + /// Field 3: `c` + #[must_use] + pub fn c(&self) -> i64 { + self.0.reborrow().c + } + /// Field 4: `d` + #[must_use] + pub fn d(&self) -> i64 { + self.0.reborrow().d + } + /// Field 5: `e` + #[must_use] + pub fn e(&self) -> i64 { + self.0.reborrow().e + } + /// Field 6: `f` + #[must_use] + pub fn f(&self) -> i64 { + self.0.reborrow().f + } + /// Field 7: `g` + #[must_use] + pub fn g(&self) -> i64 { + self.0.reborrow().g + } + /// Field 8: `h` + #[must_use] + pub fn h(&self) -> i64 { + self.0.reborrow().h + } + /// Field 9: `i` + #[must_use] + pub fn i(&self) -> i64 { + self.0.reborrow().i + } + /// Field 10: `j` + #[must_use] + pub fn j(&self) -> i64 { + self.0.reborrow().j + } + /// Field 11: `k` + #[must_use] + pub fn k(&self) -> i64 { + self.0.reborrow().k + } + /// Field 12: `l` + #[must_use] + pub fn l(&self) -> i64 { + self.0.reborrow().l + } + /// Field 13: `m` + #[must_use] + pub fn m(&self) -> i32 { + self.0.reborrow().m + } + /// Field 14: `n` + #[must_use] + pub fn n(&self) -> i32 { + self.0.reborrow().n + } + /// Field 15: `o` + #[must_use] + pub fn o(&self) -> i32 { + self.0.reborrow().o + } + /// Field 16: `p` + #[must_use] + pub fn p(&self) -> i32 { + self.0.reborrow().p + } + /// Field 17: `note_a` + #[must_use] + pub fn note_a(&self) -> &'_ str { + self.0.reborrow().note_a + } + /// Field 18: `note_b` + #[must_use] + pub fn note_b(&self) -> &'_ str { + self.0.reborrow().note_b + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ScalarHeavyOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ScalarHeavyOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ScalarHeavyOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ScalarHeavyOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ScalarHeavy { + type View<'a> = ScalarHeavyView<'a>; + type ViewHandle = ScalarHeavyOwnedView; +} +impl ::serde::Serialize for ScalarHeavyOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Few large strings: 4×~1200B + 2 scalars. Low alloc count, high bytes. #[derive(Clone, Debug, Default)] pub struct FewLargeStringsView<'a> { @@ -2063,6 +2575,141 @@ impl ::buffa::ViewReborrow for FewLargeStringsView<'static> { this } } +/** Self-contained, `'static` owned view of a `FewLargeStrings` message. + + Wraps [`::buffa::OwnedView`]`<`[`FewLargeStringsView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`FewLargeStringsView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct FewLargeStringsOwnedView(::buffa::OwnedView>); +impl FewLargeStringsOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FewLargeStringsOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FewLargeStringsOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::FewLargeStrings, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FewLargeStringsOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`FewLargeStringsView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &FewLargeStringsView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::FewLargeStrings { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `body_a` + #[must_use] + pub fn body_a(&self) -> &'_ str { + self.0.reborrow().body_a + } + /// Field 2: `body_b` + #[must_use] + pub fn body_b(&self) -> &'_ str { + self.0.reborrow().body_b + } + /// Field 3: `body_c` + #[must_use] + pub fn body_c(&self) -> &'_ str { + self.0.reborrow().body_c + } + /// Field 4: `body_d` + #[must_use] + pub fn body_d(&self) -> &'_ str { + self.0.reborrow().body_d + } + /// Field 5: `ts` + #[must_use] + pub fn ts(&self) -> i64 { + self.0.reborrow().ts + } + /// Field 6: `seq` + #[must_use] + pub fn seq(&self) -> i64 { + self.0.reborrow().seq + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for FewLargeStringsOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + FewLargeStringsOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: FewLargeStringsOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for FewLargeStringsOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::FewLargeStrings { + type View<'a> = FewLargeStringsView<'a>; + type ViewHandle = FewLargeStringsOwnedView; +} +impl ::serde::Serialize for FewLargeStringsOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Deep nested: 5 levels of singular sub-message, 2 strings per level. /// Tests `MessageFieldView` boxing on the view side. #[derive(Clone, Debug, Default)] @@ -2268,6 +2915,113 @@ impl ::buffa::ViewReborrow for NestL5View<'static> { this } } +/** Self-contained, `'static` owned view of a `NestL5` message. + + Wraps [`::buffa::OwnedView`]`<`[`NestL5View`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`NestL5View`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct NestL5OwnedView(::buffa::OwnedView>); +impl NestL5OwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL5OwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + NestL5OwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::NestL5, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL5OwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`NestL5View`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &NestL5View<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::NestL5 { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> &'_ str { + self.0.reborrow().a + } + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> &'_ str { + self.0.reborrow().b + } +} +impl ::core::convert::From<::buffa::OwnedView>> for NestL5OwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + NestL5OwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: NestL5OwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for NestL5OwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::NestL5 { + type View<'a> = NestL5View<'a>; + type ViewHandle = NestL5OwnedView; +} +impl ::serde::Serialize for NestL5OwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct NestL4View<'a> { /// Field 1: `a` @@ -2527,6 +3281,120 @@ impl ::buffa::ViewReborrow for NestL4View<'static> { this } } +/** Self-contained, `'static` owned view of a `NestL4` message. + + Wraps [`::buffa::OwnedView`]`<`[`NestL4View`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`NestL4View`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct NestL4OwnedView(::buffa::OwnedView>); +impl NestL4OwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL4OwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + NestL4OwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::NestL4, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL4OwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`NestL4View`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &NestL4View<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::NestL4 { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> &'_ str { + self.0.reborrow().a + } + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> &'_ str { + self.0.reborrow().b + } + /// Field 3: `child` + #[must_use] + pub fn child( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().child + } +} +impl ::core::convert::From<::buffa::OwnedView>> for NestL4OwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + NestL4OwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: NestL4OwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for NestL4OwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::NestL4 { + type View<'a> = NestL4View<'a>; + type ViewHandle = NestL4OwnedView; +} +impl ::serde::Serialize for NestL4OwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct NestL3View<'a> { /// Field 1: `a` @@ -2786,6 +3654,120 @@ impl ::buffa::ViewReborrow for NestL3View<'static> { this } } +/** Self-contained, `'static` owned view of a `NestL3` message. + + Wraps [`::buffa::OwnedView`]`<`[`NestL3View`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`NestL3View`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct NestL3OwnedView(::buffa::OwnedView>); +impl NestL3OwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL3OwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + NestL3OwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::NestL3, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL3OwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`NestL3View`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &NestL3View<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::NestL3 { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> &'_ str { + self.0.reborrow().a + } + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> &'_ str { + self.0.reborrow().b + } + /// Field 3: `child` + #[must_use] + pub fn child( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().child + } +} +impl ::core::convert::From<::buffa::OwnedView>> for NestL3OwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + NestL3OwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: NestL3OwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for NestL3OwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::NestL3 { + type View<'a> = NestL3View<'a>; + type ViewHandle = NestL3OwnedView; +} +impl ::serde::Serialize for NestL3OwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct NestL2View<'a> { /// Field 1: `a` @@ -3045,6 +4027,120 @@ impl ::buffa::ViewReborrow for NestL2View<'static> { this } } +/** Self-contained, `'static` owned view of a `NestL2` message. + + Wraps [`::buffa::OwnedView`]`<`[`NestL2View`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`NestL2View`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct NestL2OwnedView(::buffa::OwnedView>); +impl NestL2OwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL2OwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + NestL2OwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::NestL2, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL2OwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`NestL2View`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &NestL2View<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::NestL2 { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> &'_ str { + self.0.reborrow().a + } + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> &'_ str { + self.0.reborrow().b + } + /// Field 3: `child` + #[must_use] + pub fn child( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().child + } +} +impl ::core::convert::From<::buffa::OwnedView>> for NestL2OwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + NestL2OwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: NestL2OwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for NestL2OwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::NestL2 { + type View<'a> = NestL2View<'a>; + type ViewHandle = NestL2OwnedView; +} +impl ::serde::Serialize for NestL2OwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct NestL1View<'a> { /// Field 1: `a` @@ -3304,6 +4400,120 @@ impl ::buffa::ViewReborrow for NestL1View<'static> { this } } +/** Self-contained, `'static` owned view of a `NestL1` message. + + Wraps [`::buffa::OwnedView`]`<`[`NestL1View`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`NestL1View`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct NestL1OwnedView(::buffa::OwnedView>); +impl NestL1OwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL1OwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + NestL1OwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::NestL1, + ) -> ::core::result::Result { + ::core::result::Result::Ok(NestL1OwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`NestL1View`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &NestL1View<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::NestL1 { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> &'_ str { + self.0.reborrow().a + } + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> &'_ str { + self.0.reborrow().b + } + /// Field 3: `child` + #[must_use] + pub fn child( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().child + } +} +impl ::core::convert::From<::buffa::OwnedView>> for NestL1OwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + NestL1OwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: NestL1OwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for NestL1OwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::NestL1 { + type View<'a> = NestL1View<'a>; + type ViewHandle = NestL1OwnedView; +} +impl ::serde::Serialize for NestL1OwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct DeepNestedView<'a> { /// Field 1: `root_a` @@ -3563,6 +4773,126 @@ impl ::buffa::ViewReborrow for DeepNestedView<'static> { this } } +/** Self-contained, `'static` owned view of a `DeepNested` message. + + Wraps [`::buffa::OwnedView`]`<`[`DeepNestedView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`DeepNestedView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct DeepNestedOwnedView(::buffa::OwnedView>); +impl DeepNestedOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + DeepNestedOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + DeepNestedOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::DeepNested, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + DeepNestedOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`DeepNestedView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &DeepNestedView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::DeepNested { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `root_a` + #[must_use] + pub fn root_a(&self) -> &'_ str { + self.0.reborrow().root_a + } + /// Field 2: `root_b` + #[must_use] + pub fn root_b(&self) -> &'_ str { + self.0.reborrow().root_b + } + /// Field 3: `child` + #[must_use] + pub fn child( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().child + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for DeepNestedOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + DeepNestedOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: DeepNestedOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for DeepNestedOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::DeepNested { + type View<'a> = DeepNestedView<'a>; + type ViewHandle = DeepNestedOwnedView; +} +impl ::serde::Serialize for DeepNestedOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Map-dominated: 30-entry string map + 2 plain strings. Closest to the /// LogRecord shape that hit 5.8× in the buffa build_encode benches. #[derive(Clone, Debug, Default)] @@ -3873,3 +5203,121 @@ impl ::buffa::ViewReborrow for MapDominatedView<'static> { this } } +/** Self-contained, `'static` owned view of a `MapDominated` message. + + Wraps [`::buffa::OwnedView`]`<`[`MapDominatedView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`MapDominatedView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct MapDominatedOwnedView(::buffa::OwnedView>); +impl MapDominatedOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MapDominatedOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MapDominatedOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::MapDominated, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MapDominatedOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`MapDominatedView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &MapDominatedView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::MapDominated { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `id` + #[must_use] + pub fn id(&self) -> &'_ str { + self.0.reborrow().id + } + /// Field 2: `kind` + #[must_use] + pub fn kind(&self) -> &'_ str { + self.0.reborrow().kind + } + /// Field 3: `labels` (map) + #[must_use] + pub fn labels(&self) -> &::buffa::MapView<'_, &'_ str, &'_ str> { + &self.0.reborrow().labels + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for MapDominatedOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + MapDominatedOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: MapDominatedOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for MapDominatedOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::MapDominated { + type View<'a> = MapDominatedView<'a>; + type ViewHandle = MapDominatedOwnedView; +} +impl ::serde::Serialize for MapDominatedOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/benches/rpc/src/generated/buffa/filter.__view.rs b/benches/rpc/src/generated/buffa/filter.__view.rs index ed67467..fe0c94c 100644 --- a/benches/rpc/src/generated/buffa/filter.__view.rs +++ b/benches/rpc/src/generated/buffa/filter.__view.rs @@ -446,3 +446,142 @@ impl ::buffa::ViewReborrow for RecordView<'static> { this } } +/** Self-contained, `'static` owned view of a `Record` message. + + Wraps [`::buffa::OwnedView`]`<`[`RecordView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`RecordView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct RecordOwnedView(::buffa::OwnedView>); +impl RecordOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(RecordOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RecordOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Record, + ) -> ::core::result::Result { + ::core::result::Result::Ok(RecordOwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`RecordView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &RecordView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Record { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `id` + #[must_use] + pub fn id(&self) -> &'_ str { + self.0.reborrow().id + } + /// Field 2: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// Field 3: `description` + #[must_use] + pub fn description(&self) -> &'_ str { + self.0.reborrow().description + } + /// Sensitive: scrubbed if non-empty. + /// + /// Field 4: `email` + #[must_use] + pub fn email(&self) -> &'_ str { + self.0.reborrow().email + } + /// Field 5: `ssn` + #[must_use] + pub fn ssn(&self) -> &'_ str { + self.0.reborrow().ssn + } + /// Field 6: `notes` + #[must_use] + pub fn notes(&self) -> &'_ str { + self.0.reborrow().notes + } + /// Field 7: `tags` + #[must_use] + pub fn tags(&self) -> &::buffa::RepeatedView<'_, &'_ str> { + &self.0.reborrow().tags + } + /// Field 8: `attributes` (map) + #[must_use] + pub fn attributes(&self) -> &::buffa::MapView<'_, &'_ str, &'_ str> { + &self.0.reborrow().attributes + } +} +impl ::core::convert::From<::buffa::OwnedView>> for RecordOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + RecordOwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: RecordOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for RecordOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Record { + type View<'a> = RecordView<'a>; + type ViewHandle = RecordOwnedView; +} +impl ::serde::Serialize for RecordOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/benches/rpc/src/generated/buffa/fortune.__view.rs b/benches/rpc/src/generated/buffa/fortune.__view.rs index 6327651..9f1e1f8 100644 --- a/benches/rpc/src/generated/buffa/fortune.__view.rs +++ b/benches/rpc/src/generated/buffa/fortune.__view.rs @@ -150,6 +150,113 @@ impl ::buffa::ViewReborrow for GetFortunesRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `GetFortunesRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`GetFortunesRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`GetFortunesRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct GetFortunesRequestOwnedView( + ::buffa::OwnedView>, +); +impl GetFortunesRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GetFortunesRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GetFortunesRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::GetFortunesRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GetFortunesRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`GetFortunesRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &GetFortunesRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::GetFortunesRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for GetFortunesRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + GetFortunesRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: GetFortunesRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for GetFortunesRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::GetFortunesRequest { + type View<'a> = GetFortunesRequestView<'a>; + type ViewHandle = GetFortunesRequestOwnedView; +} +impl ::serde::Serialize for GetFortunesRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct GetFortunesResponseView<'a> { /// Field 1: `fortunes` @@ -349,6 +456,120 @@ impl ::buffa::ViewReborrow for GetFortunesResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `GetFortunesResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`GetFortunesResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`GetFortunesResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct GetFortunesResponseOwnedView( + ::buffa::OwnedView>, +); +impl GetFortunesResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GetFortunesResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GetFortunesResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::GetFortunesResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GetFortunesResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`GetFortunesResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &GetFortunesResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::GetFortunesResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `fortunes` + #[must_use] + pub fn fortunes( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::FortuneView<'_>> { + &self.0.reborrow().fortunes + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for GetFortunesResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + GetFortunesResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: GetFortunesResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for GetFortunesResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::GetFortunesResponse { + type View<'a> = GetFortunesResponseView<'a>; + type ViewHandle = GetFortunesResponseOwnedView; +} +impl ::serde::Serialize for GetFortunesResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct FortuneView<'a> { /// Field 1: `id` @@ -558,3 +779,114 @@ impl ::buffa::ViewReborrow for FortuneView<'static> { this } } +/** Self-contained, `'static` owned view of a `Fortune` message. + + Wraps [`::buffa::OwnedView`]`<`[`FortuneView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`FortuneView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct FortuneOwnedView(::buffa::OwnedView>); +impl FortuneOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(FortuneOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FortuneOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Fortune, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FortuneOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`FortuneView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &FortuneView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Fortune { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `id` + #[must_use] + pub fn id(&self) -> i32 { + self.0.reborrow().id + } + /// Field 2: `message` + #[must_use] + pub fn message(&self) -> &'_ str { + self.0.reborrow().message + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for FortuneOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + FortuneOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: FortuneOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for FortuneOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Fortune { + type View<'a> = FortuneView<'a>; + type ViewHandle = FortuneOwnedView; +} +impl ::serde::Serialize for FortuneOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/benches/rpc/src/generated/buffa/fortune.v1.mod.rs b/benches/rpc/src/generated/buffa/fortune.v1.mod.rs index a50097e..31805d0 100644 --- a/benches/rpc/src/generated/buffa/fortune.v1.mod.rs +++ b/benches/rpc/src/generated/buffa/fortune.v1.mod.rs @@ -30,8 +30,14 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::GetFortunesRequestView; #[doc(inline)] +pub use self::__buffa::view::GetFortunesRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::GetFortunesResponseView; #[doc(inline)] +pub use self::__buffa::view::GetFortunesResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::FortuneView; #[doc(inline)] +pub use self::__buffa::view::FortuneOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/benches/rpc/src/generated/connect/bench.__connect.rs b/benches/rpc/src/generated/connect/bench.__connect.rs index 2d0c2d6..325a8e2 100644 --- a/benches/rpc/src/generated/connect/bench.__connect.rs +++ b/benches/rpc/src/generated/connect/bench.__connect.rs @@ -43,7 +43,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable @@ -63,7 +63,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable @@ -83,7 +83,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable @@ -103,7 +103,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -166,19 +166,31 @@ pub const BENCH_SERVICE_LOG_UNARY_OWNED_SPEC: ::connectrpc::Spec = ::connectrpc: /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -191,10 +203,11 @@ pub const BENCH_SERVICE_LOG_UNARY_OWNED_SPEC: ::connectrpc::Spec = ::connectrpc: /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -202,10 +215,16 @@ pub trait BenchService: Send + Sync + 'static { /// Handle the Unary RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn unary<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedBenchRequestView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::BenchRequest>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -214,10 +233,16 @@ pub trait BenchService: Send + Sync + 'static { >, > + Send; /// Handle the ServerStream RPC. + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call (until the response stream is returned); + /// message fields are read directly on it (zero-copy). Data the + /// returned stream needs must be copied out or converted via + /// `.to_owned_message()`. fn server_stream( &self, ctx: ::connectrpc::RequestContext, - request: OwnedBenchRequestView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::BenchRequest>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< ::connectrpc::ServiceStream< @@ -230,10 +255,18 @@ pub trait BenchService: Send + Sync + 'static { /// Handle the ClientStream RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// Each `requests` item is a [`StreamMessage`](::connectrpc::StreamMessage): + /// it owns its buffer, is `Send + 'static`, and exposes zero-copy + /// accessor methods (`item.name()`), `.view()`, and + /// `.to_owned_message()`. Items can be yielded back unchanged + /// (`StreamMessage` implements `Encodable`). fn client_stream<'a>( &'a self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream, + requests: ::connectrpc::ServiceStream< + ::connectrpc::StreamMessage, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -242,10 +275,18 @@ pub trait BenchService: Send + Sync + 'static { >, > + Send; /// Handle the BidiStream RPC. + /// + /// Each `requests` item is a [`StreamMessage`](::connectrpc::StreamMessage): + /// it owns its buffer, is `Send + 'static`, and exposes zero-copy + /// accessor methods (`item.name()`), `.view()`, and + /// `.to_owned_message()`. Items can be yielded back unchanged + /// (`StreamMessage` implements `Encodable`). fn bidi_stream( &self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream, + requests: ::connectrpc::ServiceStream< + ::connectrpc::StreamMessage, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< ::connectrpc::ServiceStream< @@ -258,10 +299,16 @@ pub trait BenchService: Send + Sync + 'static { /// Handle the LogUnary RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn log_unary<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedLogRequestView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::LogRequest>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -272,10 +319,16 @@ pub trait BenchService: Send + Sync + 'static { /// Handle the LogUnaryOwned RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn log_unary_owned<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedLogRequestView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::LogRequest>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -317,10 +370,21 @@ impl BenchServiceExt for S { "Unary", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::BenchRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.unary(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::BenchRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.unary(ctx, sreq) .await? .encode::(format) } @@ -337,9 +401,21 @@ impl BenchServiceExt for S { "ServerStream", ::connectrpc::view_streaming_handler_fn({ let svc = ::std::sync::Arc::clone(&self); - move |ctx, req| { + move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::BenchRequestView< + 'static, + >, + >| + { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.server_stream(ctx, req).await } + async move { + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::BenchRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.server_stream(ctx, sreq).await + } } }), ) @@ -352,6 +428,9 @@ impl BenchServiceExt for S { move |ctx, req, format| { let svc = ::std::sync::Arc::clone(&svc); async move { + let req = ::connectrpc::dispatcher::codegen::into_stream_messages::< + crate::proto::bench::v1::BenchRequest, + >(req); svc.client_stream(ctx, req) .await? .encode::(format) @@ -371,7 +450,12 @@ impl BenchServiceExt for S { let svc = ::std::sync::Arc::clone(&self); move |ctx, req| { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.bidi_stream(ctx, req).await } + async move { + let req = ::connectrpc::dispatcher::codegen::into_stream_messages::< + crate::proto::bench::v1::BenchRequest, + >(req); + svc.bidi_stream(ctx, req).await + } } }), ) @@ -381,10 +465,21 @@ impl BenchServiceExt for S { "LogUnary", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::LogRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.log_unary(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::LogRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.log_unary(ctx, sreq) .await? .encode::(format) } @@ -397,10 +492,21 @@ impl BenchServiceExt for S { "LogUnaryOwned", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::LogRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.log_unary_owned(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::LogRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.log_unary_owned(ctx, sreq) .await? .encode::(format) } @@ -507,9 +613,17 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { "Unary" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::BenchRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::BenchRequest, >(request.encoded()?, format)?; + let req: crate::proto::bench::v1::__buffa::view::BenchRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::BenchRequest, + >::from_parts(&req, &body); svc.unary(ctx, req) .await? .encode::(format) @@ -518,9 +632,17 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { "LogUnary" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::LogRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::LogRequest, >(request.encoded()?, format)?; + let req: crate::proto::bench::v1::__buffa::view::LogRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::LogRequest, + >::from_parts(&req, &body); svc.log_unary(ctx, req) .await? .encode::(format) @@ -529,9 +651,17 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { "LogUnaryOwned" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::LogRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::LogRequest, >(request.encoded()?, format)?; + let req: crate::proto::bench::v1::__buffa::view::LogRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::LogRequest, + >::from_parts(&req, &body); svc.log_unary_owned(ctx, req) .await? .encode::(format) @@ -555,9 +685,17 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { "ServerStream" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::BenchRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::BenchRequest, >(request, format)?; + let req: crate::proto::bench::v1::__buffa::view::BenchRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::BenchRequest, + >::from_parts(&req, &body); let resp = svc.server_stream(ctx, req).await?; Ok( resp @@ -587,8 +725,8 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { "ClientStream" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::< - crate::proto::bench::v1::__buffa::view::BenchRequestView, + let req_stream = ::connectrpc::dispatcher::codegen::decode_message_request_stream::< + crate::proto::bench::v1::BenchRequest, >(requests, format); svc.client_stream(ctx, req_stream) .await? @@ -613,8 +751,8 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { "BidiStream" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::< - crate::proto::bench::v1::__buffa::view::BenchRequestView, + let req_stream = ::connectrpc::dispatcher::codegen::decode_message_request_stream::< + crate::proto::bench::v1::BenchRequest, >(requests, format); let resp = svc.bidi_stream(ctx, req_stream).await?; Ok( @@ -667,11 +805,12 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.unary(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.unary(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -680,6 +819,12 @@ impl ::connectrpc::Dispatcher for BenchServiceServer { /// ```rust,ignore /// let owned = client.unary(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct BenchServiceClient { transport: T, @@ -954,19 +1099,31 @@ pub const ECHO_SERVICE_ECHO_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::serve /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -979,10 +1136,11 @@ pub const ECHO_SERVICE_ECHO_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::serve /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -990,10 +1148,16 @@ pub trait EchoService: Send + Sync + 'static { /// Handle the Echo RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn echo<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedEchoRequestView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::EchoRequest>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -1035,10 +1199,21 @@ impl EchoServiceExt for S { "Echo", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::EchoRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.echo(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::EchoRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.echo(ctx, sreq) .await? .encode::(format) } @@ -1115,9 +1290,17 @@ impl ::connectrpc::Dispatcher for EchoServiceServer { "Echo" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::EchoRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::EchoRequest, >(request.encoded()?, format)?; + let req: crate::proto::bench::v1::__buffa::view::EchoRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::EchoRequest, + >::from_parts(&req, &body); svc.echo(ctx, req) .await? .encode::(format) @@ -1208,11 +1391,12 @@ impl ::connectrpc::Dispatcher for EchoServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.echo(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.echo(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -1221,6 +1405,12 @@ impl ::connectrpc::Dispatcher for EchoServiceServer { /// ```rust,ignore /// let owned = client.echo(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct EchoServiceClient { transport: T, @@ -1297,19 +1487,31 @@ pub const LOG_INGEST_SERVICE_INGEST_SPEC: ::connectrpc::Spec = ::connectrpc::Spe /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -1322,10 +1524,11 @@ pub const LOG_INGEST_SERVICE_INGEST_SPEC: ::connectrpc::Spec = ::connectrpc::Spe /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -1333,10 +1536,16 @@ pub trait LogIngestService: Send + Sync + 'static { /// Handle the Ingest RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn ingest<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedLogRequestView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::LogRequest>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -1378,10 +1587,21 @@ impl LogIngestServiceExt for S { "Ingest", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::LogRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.ingest(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::LogRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.ingest(ctx, sreq) .await? .encode::< crate::proto::bench::v1::LogIngestResponse, @@ -1460,9 +1680,17 @@ impl ::connectrpc::Dispatcher for LogIngestServiceServer "Ingest" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::LogRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::LogRequest, >(request.encoded()?, format)?; + let req: crate::proto::bench::v1::__buffa::view::LogRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::LogRequest, + >::from_parts(&req, &body); svc.ingest(ctx, req) .await? .encode::(format) @@ -1553,11 +1781,12 @@ impl ::connectrpc::Dispatcher for LogIngestServiceServer /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.ingest(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.ingest(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -1566,6 +1795,12 @@ impl ::connectrpc::Dispatcher for LogIngestServiceServer /// ```rust,ignore /// let owned = client.ingest(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct LogIngestServiceClient { transport: T, diff --git a/benches/rpc/src/generated/connect/bench_noutf8.__connect.rs b/benches/rpc/src/generated/connect/bench_noutf8.__connect.rs index df9aa3d..25fb77d 100644 --- a/benches/rpc/src/generated/connect/bench_noutf8.__connect.rs +++ b/benches/rpc/src/generated/connect/bench_noutf8.__connect.rs @@ -23,7 +23,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -41,19 +41,31 @@ pub const LOG_INGEST_SERVICE_INGEST_SPEC: ::connectrpc::Spec = ::connectrpc::Spe /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -66,10 +78,11 @@ pub const LOG_INGEST_SERVICE_INGEST_SPEC: ::connectrpc::Spec = ::connectrpc::Spe /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -77,10 +90,19 @@ pub trait LogIngestService: Send + Sync + 'static { /// Handle the Ingest RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn ingest<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedLogRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::bench::noutf8::v1::LogRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -122,10 +144,21 @@ impl LogIngestServiceExt for S { "Ingest", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::noutf8::v1::__buffa::view::LogRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.ingest(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::noutf8::v1::LogRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.ingest(ctx, sreq) .await? .encode::< crate::proto::bench::noutf8::v1::LogIngestResponse, @@ -204,9 +237,17 @@ impl ::connectrpc::Dispatcher for LogIngestServiceServer "Ingest" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::noutf8::v1::__buffa::view::LogRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::noutf8::v1::LogRequest, >(request.encoded()?, format)?; + let req: crate::proto::bench::noutf8::v1::__buffa::view::LogRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::noutf8::v1::LogRequest, + >::from_parts(&req, &body); svc.ingest(ctx, req) .await? .encode::< @@ -299,11 +340,12 @@ impl ::connectrpc::Dispatcher for LogIngestServiceServer /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.ingest(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.ingest(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -312,6 +354,12 @@ impl ::connectrpc::Dispatcher for LogIngestServiceServer /// ```rust,ignore /// let owned = client.ingest(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct LogIngestServiceClient { transport: T, diff --git a/benches/rpc/src/generated/connect/echo_bloat.__connect.rs b/benches/rpc/src/generated/connect/echo_bloat.__connect.rs index 9bb0fb5..351a264 100644 --- a/benches/rpc/src/generated/connect/echo_bloat.__connect.rs +++ b/benches/rpc/src/generated/connect/echo_bloat.__connect.rs @@ -19,7 +19,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -42,19 +42,31 @@ pub const BLOAT_ECHO_SERVICE_ECHO_SPEC: ::connectrpc::Spec = ::connectrpc::Spec: /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -67,10 +79,11 @@ pub const BLOAT_ECHO_SERVICE_ECHO_SPEC: ::connectrpc::Spec = ::connectrpc::Spec: /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -78,10 +91,16 @@ pub trait BloatEchoService: Send + Sync + 'static { /// Handle the Echo RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn echo<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedBloatEchoView, + request: ::connectrpc::ServiceRequest<'_, crate::proto::bench::v1::BloatEcho>, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -123,10 +142,21 @@ impl BloatEchoServiceExt for S { "Echo", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::bench::v1::__buffa::view::BloatEchoView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.echo(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::BloatEcho, + >::from_parts(req.reborrow(), req.bytes()); + svc.echo(ctx, sreq) .await? .encode::(format) } @@ -203,9 +233,15 @@ impl ::connectrpc::Dispatcher for BloatEchoServiceServer "Echo" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::bench::v1::__buffa::view::BloatEchoView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::bench::v1::BloatEcho, >(request.encoded()?, format)?; + let req: crate::proto::bench::v1::__buffa::view::BloatEchoView<'_> = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::bench::v1::BloatEcho, + >::from_parts(&req, &body); svc.echo(ctx, req) .await? .encode::(format) @@ -296,11 +332,12 @@ impl ::connectrpc::Dispatcher for BloatEchoServiceServer /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.echo(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.echo(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -309,6 +346,12 @@ impl ::connectrpc::Dispatcher for BloatEchoServiceServer /// ```rust,ignore /// let owned = client.echo(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct BloatEchoServiceClient { transport: T, diff --git a/benches/rpc/src/generated/connect/filter.__connect.rs b/benches/rpc/src/generated/connect/filter.__connect.rs index 4d0a0b9..4f1d972 100644 --- a/benches/rpc/src/generated/connect/filter.__connect.rs +++ b/benches/rpc/src/generated/connect/filter.__connect.rs @@ -19,7 +19,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -39,19 +39,31 @@ pub const FILTER_SERVICE_REDACT_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::s /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -64,10 +76,11 @@ pub const FILTER_SERVICE_REDACT_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::s /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -75,10 +88,19 @@ pub trait FilterService: Send + Sync + 'static { /// Handle the Redact RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn redact<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedRecordView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::anthropic::connectrpc::filter::v1::Record, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -120,10 +142,21 @@ impl FilterServiceExt for S { "Redact", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::anthropic::connectrpc::filter::v1::__buffa::view::RecordView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.redact(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::filter::v1::Record, + >::from_parts(req.reborrow(), req.bytes()); + svc.redact(ctx, sreq) .await? .encode::< crate::proto::anthropic::connectrpc::filter::v1::Record, @@ -203,9 +236,17 @@ impl ::connectrpc::Dispatcher for FilterServiceServer { "Redact" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::anthropic::connectrpc::filter::v1::__buffa::view::RecordView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::anthropic::connectrpc::filter::v1::Record, >(request.encoded()?, format)?; + let req: crate::proto::anthropic::connectrpc::filter::v1::__buffa::view::RecordView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::filter::v1::Record, + >::from_parts(&req, &body); svc.redact(ctx, req) .await? .encode::< @@ -301,11 +342,12 @@ impl ::connectrpc::Dispatcher for FilterServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.redact(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.redact(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -314,6 +356,12 @@ impl ::connectrpc::Dispatcher for FilterServiceServer { /// ```rust,ignore /// let owned = client.redact(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct FilterServiceClient { transport: T, diff --git a/benches/rpc/src/generated/connect/fortune.__connect.rs b/benches/rpc/src/generated/connect/fortune.__connect.rs index cc7f20a..d756a53 100644 --- a/benches/rpc/src/generated/connect/fortune.__connect.rs +++ b/benches/rpc/src/generated/connect/fortune.__connect.rs @@ -23,7 +23,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -41,19 +41,31 @@ pub const FORTUNE_SERVICE_GET_FORTUNES_SPEC: ::connectrpc::Spec = ::connectrpc:: /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -66,10 +78,11 @@ pub const FORTUNE_SERVICE_GET_FORTUNES_SPEC: ::connectrpc::Spec = ::connectrpc:: /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -77,10 +90,19 @@ pub trait FortuneService: Send + Sync + 'static { /// Handle the GetFortunes RPC. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn get_fortunes<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedGetFortunesRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::fortune::v1::GetFortunesRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -122,10 +144,21 @@ impl FortuneServiceExt for S { "GetFortunes", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::fortune::v1::__buffa::view::GetFortunesRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.get_fortunes(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::fortune::v1::GetFortunesRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.get_fortunes(ctx, sreq) .await? .encode::< crate::proto::fortune::v1::GetFortunesResponse, @@ -204,9 +237,17 @@ impl ::connectrpc::Dispatcher for FortuneServiceServer { "GetFortunes" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::fortune::v1::__buffa::view::GetFortunesRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::fortune::v1::GetFortunesRequest, >(request.encoded()?, format)?; + let req: crate::proto::fortune::v1::__buffa::view::GetFortunesRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::fortune::v1::GetFortunesRequest, + >::from_parts(&req, &body); svc.get_fortunes(ctx, req) .await? .encode::(format) @@ -297,11 +338,12 @@ impl ::connectrpc::Dispatcher for FortuneServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.get_fortunes(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.get_fortunes(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -310,6 +352,12 @@ impl ::connectrpc::Dispatcher for FortuneServiceServer { /// ```rust,ignore /// let owned = client.get_fortunes(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct FortuneServiceClient { transport: T, diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.__view.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.__view.rs index 7e42cb0..cb125b8 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.__view.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.__view.rs @@ -983,6 +983,311 @@ impl ::buffa::ViewReborrow for ClientCompatRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `ClientCompatRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`ClientCompatRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ClientCompatRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ClientCompatRequestOwnedView( + ::buffa::OwnedView>, +); +impl ClientCompatRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientCompatRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientCompatRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ClientCompatRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientCompatRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ClientCompatRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ClientCompatRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ClientCompatRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The name of the test that this request is performing. + /// When writing test cases, this is a required field. + /// + /// Field 1: `test_name` + #[must_use] + pub fn test_name(&self) -> &'_ str { + self.0.reborrow().test_name + } + /// Test suite YAML definitions should NOT set values for these next + /// nine fields (fields 2 - 10). They are automatically populated by the test + /// runner. If a test is specific to one of these values, it should instead be + /// indicated in the test suite itself (where it defines the required + /// features and relevant values for these fields). + /// + /// The HTTP version to use for the test (i.e. HTTP/1.1, HTTP/2, HTTP/3). + /// + /// Field 2: `http_version` + #[must_use] + pub fn http_version(&self) -> ::buffa::EnumValue { + self.0.reborrow().http_version + } + /// The protocol to use for the test (i.e. Connect, gRPC, gRPC-web). + /// + /// Field 3: `protocol` + #[must_use] + pub fn protocol(&self) -> ::buffa::EnumValue { + self.0.reborrow().protocol + } + /// The codec to use for the test (i.e. JSON, proto/binary). + /// + /// Field 4: `codec` + #[must_use] + pub fn codec(&self) -> ::buffa::EnumValue { + self.0.reborrow().codec + } + /// The compression to use for the test (i.e. brotli, gzip, identity). + /// + /// Field 5: `compression` + #[must_use] + pub fn compression(&self) -> ::buffa::EnumValue { + self.0.reborrow().compression + } + /// The server host that this request will be sent to. + /// + /// Field 6: `host` + #[must_use] + pub fn host(&self) -> &'_ str { + self.0.reborrow().host + } + /// The server port that this request will be sent to. + /// + /// Field 7: `port` + #[must_use] + pub fn port(&self) -> u32 { + self.0.reborrow().port + } + /// If non-empty, the server is using TLS. The bytes are the + /// server's PEM-encoded certificate, which the client should + /// verify and trust. + /// + /// Field 8: `server_tls_cert` + #[must_use] + pub fn server_tls_cert(&self) -> &'_ [u8] { + self.0.reborrow().server_tls_cert + } + /// If present, the client certificate credentials to use to + /// authenticate with the server. This will only be present + /// when server_tls_cert is non-empty. + /// + /// Field 9: `client_tls_creds` + #[must_use] + pub fn client_tls_creds( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().client_tls_creds + } + /// If non-zero, indicates the maximum size in bytes for a message. + /// If the server sends anything larger, the client should reject it. + /// + /// Field 10: `message_receive_limit` + #[must_use] + pub fn message_receive_limit(&self) -> u32 { + self.0.reborrow().message_receive_limit + } + /// The fully-qualified name of the service this test will interact with. + /// If specified, method must also be specified. + /// If not specified, defaults to "connectrpc.conformance.v1.ConformanceService". + /// + /// Field 11: `service` + #[must_use] + pub fn service(&self) -> ::core::option::Option<&'_ str> { + self.0.reborrow().service + } + /// The method on `service` that will be called. + /// If specified, service must also be specified. + /// If not specified, the test runner will auto-populate this field based on the stream_type. + /// + /// Field 12: `method` + #[must_use] + pub fn method(&self) -> ::core::option::Option<&'_ str> { + self.0.reborrow().method + } + /// The stream type of `method` (i.e. unary, client stream, server stream, full-duplex bidi + /// stream, or half-duplex bidi stream). + /// When writing test cases, this is a required field. + /// + /// Field 13: `stream_type` + #[must_use] + pub fn stream_type(&self) -> ::buffa::EnumValue { + self.0.reborrow().stream_type + } + /// If protocol indicates Connect and stream type indicates + /// Unary, this instructs the client to use a GET HTTP method + /// when making the request. + /// + /// Field 14: `use_get_http_method` + #[must_use] + pub fn use_get_http_method(&self) -> bool { + self.0.reborrow().use_get_http_method + } + /// Any request headers that should be sent as part of the request. + /// These include only custom header metadata. Headers that are + /// part of the relevant protocol (such as "content-type", etc) should + /// not be stated here. + /// + /// Field 15: `request_headers` + #[must_use] + pub fn request_headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().request_headers + } + /// The actual request messages that will sent to the server. + /// The type URL for all entries should be equal to the request type of the + /// method. + /// There must be exactly one for unary and server stream methods but + /// can be zero or more for client and bidi stream methods. + /// For client and bidi stream methods, all entries will have the + /// same type URL. + /// + /// Field 16: `request_messages` + #[must_use] + pub fn request_messages( + &self, + ) -> &::buffa::RepeatedView< + '_, + ::buffa_types::google::protobuf::__buffa::view::AnyView<'_>, + > { + &self.0.reborrow().request_messages + } + /// The timeout, in milliseconds, for the request. This is equivalent to a + /// deadline for the request. If unset, there will be no timeout. + /// + /// Field 17: `timeout_ms` + #[must_use] + pub fn timeout_ms(&self) -> ::core::option::Option { + self.0.reborrow().timeout_ms + } + /// Wait this many milliseconds before sending a request message. + /// For client or bidi stream methods, this delay should be + /// applied before each request sent. + /// + /// Field 18: `request_delay_ms` + #[must_use] + pub fn request_delay_ms(&self) -> u32 { + self.0.reborrow().request_delay_ms + } + /// If present, the client should cancel the RPC instead of + /// allowing to complete normally. + /// + /// Field 19: `cancel` + #[must_use] + pub fn cancel( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::client_compat_request::CancelView<'_>, + > { + &self.0.reborrow().cancel + } + /// The following field is only used by the reference client. If + /// you are implementing a client under test, you may ignore it + /// or respond with an error if the client receives a request where + /// it is set. + /// + /// When this field is present, it defines the actual HTTP request + /// that will be sent. The above group of fields must still be + /// provided and valid so that the reference client knows how it + /// should try to interpret the server's response. + /// + /// Field 20: `raw_request` + #[must_use] + pub fn raw_request( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::RawHTTPRequestView<'_>, + > { + &self.0.reborrow().raw_request + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ClientCompatRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ClientCompatRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ClientCompatRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ClientCompatRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ClientCompatRequest { + type View<'a> = ClientCompatRequestView<'a>; + type ViewHandle = ClientCompatRequestOwnedView; +} +impl ::serde::Serialize for ClientCompatRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} pub mod client_compat_request { #[allow(unused_imports)] use super::*; @@ -1333,6 +1638,122 @@ pub mod client_compat_request { this } } + /** Self-contained, `'static` owned view of a `Cancel` message. + + Wraps [`::buffa::OwnedView`]`<`[`CancelView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`CancelView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ + #[derive(Clone, Debug)] + pub struct CancelOwnedView(::buffa::OwnedView>); + impl CancelOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CancelOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CancelOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::super::client_compat_request::Cancel, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CancelOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`CancelView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &CancelView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message( + &self, + ) -> super::super::super::client_compat_request::Cancel { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Oneof `cancel_timing`. + #[must_use] + pub fn cancel_timing( + &self, + ) -> ::core::option::Option< + &super::super::super::__buffa::view::oneof::client_compat_request::cancel::CancelTiming< + '_, + >, + > { + self.0.reborrow().cancel_timing.as_ref() + } + } + impl ::core::convert::From<::buffa::OwnedView>> + for CancelOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + CancelOwnedView(inner) + } + } + impl ::core::convert::From + for ::buffa::OwnedView> { + fn from(wrapper: CancelOwnedView) -> Self { + wrapper.0 + } + } + impl ::core::convert::AsRef<::buffa::OwnedView>> + for CancelOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } + } + impl ::buffa::HasMessageView for super::super::super::client_compat_request::Cancel { + type View<'a> = CancelView<'a>; + type ViewHandle = CancelOwnedView; + } + impl ::serde::Serialize for CancelOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } + } } /// The outcome of one ClientCompatRequest. #[derive(Clone, Debug, Default)] @@ -1667,6 +2088,129 @@ impl ::buffa::ViewReborrow for ClientCompatResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ClientCompatResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`ClientCompatResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ClientCompatResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ClientCompatResponseOwnedView( + ::buffa::OwnedView>, +); +impl ClientCompatResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientCompatResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientCompatResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ClientCompatResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientCompatResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ClientCompatResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ClientCompatResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ClientCompatResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The test name that this response applies to. + /// + /// Field 1: `test_name` + #[must_use] + pub fn test_name(&self) -> &'_ str { + self.0.reborrow().test_name + } + /// Oneof `result`. + #[must_use] + pub fn result( + &self, + ) -> ::core::option::Option< + &super::super::__buffa::view::oneof::client_compat_response::Result<'_>, + > { + self.0.reborrow().result.as_ref() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ClientCompatResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ClientCompatResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ClientCompatResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ClientCompatResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ClientCompatResponse { + type View<'a> = ClientCompatResponseView<'a>; + type ViewHandle = ClientCompatResponseOwnedView; +} +impl ::serde::Serialize for ClientCompatResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// The result of a ClientCompatRequest, which may or may not be successful. /// The client will build this message and return it back to the test runner. #[derive(Clone, Debug, Default)] @@ -2149,6 +2693,187 @@ impl ::buffa::ViewReborrow for ClientResponseResultView<'static> { this } } +/** Self-contained, `'static` owned view of a `ClientResponseResult` message. + + Wraps [`::buffa::OwnedView`]`<`[`ClientResponseResultView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ClientResponseResultView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ClientResponseResultOwnedView( + ::buffa::OwnedView>, +); +impl ClientResponseResultOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientResponseResultOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientResponseResultOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ClientResponseResult, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientResponseResultOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ClientResponseResultView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ClientResponseResultView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ClientResponseResult { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// All response headers read from the response. + /// + /// Field 1: `response_headers` + #[must_use] + pub fn response_headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().response_headers + } + /// Servers should echo back payloads that they received as part of the request. + /// This field should contain all the payloads the server echoed back. Note that + /// There will be zero-to-one for unary and client stream methods and + /// zero-to-many for server and bidi stream methods. + /// + /// Field 2: `payloads` + #[must_use] + pub fn payloads( + &self, + ) -> &::buffa::RepeatedView< + '_, + super::super::__buffa::view::ConformancePayloadView<'_>, + > { + &self.0.reborrow().payloads + } + /// The error received from the actual RPC invocation. Note this is not representative + /// of a runtime error and should always be the proto equivalent of a Connect + /// or gRPC error. + /// + /// Field 3: `error` + #[must_use] + pub fn error( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().error + } + /// All response headers read from the response. + /// + /// Field 4: `response_trailers` + #[must_use] + pub fn response_trailers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().response_trailers + } + /// The number of messages that were present in the request but that could not be + /// sent because an error occurred before finishing the upload. + /// + /// Field 5: `num_unsent_requests` + #[must_use] + pub fn num_unsent_requests(&self) -> i32 { + self.0.reborrow().num_unsent_requests + } + /// The following field is only set by the reference client. It communicates + /// the underlying HTTP status code of the server's response. + /// If you are implementing a client-under-test, you should ignore this field + /// and leave it unset. + /// + /// Field 6: `http_status_code` + #[must_use] + pub fn http_status_code(&self) -> ::core::option::Option { + self.0.reborrow().http_status_code + } + /// This field is used only by the reference client, and it can be used + /// to provide additional feedback about problems observed in the server + /// response or in client processing of the response. If non-empty, the test + /// case is considered failed even if the result above matches all expectations. + /// If you are implementing a client-under-test, you should ignore this field + /// and leave it unset. + /// + /// Field 7: `feedback` + #[must_use] + pub fn feedback(&self) -> &::buffa::RepeatedView<'_, &'_ str> { + &self.0.reborrow().feedback + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ClientResponseResultOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ClientResponseResultOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ClientResponseResultOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ClientResponseResultOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ClientResponseResult { + type View<'a> = ClientResponseResultView<'a>; + type ViewHandle = ClientResponseResultOwnedView; +} +impl ::serde::Serialize for ClientResponseResultOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// The client is not able to fulfill the ClientCompatRequest. This may be due /// to a runtime error or an unexpected internal error such as the requested protocol /// not being supported. This is completely independent of the actual RPC invocation. @@ -2332,6 +3057,122 @@ impl ::buffa::ViewReborrow for ClientErrorResultView<'static> { this } } +/** Self-contained, `'static` owned view of a `ClientErrorResult` message. + + Wraps [`::buffa::OwnedView`]`<`[`ClientErrorResultView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ClientErrorResultView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ClientErrorResultOwnedView( + ::buffa::OwnedView>, +); +impl ClientErrorResultOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientErrorResultOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientErrorResultOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ClientErrorResult, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientErrorResultOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ClientErrorResultView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ClientErrorResultView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ClientErrorResult { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// A message describing the error that occurred. This string will be shown to + /// users running conformance tests so it should include any relevant details + /// that may help troubleshoot or remedy the error. + /// + /// Field 1: `message` + #[must_use] + pub fn message(&self) -> &'_ str { + self.0.reborrow().message + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ClientErrorResultOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ClientErrorResultOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ClientErrorResultOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ClientErrorResultOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ClientErrorResult { + type View<'a> = ClientErrorResultView<'a>; + type ViewHandle = ClientErrorResultOwnedView; +} +impl ::serde::Serialize for ClientErrorResultOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Details about various values as observed on the wire. This message is used /// only by the reference client when reporting results and should not be populated /// by clients under test. @@ -2674,3 +3515,149 @@ impl ::buffa::ViewReborrow for WireDetailsView<'static> { this } } +/** Self-contained, `'static` owned view of a `WireDetails` message. + + Wraps [`::buffa::OwnedView`]`<`[`WireDetailsView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`WireDetailsView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct WireDetailsOwnedView(::buffa::OwnedView>); +impl WireDetailsOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + WireDetailsOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + WireDetailsOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::WireDetails, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + WireDetailsOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`WireDetailsView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &WireDetailsView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::WireDetails { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The HTTP status code of the response. + /// + /// Field 1: `actual_status_code` + #[must_use] + pub fn actual_status_code(&self) -> i32 { + self.0.reborrow().actual_status_code + } + /// When processing an error from a Connect server, this should contain + /// the actual JSON received on the wire. + /// + /// Field 2: `connect_error_raw` + #[must_use] + pub fn connect_error_raw( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::StructView<'_>, + > { + &self.0.reborrow().connect_error_raw + } + /// Any HTTP trailers observed after the response body. These do NOT + /// include trailers that conveyed via the body, as done in the gRPC-Web + /// and Connect streaming protocols. + /// + /// Field 3: `actual_http_trailers` + #[must_use] + pub fn actual_http_trailers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().actual_http_trailers + } + /// Any trailers that were transmitted in the final message of the + /// response body for a gRPC-Web response. This could differ from the + /// ClientResponseResult.response_trailers field since the RPC client + /// library might canonicalize keys and it might choose to remove + /// "grpc-status" et al from the set of metadata. This field will + /// capture all of the entries and their exact on-the-wire spelling + /// and formatting. + /// + /// Field 4: `actual_grpcweb_trailers` + #[must_use] + pub fn actual_grpcweb_trailers(&self) -> ::core::option::Option<&'_ str> { + self.0.reborrow().actual_grpcweb_trailers + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for WireDetailsOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + WireDetailsOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: WireDetailsOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for WireDetailsOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::WireDetails { + type View<'a> = WireDetailsView<'a>; + type ViewHandle = WireDetailsOwnedView; +} +impl ::serde::Serialize for WireDetailsOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.rs index e589a1a..4e3e707 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.client_compat.rs @@ -1261,6 +1261,8 @@ pub mod client_compat_request { } #[doc(inline)] pub use super::__buffa::view::client_compat_request::CancelView; + #[doc(inline)] + pub use super::__buffa::view::client_compat_request::CancelOwnedView; } /// The outcome of one ClientCompatRequest. #[derive(Clone, PartialEq, Default)] diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.config.__view.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.config.__view.rs index ed766c6..558038e 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.config.__view.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.config.__view.rs @@ -321,6 +321,135 @@ impl ::buffa::ViewReborrow for ConfigView<'static> { this } } +/** Self-contained, `'static` owned view of a `Config` message. + + Wraps [`::buffa::OwnedView`]`<`[`ConfigView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ConfigView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ConfigOwnedView(::buffa::OwnedView>); +impl ConfigOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(ConfigOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConfigOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Config, + ) -> ::core::result::Result { + ::core::result::Result::Ok(ConfigOwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`ConfigView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ConfigView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Config { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The features supported by the client or server under test. + /// This is used to filter the set of test cases that are run. + /// If absent, an empty message is used. See Features for more + /// on how empty/absent fields are interpreted. + /// + /// Field 1: `features` + #[must_use] + pub fn features( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().features + } + /// This can indicate additional permutations that are supported + /// that might otherwise be excluded based on the above features. + /// + /// Field 2: `include_cases` + #[must_use] + pub fn include_cases( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::ConfigCaseView<'_>> { + &self.0.reborrow().include_cases + } + /// This can indicates permutations that are not supported even + /// though their support might be implied by the above features. + /// + /// Field 3: `exclude_cases` + #[must_use] + pub fn exclude_cases( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::ConfigCaseView<'_>> { + &self.0.reborrow().exclude_cases + } +} +impl ::core::convert::From<::buffa::OwnedView>> for ConfigOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ConfigOwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: ConfigOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ConfigOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Config { + type View<'a> = ConfigView<'a>; + type ViewHandle = ConfigOwnedView; +} +impl ::serde::Serialize for ConfigOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Features define the feature set that a client or server supports. They are /// used to determine the server configurations and test cases that /// will be run. They are defined in YAML files and are specified as part of the @@ -1044,6 +1173,217 @@ impl ::buffa::ViewReborrow for FeaturesView<'static> { this } } +/** Self-contained, `'static` owned view of a `Features` message. + + Wraps [`::buffa::OwnedView`]`<`[`FeaturesView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`FeaturesView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct FeaturesOwnedView(::buffa::OwnedView>); +impl FeaturesOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(FeaturesOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FeaturesOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Features, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + FeaturesOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`FeaturesView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &FeaturesView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Features { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Supported HTTP versions. + /// If empty, HTTP 1.1 and HTTP/2 are assumed. + /// + /// Field 1: `versions` + #[must_use] + pub fn versions( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().versions + } + /// Supported protocols. + /// If empty, all three are assumed: Connect, gRPC, and gRPC-Web. + /// + /// Field 2: `protocols` + #[must_use] + pub fn protocols( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().protocols + } + /// Supported codecs. + /// If empty, "proto" and "json" are assumed. + /// + /// Field 3: `codecs` + #[must_use] + pub fn codecs( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().codecs + } + /// Supported compression algorithms. + /// If empty, "identity" and "gzip" are assumed. + /// + /// Field 4: `compressions` + #[must_use] + pub fn compressions( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().compressions + } + /// Supported stream types. + /// If empty, all stream types are assumed. This is usually for + /// clients, since some client environments may not be able to + /// support certain kinds of streaming operations, especially + /// bidirectional streams. + /// + /// Field 5: `stream_types` + #[must_use] + pub fn stream_types( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().stream_types + } + /// Whether H2C (unencrypted, non-TLS HTTP/2 over cleartext) is supported. + /// If absent, true is assumed. + /// + /// Field 6: `supports_h2c` + #[must_use] + pub fn supports_h2c(&self) -> ::core::option::Option { + self.0.reborrow().supports_h2c + } + /// Whether TLS is supported. + /// If absent, true is assumed. + /// + /// Field 7: `supports_tls` + #[must_use] + pub fn supports_tls(&self) -> ::core::option::Option { + self.0.reborrow().supports_tls + } + /// Whether the client supports TLS certificates. + /// If absent, false is assumed. This should not be set if + /// supports_tls is false. + /// + /// Field 8: `supports_tls_client_certs` + #[must_use] + pub fn supports_tls_client_certs(&self) -> ::core::option::Option { + self.0.reborrow().supports_tls_client_certs + } + /// Whether trailers are supported. + /// If absent, true is assumed. If false, implies that gRPC protocol is not allowed. + /// + /// Field 9: `supports_trailers` + #[must_use] + pub fn supports_trailers(&self) -> ::core::option::Option { + self.0.reborrow().supports_trailers + } + /// Whether half duplex bidi streams are supported over HTTP/1.1. + /// If absent, false is assumed. + /// + /// Field 10: `supports_half_duplex_bidi_over_http1` + #[must_use] + pub fn supports_half_duplex_bidi_over_http1(&self) -> ::core::option::Option { + self.0.reborrow().supports_half_duplex_bidi_over_http1 + } + /// Whether Connect via GET is supported. + /// If absent, true is assumed. + /// + /// Field 11: `supports_connect_get` + #[must_use] + pub fn supports_connect_get(&self) -> ::core::option::Option { + self.0.reborrow().supports_connect_get + } + /// Whether a message receive limit is supported. + /// If absent, true is assumed. + /// + /// Field 12: `supports_message_receive_limit` + #[must_use] + pub fn supports_message_receive_limit(&self) -> ::core::option::Option { + self.0.reborrow().supports_message_receive_limit + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for FeaturesOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + FeaturesOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: FeaturesOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for FeaturesOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Features { + type View<'a> = FeaturesView<'a>; + type ViewHandle = FeaturesOwnedView; +} +impl ::serde::Serialize for FeaturesOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// ConfigCase represents a single resolved configuration case. When tests are /// run, the Config and the supported features therein are used to compute all /// of the cases relevant to the implementation under test. These configuration @@ -1458,6 +1798,169 @@ impl ::buffa::ViewReborrow for ConfigCaseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ConfigCase` message. + + Wraps [`::buffa::OwnedView`]`<`[`ConfigCaseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ConfigCaseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ConfigCaseOwnedView(::buffa::OwnedView>); +impl ConfigCaseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConfigCaseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConfigCaseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ConfigCase, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConfigCaseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ConfigCaseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ConfigCaseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ConfigCase { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// If unspecified, indicates cases for all versions. + /// + /// Field 1: `version` + #[must_use] + pub fn version(&self) -> ::buffa::EnumValue { + self.0.reborrow().version + } + /// If unspecified, indicates cases for all protocols. + /// + /// Field 2: `protocol` + #[must_use] + pub fn protocol(&self) -> ::buffa::EnumValue { + self.0.reborrow().protocol + } + /// If unspecified, indicates cases for all codecs. + /// + /// Field 3: `codec` + #[must_use] + pub fn codec(&self) -> ::buffa::EnumValue { + self.0.reborrow().codec + } + /// If unspecified, indicates cases for all compression algorithms. + /// + /// Field 4: `compression` + #[must_use] + pub fn compression(&self) -> ::buffa::EnumValue { + self.0.reborrow().compression + } + /// If unspecified, indicates cases for all stream types. + /// + /// Field 5: `stream_type` + #[must_use] + pub fn stream_type(&self) -> ::buffa::EnumValue { + self.0.reborrow().stream_type + } + /// If absent, indicates cases for plaintext (no TLS) but also for + /// TLS if features indicate that TLS is supported. + /// + /// Field 6: `use_tls` + #[must_use] + pub fn use_tls(&self) -> ::core::option::Option { + self.0.reborrow().use_tls + } + /// If absent, indicates cases without client certs but also cases + /// that use client certs if features indicate they are supported. + /// + /// Field 7: `use_tls_client_certs` + #[must_use] + pub fn use_tls_client_certs(&self) -> ::core::option::Option { + self.0.reborrow().use_tls_client_certs + } + /// If absent, indicates cases that do not test message receive + /// limits but also cases that do test message receive limits if + /// features indicate they are supported. + /// + /// Field 8: `use_message_receive_limit` + #[must_use] + pub fn use_message_receive_limit(&self) -> ::core::option::Option { + self.0.reborrow().use_message_receive_limit + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ConfigCaseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ConfigCaseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ConfigCaseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ConfigCaseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ConfigCase { + type View<'a> = ConfigCaseView<'a>; + type ViewHandle = ConfigCaseOwnedView; +} +impl ::serde::Serialize for ConfigCaseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// TLSCreds represents credentials for TLS. It includes both a /// certificate and corresponding private key. Both are encoded /// in PEM format. @@ -1682,3 +2185,114 @@ impl ::buffa::ViewReborrow for TLSCredsView<'static> { this } } +/** Self-contained, `'static` owned view of a `TLSCreds` message. + + Wraps [`::buffa::OwnedView`]`<`[`TLSCredsView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`TLSCredsView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct TLSCredsOwnedView(::buffa::OwnedView>); +impl TLSCredsOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(TLSCredsOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TLSCredsOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::TLSCreds, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TLSCredsOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`TLSCredsView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &TLSCredsView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::TLSCreds { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `cert` + #[must_use] + pub fn cert(&self) -> &'_ [u8] { + self.0.reborrow().cert + } + /// Field 2: `key` + #[must_use] + pub fn key(&self) -> &'_ [u8] { + self.0.reborrow().key + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for TLSCredsOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + TLSCredsOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: TLSCredsOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for TLSCredsOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::TLSCreds { + type View<'a> = TLSCredsView<'a>; + type ViewHandle = TLSCredsOwnedView; +} +impl ::serde::Serialize for TLSCredsOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.config.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.config.rs index 112dc27..d41c29a 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.config.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.config.rs @@ -9,6 +9,20 @@ pub enum HTTPVersion { HTTP_VERSION_2 = 2i32, HTTP_VERSION_3 = 3i32, } +impl HTTPVersion { + ///Idiomatic alias for [`Self::HTTP_VERSION_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const HttpVersionUnspecified: Self = Self::HTTP_VERSION_UNSPECIFIED; + ///Idiomatic alias for [`Self::HTTP_VERSION_1`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const HttpVersion1: Self = Self::HTTP_VERSION_1; + ///Idiomatic alias for [`Self::HTTP_VERSION_2`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const HttpVersion2: Self = Self::HTTP_VERSION_2; + ///Idiomatic alias for [`Self::HTTP_VERSION_3`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const HttpVersion3: Self = Self::HTTP_VERSION_3; +} impl ::core::default::Default for HTTPVersion { fn default() -> Self { Self::HTTP_VERSION_UNSPECIFIED @@ -152,6 +166,20 @@ pub enum Protocol { /// PROTOCOL_REST_TRANSCODING = 5; PROTOCOL_GRPC_WEB = 3i32, } +impl Protocol { + ///Idiomatic alias for [`Self::PROTOCOL_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::PROTOCOL_UNSPECIFIED; + ///Idiomatic alias for [`Self::PROTOCOL_CONNECT`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Connect: Self = Self::PROTOCOL_CONNECT; + ///Idiomatic alias for [`Self::PROTOCOL_GRPC`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Grpc: Self = Self::PROTOCOL_GRPC; + ///Idiomatic alias for [`Self::PROTOCOL_GRPC_WEB`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const GrpcWeb: Self = Self::PROTOCOL_GRPC_WEB; +} impl ::core::default::Default for Protocol { fn default() -> Self { Self::PROTOCOL_UNSPECIFIED @@ -293,6 +321,20 @@ pub enum Codec { /// not used; will be ignored CODEC_TEXT = 3i32, } +impl Codec { + ///Idiomatic alias for [`Self::CODEC_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::CODEC_UNSPECIFIED; + ///Idiomatic alias for [`Self::CODEC_PROTO`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Proto: Self = Self::CODEC_PROTO; + ///Idiomatic alias for [`Self::CODEC_JSON`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Json: Self = Self::CODEC_JSON; + ///Idiomatic alias for [`Self::CODEC_TEXT`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Text: Self = Self::CODEC_TEXT; +} impl ::core::default::Default for Codec { fn default() -> Self { Self::CODEC_UNSPECIFIED @@ -429,6 +471,29 @@ pub enum Compression { COMPRESSION_DEFLATE = 5i32, COMPRESSION_SNAPPY = 6i32, } +impl Compression { + ///Idiomatic alias for [`Self::COMPRESSION_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::COMPRESSION_UNSPECIFIED; + ///Idiomatic alias for [`Self::COMPRESSION_IDENTITY`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Identity: Self = Self::COMPRESSION_IDENTITY; + ///Idiomatic alias for [`Self::COMPRESSION_GZIP`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Gzip: Self = Self::COMPRESSION_GZIP; + ///Idiomatic alias for [`Self::COMPRESSION_BR`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Br: Self = Self::COMPRESSION_BR; + ///Idiomatic alias for [`Self::COMPRESSION_ZSTD`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Zstd: Self = Self::COMPRESSION_ZSTD; + ///Idiomatic alias for [`Self::COMPRESSION_DEFLATE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Deflate: Self = Self::COMPRESSION_DEFLATE; + ///Idiomatic alias for [`Self::COMPRESSION_SNAPPY`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Snappy: Self = Self::COMPRESSION_SNAPPY; +} impl ::core::default::Default for Compression { fn default() -> Self { Self::COMPRESSION_UNSPECIFIED @@ -589,6 +654,26 @@ pub enum StreamType { STREAM_TYPE_HALF_DUPLEX_BIDI_STREAM = 4i32, STREAM_TYPE_FULL_DUPLEX_BIDI_STREAM = 5i32, } +impl StreamType { + ///Idiomatic alias for [`Self::STREAM_TYPE_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::STREAM_TYPE_UNSPECIFIED; + ///Idiomatic alias for [`Self::STREAM_TYPE_UNARY`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unary: Self = Self::STREAM_TYPE_UNARY; + ///Idiomatic alias for [`Self::STREAM_TYPE_CLIENT_STREAM`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const ClientStream: Self = Self::STREAM_TYPE_CLIENT_STREAM; + ///Idiomatic alias for [`Self::STREAM_TYPE_SERVER_STREAM`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const ServerStream: Self = Self::STREAM_TYPE_SERVER_STREAM; + ///Idiomatic alias for [`Self::STREAM_TYPE_HALF_DUPLEX_BIDI_STREAM`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const HalfDuplexBidiStream: Self = Self::STREAM_TYPE_HALF_DUPLEX_BIDI_STREAM; + ///Idiomatic alias for [`Self::STREAM_TYPE_FULL_DUPLEX_BIDI_STREAM`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const FullDuplexBidiStream: Self = Self::STREAM_TYPE_FULL_DUPLEX_BIDI_STREAM; +} impl ::core::default::Default for StreamType { fn default() -> Self { Self::STREAM_TYPE_UNSPECIFIED @@ -766,6 +851,59 @@ pub enum Code { CODE_DATA_LOSS = 15i32, CODE_UNAUTHENTICATED = 16i32, } +impl Code { + ///Idiomatic alias for [`Self::CODE_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::CODE_UNSPECIFIED; + ///Idiomatic alias for [`Self::CODE_CANCELED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Canceled: Self = Self::CODE_CANCELED; + ///Idiomatic alias for [`Self::CODE_UNKNOWN`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unknown: Self = Self::CODE_UNKNOWN; + ///Idiomatic alias for [`Self::CODE_INVALID_ARGUMENT`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const InvalidArgument: Self = Self::CODE_INVALID_ARGUMENT; + ///Idiomatic alias for [`Self::CODE_DEADLINE_EXCEEDED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const DeadlineExceeded: Self = Self::CODE_DEADLINE_EXCEEDED; + ///Idiomatic alias for [`Self::CODE_NOT_FOUND`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const NotFound: Self = Self::CODE_NOT_FOUND; + ///Idiomatic alias for [`Self::CODE_ALREADY_EXISTS`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const AlreadyExists: Self = Self::CODE_ALREADY_EXISTS; + ///Idiomatic alias for [`Self::CODE_PERMISSION_DENIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const PermissionDenied: Self = Self::CODE_PERMISSION_DENIED; + ///Idiomatic alias for [`Self::CODE_RESOURCE_EXHAUSTED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const ResourceExhausted: Self = Self::CODE_RESOURCE_EXHAUSTED; + ///Idiomatic alias for [`Self::CODE_FAILED_PRECONDITION`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const FailedPrecondition: Self = Self::CODE_FAILED_PRECONDITION; + ///Idiomatic alias for [`Self::CODE_ABORTED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Aborted: Self = Self::CODE_ABORTED; + ///Idiomatic alias for [`Self::CODE_OUT_OF_RANGE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const OutOfRange: Self = Self::CODE_OUT_OF_RANGE; + ///Idiomatic alias for [`Self::CODE_UNIMPLEMENTED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unimplemented: Self = Self::CODE_UNIMPLEMENTED; + ///Idiomatic alias for [`Self::CODE_INTERNAL`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Internal: Self = Self::CODE_INTERNAL; + ///Idiomatic alias for [`Self::CODE_UNAVAILABLE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unavailable: Self = Self::CODE_UNAVAILABLE; + ///Idiomatic alias for [`Self::CODE_DATA_LOSS`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const DataLoss: Self = Self::CODE_DATA_LOSS; + ///Idiomatic alias for [`Self::CODE_UNAUTHENTICATED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unauthenticated: Self = Self::CODE_UNAUTHENTICATED; +} impl ::core::default::Default for Code { fn default() -> Self { Self::CODE_UNSPECIFIED diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.mod.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.mod.rs index 5f648d0..5e6bc91 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.mod.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.mod.rs @@ -87,70 +87,138 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::ConfigView; #[doc(inline)] +pub use self::__buffa::view::ConfigOwnedView; +#[doc(inline)] pub use self::__buffa::view::FeaturesView; #[doc(inline)] +pub use self::__buffa::view::FeaturesOwnedView; +#[doc(inline)] pub use self::__buffa::view::ConfigCaseView; #[doc(inline)] +pub use self::__buffa::view::ConfigCaseOwnedView; +#[doc(inline)] pub use self::__buffa::view::TLSCredsView; #[doc(inline)] +pub use self::__buffa::view::TLSCredsOwnedView; +#[doc(inline)] pub use self::__buffa::view::UnaryResponseDefinitionView; #[doc(inline)] +pub use self::__buffa::view::UnaryResponseDefinitionOwnedView; +#[doc(inline)] pub use self::__buffa::view::StreamResponseDefinitionView; #[doc(inline)] +pub use self::__buffa::view::StreamResponseDefinitionOwnedView; +#[doc(inline)] pub use self::__buffa::view::UnaryRequestView; #[doc(inline)] +pub use self::__buffa::view::UnaryRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::UnaryResponseView; #[doc(inline)] +pub use self::__buffa::view::UnaryResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::IdempotentUnaryRequestView; #[doc(inline)] +pub use self::__buffa::view::IdempotentUnaryRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::IdempotentUnaryResponseView; #[doc(inline)] +pub use self::__buffa::view::IdempotentUnaryResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ServerStreamRequestView; #[doc(inline)] +pub use self::__buffa::view::ServerStreamRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::ServerStreamResponseView; #[doc(inline)] +pub use self::__buffa::view::ServerStreamResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ClientStreamRequestView; #[doc(inline)] +pub use self::__buffa::view::ClientStreamRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::ClientStreamResponseView; #[doc(inline)] +pub use self::__buffa::view::ClientStreamResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::BidiStreamRequestView; #[doc(inline)] +pub use self::__buffa::view::BidiStreamRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::BidiStreamResponseView; #[doc(inline)] +pub use self::__buffa::view::BidiStreamResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::UnimplementedRequestView; #[doc(inline)] +pub use self::__buffa::view::UnimplementedRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::UnimplementedResponseView; #[doc(inline)] +pub use self::__buffa::view::UnimplementedResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ConformancePayloadView; #[doc(inline)] +pub use self::__buffa::view::ConformancePayloadOwnedView; +#[doc(inline)] pub use self::__buffa::view::ErrorView; #[doc(inline)] +pub use self::__buffa::view::ErrorOwnedView; +#[doc(inline)] pub use self::__buffa::view::HeaderView; #[doc(inline)] +pub use self::__buffa::view::HeaderOwnedView; +#[doc(inline)] pub use self::__buffa::view::RawHTTPRequestView; #[doc(inline)] +pub use self::__buffa::view::RawHTTPRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::MessageContentsView; #[doc(inline)] +pub use self::__buffa::view::MessageContentsOwnedView; +#[doc(inline)] pub use self::__buffa::view::StreamContentsView; #[doc(inline)] +pub use self::__buffa::view::StreamContentsOwnedView; +#[doc(inline)] pub use self::__buffa::view::RawHTTPResponseView; #[doc(inline)] +pub use self::__buffa::view::RawHTTPResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ClientCompatRequestView; #[doc(inline)] +pub use self::__buffa::view::ClientCompatRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::ClientCompatResponseView; #[doc(inline)] +pub use self::__buffa::view::ClientCompatResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ClientResponseResultView; #[doc(inline)] +pub use self::__buffa::view::ClientResponseResultOwnedView; +#[doc(inline)] pub use self::__buffa::view::ClientErrorResultView; #[doc(inline)] +pub use self::__buffa::view::ClientErrorResultOwnedView; +#[doc(inline)] pub use self::__buffa::view::WireDetailsView; #[doc(inline)] +pub use self::__buffa::view::WireDetailsOwnedView; +#[doc(inline)] pub use self::__buffa::view::ServerCompatRequestView; #[doc(inline)] +pub use self::__buffa::view::ServerCompatRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::ServerCompatResponseView; #[doc(inline)] +pub use self::__buffa::view::ServerCompatResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::TestSuiteView; #[doc(inline)] +pub use self::__buffa::view::TestSuiteOwnedView; +#[doc(inline)] pub use self::__buffa::view::TestCaseView; #[doc(inline)] +pub use self::__buffa::view::TestCaseOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.server_compat.__view.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.server_compat.__view.rs index 903d3d3..64dd965 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.server_compat.__view.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.server_compat.__view.rs @@ -436,6 +436,191 @@ impl ::buffa::ViewReborrow for ServerCompatRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `ServerCompatRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`ServerCompatRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ServerCompatRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ServerCompatRequestOwnedView( + ::buffa::OwnedView>, +); +impl ServerCompatRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerCompatRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerCompatRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ServerCompatRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerCompatRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ServerCompatRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ServerCompatRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ServerCompatRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Signals to the server that it must support at least this protocol. Note + /// that it is fine to support others. + /// For example if `PROTOCOL_CONNECT` is specified, the server _must_ support + /// at least Connect, but _may_ also support gRPC or gRPC-web. + /// + /// Field 1: `protocol` + #[must_use] + pub fn protocol(&self) -> ::buffa::EnumValue { + self.0.reborrow().protocol + } + /// Signals to the server the minimum HTTP version to support. As with + /// `protocol`, it is fine to support other versions. For example, if + /// `HTTP_VERSION_2` is specified, the server _must_ support HTTP/2, but _may_ also + /// support HTTP/1.1 or HTTP/3. + /// + /// Field 2: `http_version` + #[must_use] + pub fn http_version(&self) -> ::buffa::EnumValue { + self.0.reborrow().http_version + } + /// If true, generate a certificate that clients will be configured to trust + /// when connecting and return it in the `pem_cert` field of the `ServerCompatResponse`. + /// The certificate can be any TLS certificate where the subject matches the + /// value sent back in the `host` field of the `ServerCompatResponse`. + /// Self-signed certificates (and `localhost` as the subject) are allowed. + /// If false, the server should not use TLS and instead use + /// a plain-text/unencrypted socket. + /// + /// Field 4: `use_tls` + #[must_use] + pub fn use_tls(&self) -> bool { + self.0.reborrow().use_tls + } + /// If non-empty, the clients will use certificates to authenticate + /// themselves. This value is a PEM-encoded cert that should be + /// trusted by the server. When non-empty, the server should require + /// that clients provide certificates and they should validate that + /// the certificate presented is valid. + /// + /// This will always be empty if use_tls is false. + /// + /// Field 5: `client_tls_cert` + #[must_use] + pub fn client_tls_cert(&self) -> &'_ [u8] { + self.0.reborrow().client_tls_cert + } + /// If non-zero, indicates the maximum size in bytes for a message. + /// If the client sends anything larger, the server should reject it. + /// + /// Field 6: `message_receive_limit` + #[must_use] + pub fn message_receive_limit(&self) -> u32 { + self.0.reborrow().message_receive_limit + } + /// If use_tls is true, this provides details for a self-signed TLS + /// cert that the server may use. + /// + /// The provided certificate is only good for loopback communication: + /// it uses "localhost" and "127.0.0.1" as the IP and DNS names in + /// the certificate's subject. If the server needs a different subject + /// or the client is in an environment where configuring trust of a + /// self-signed certificate is difficult or infeasible. + /// + /// If the server implementation chooses to use these credentials, + /// it must echo back the certificate in the ServerCompatResponse and + /// should also leave the host field empty or explicitly set to + /// "127.0.0.1". + /// + /// If it chooses to use a different certificate and key, it must send + /// back the corresponding certificate in the ServerCompatResponse. + /// + /// Field 7: `server_creds` + #[must_use] + pub fn server_creds( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().server_creds + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ServerCompatRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ServerCompatRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ServerCompatRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ServerCompatRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ServerCompatRequest { + type View<'a> = ServerCompatRequestView<'a>; + type ViewHandle = ServerCompatRequestOwnedView; +} +impl ::serde::Serialize for ServerCompatRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// The outcome of one ServerCompatRequest. #[derive(Clone, Debug, Default)] pub struct ServerCompatResponseView<'a> { @@ -692,3 +877,135 @@ impl ::buffa::ViewReborrow for ServerCompatResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ServerCompatResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`ServerCompatResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ServerCompatResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ServerCompatResponseOwnedView( + ::buffa::OwnedView>, +); +impl ServerCompatResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerCompatResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerCompatResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ServerCompatResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerCompatResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ServerCompatResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ServerCompatResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ServerCompatResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The host where the server is running. This should usually be `127.0.0.1`, + /// unless your program actually starts a remote server to which the client + /// should connect. + /// + /// Field 1: `host` + #[must_use] + pub fn host(&self) -> &'_ str { + self.0.reborrow().host + } + /// The port where the server is listening. + /// + /// Field 2: `port` + #[must_use] + pub fn port(&self) -> u32 { + self.0.reborrow().port + } + /// The TLS certificate, in PEM format, if `use_tls` was set + /// to `true`. Clients will verify this certificate when connecting via TLS. + /// If `use_tls` was set to `false`, this should always be empty. + /// + /// Field 3: `pem_cert` + #[must_use] + pub fn pem_cert(&self) -> &'_ [u8] { + self.0.reborrow().pem_cert + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ServerCompatResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ServerCompatResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ServerCompatResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ServerCompatResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ServerCompatResponse { + type View<'a> = ServerCompatResponseView<'a>; + type ViewHandle = ServerCompatResponseOwnedView; +} +impl ::serde::Serialize for ServerCompatResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.service.__view.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.service.__view.rs index 679ca05..c048bdf 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.service.__view.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.service.__view.rs @@ -496,6 +496,162 @@ impl ::buffa::ViewReborrow for UnaryResponseDefinitionView<'static> { this } } +/** Self-contained, `'static` owned view of a `UnaryResponseDefinition` message. + + Wraps [`::buffa::OwnedView`]`<`[`UnaryResponseDefinitionView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`UnaryResponseDefinitionView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct UnaryResponseDefinitionOwnedView( + ::buffa::OwnedView>, +); +impl UnaryResponseDefinitionOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryResponseDefinitionOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryResponseDefinitionOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::UnaryResponseDefinition, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryResponseDefinitionOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`UnaryResponseDefinitionView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &UnaryResponseDefinitionView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::UnaryResponseDefinition { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Response headers to send + /// + /// Field 1: `response_headers` + #[must_use] + pub fn response_headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().response_headers + } + /// Response trailers to send - together with the error if present + /// + /// Field 4: `response_trailers` + #[must_use] + pub fn response_trailers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().response_trailers + } + /// Wait this many milliseconds before sending a response message + /// + /// Field 6: `response_delay_ms` + #[must_use] + pub fn response_delay_ms(&self) -> u32 { + self.0.reborrow().response_delay_ms + } + /// This field is only used by the reference server. If you are implementing a + /// server under test, you can ignore this field or respond with an error if the + /// server receives a request where it is set. + /// + /// For test definitions, this field should be used instead of the above fields. + /// + /// Field 5: `raw_response` + #[must_use] + pub fn raw_response( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::RawHTTPResponseView<'_>, + > { + &self.0.reborrow().raw_response + } + /// Oneof `response`. + #[must_use] + pub fn response( + &self, + ) -> ::core::option::Option< + &super::super::__buffa::view::oneof::unary_response_definition::Response<'_>, + > { + self.0.reborrow().response.as_ref() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for UnaryResponseDefinitionOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + UnaryResponseDefinitionOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: UnaryResponseDefinitionOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for UnaryResponseDefinitionOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::UnaryResponseDefinition { + type View<'a> = UnaryResponseDefinitionView<'a>; + type ViewHandle = UnaryResponseDefinitionOwnedView; +} +impl ::serde::Serialize for UnaryResponseDefinitionOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// A definition of responses to be sent from a streaming endpoint. /// Can be used to define responses for server-streaming or bidi-streaming calls. #[derive(Clone, Debug, Default)] @@ -969,6 +1125,173 @@ impl ::buffa::ViewReborrow for StreamResponseDefinitionView<'static> { this } } +/** Self-contained, `'static` owned view of a `StreamResponseDefinition` message. + + Wraps [`::buffa::OwnedView`]`<`[`StreamResponseDefinitionView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`StreamResponseDefinitionView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct StreamResponseDefinitionOwnedView( + ::buffa::OwnedView>, +); +impl StreamResponseDefinitionOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamResponseDefinitionOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamResponseDefinitionOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::StreamResponseDefinition, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamResponseDefinitionOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`StreamResponseDefinitionView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &StreamResponseDefinitionView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::StreamResponseDefinition { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Response headers to send + /// + /// Field 1: `response_headers` + #[must_use] + pub fn response_headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().response_headers + } + /// Response data to send + /// + /// Field 2: `response_data` + #[must_use] + pub fn response_data(&self) -> &::buffa::RepeatedView<'_, &'_ [u8]> { + &self.0.reborrow().response_data + } + /// Wait this many milliseconds before sending each response message + /// + /// Field 3: `response_delay_ms` + #[must_use] + pub fn response_delay_ms(&self) -> u32 { + self.0.reborrow().response_delay_ms + } + /// Optional error to raise, but only after sending any response messages. + /// In the event an immediate error is thrown before any responses are sent, + /// (i.e. the equivalent of a trailers-only response), then servers should + /// build a RequestInfo message with available information and append that to + /// the error details. + /// + /// Field 4: `error` + #[must_use] + pub fn error( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().error + } + /// Response trailers to send - together with the error if present + /// + /// Field 5: `response_trailers` + #[must_use] + pub fn response_trailers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().response_trailers + } + /// This field is only used by the reference server. If you are implementing a + /// server under test, you can ignore this field or respond with an error if the + /// server receives a request where it is set. + /// + /// For test definitions, this field should be used instead of the above fields. + /// + /// Field 6: `raw_response` + #[must_use] + pub fn raw_response( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::RawHTTPResponseView<'_>, + > { + &self.0.reborrow().raw_response + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for StreamResponseDefinitionOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + StreamResponseDefinitionOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: StreamResponseDefinitionOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for StreamResponseDefinitionOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::StreamResponseDefinition { + type View<'a> = StreamResponseDefinitionView<'a>; + type ViewHandle = StreamResponseDefinitionOwnedView; +} +impl ::serde::Serialize for StreamResponseDefinitionOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct UnaryRequestView<'a> { /// The response definition which should be returned in the conformance payload @@ -1219,6 +1542,127 @@ impl ::buffa::ViewReborrow for UnaryRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `UnaryRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`UnaryRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`UnaryRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct UnaryRequestOwnedView(::buffa::OwnedView>); +impl UnaryRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::UnaryRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`UnaryRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &UnaryRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::UnaryRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The response definition which should be returned in the conformance payload + /// + /// Field 1: `response_definition` + #[must_use] + pub fn response_definition( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::UnaryResponseDefinitionView<'_>, + > { + &self.0.reborrow().response_definition + } + /// Additional data. Only used to pad the request size to test large request messages. + /// + /// Field 2: `request_data` + #[must_use] + pub fn request_data(&self) -> &'_ [u8] { + self.0.reborrow().request_data + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for UnaryRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + UnaryRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: UnaryRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for UnaryRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::UnaryRequest { + type View<'a> = UnaryRequestView<'a>; + type ViewHandle = UnaryRequestOwnedView; +} +impl ::serde::Serialize for UnaryRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct UnaryResponseView<'a> { /// The conformance payload to respond with. @@ -1428,6 +1872,120 @@ impl ::buffa::ViewReborrow for UnaryResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `UnaryResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`UnaryResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`UnaryResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct UnaryResponseOwnedView(::buffa::OwnedView>); +impl UnaryResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::UnaryResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnaryResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`UnaryResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &UnaryResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::UnaryResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The conformance payload to respond with. + /// + /// Field 1: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ConformancePayloadView<'_>, + > { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for UnaryResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + UnaryResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: UnaryResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for UnaryResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::UnaryResponse { + type View<'a> = UnaryResponseView<'a>; + type ViewHandle = UnaryResponseOwnedView; +} +impl ::serde::Serialize for UnaryResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct IdempotentUnaryRequestView<'a> { /// The response definition which should be returned in the conformance payload @@ -1678,6 +2236,131 @@ impl ::buffa::ViewReborrow for IdempotentUnaryRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `IdempotentUnaryRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`IdempotentUnaryRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`IdempotentUnaryRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct IdempotentUnaryRequestOwnedView( + ::buffa::OwnedView>, +); +impl IdempotentUnaryRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IdempotentUnaryRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IdempotentUnaryRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::IdempotentUnaryRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IdempotentUnaryRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`IdempotentUnaryRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &IdempotentUnaryRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::IdempotentUnaryRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The response definition which should be returned in the conformance payload + /// + /// Field 1: `response_definition` + #[must_use] + pub fn response_definition( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::UnaryResponseDefinitionView<'_>, + > { + &self.0.reborrow().response_definition + } + /// Additional data. Only used to pad the request size to test large request messages. + /// + /// Field 2: `request_data` + #[must_use] + pub fn request_data(&self) -> &'_ [u8] { + self.0.reborrow().request_data + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for IdempotentUnaryRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + IdempotentUnaryRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: IdempotentUnaryRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for IdempotentUnaryRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::IdempotentUnaryRequest { + type View<'a> = IdempotentUnaryRequestView<'a>; + type ViewHandle = IdempotentUnaryRequestOwnedView; +} +impl ::serde::Serialize for IdempotentUnaryRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct IdempotentUnaryResponseView<'a> { /// The conformance payload to respond with. @@ -1889,6 +2572,124 @@ impl ::buffa::ViewReborrow for IdempotentUnaryResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `IdempotentUnaryResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`IdempotentUnaryResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`IdempotentUnaryResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct IdempotentUnaryResponseOwnedView( + ::buffa::OwnedView>, +); +impl IdempotentUnaryResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IdempotentUnaryResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IdempotentUnaryResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::IdempotentUnaryResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IdempotentUnaryResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`IdempotentUnaryResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &IdempotentUnaryResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::IdempotentUnaryResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The conformance payload to respond with. + /// + /// Field 1: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ConformancePayloadView<'_>, + > { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for IdempotentUnaryResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + IdempotentUnaryResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: IdempotentUnaryResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for IdempotentUnaryResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::IdempotentUnaryResponse { + type View<'a> = IdempotentUnaryResponseView<'a>; + type ViewHandle = IdempotentUnaryResponseOwnedView; +} +impl ::serde::Serialize for IdempotentUnaryResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct ServerStreamRequestView<'a> { /// The response definition which should be returned in the conformance payload. @@ -2139,12 +2940,137 @@ impl ::buffa::ViewReborrow for ServerStreamRequestView<'static> { this } } -#[derive(Clone, Debug, Default)] -pub struct ServerStreamResponseView<'a> { - /// The conformance payload to respond with - /// - /// Field 1: `payload` - pub payload: ::buffa::MessageFieldView< +/** Self-contained, `'static` owned view of a `ServerStreamRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`ServerStreamRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ServerStreamRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ServerStreamRequestOwnedView( + ::buffa::OwnedView>, +); +impl ServerStreamRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerStreamRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerStreamRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ServerStreamRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerStreamRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ServerStreamRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ServerStreamRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ServerStreamRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The response definition which should be returned in the conformance payload. + /// + /// Field 1: `response_definition` + #[must_use] + pub fn response_definition( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::StreamResponseDefinitionView<'_>, + > { + &self.0.reborrow().response_definition + } + /// Additional data. Only used to pad the request size to test large request messages. + /// + /// Field 2: `request_data` + #[must_use] + pub fn request_data(&self) -> &'_ [u8] { + self.0.reborrow().request_data + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ServerStreamRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ServerStreamRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ServerStreamRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ServerStreamRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ServerStreamRequest { + type View<'a> = ServerStreamRequestView<'a>; + type ViewHandle = ServerStreamRequestOwnedView; +} +impl ::serde::Serialize for ServerStreamRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} +#[derive(Clone, Debug, Default)] +pub struct ServerStreamResponseView<'a> { + /// The conformance payload to respond with + /// + /// Field 1: `payload` + pub payload: ::buffa::MessageFieldView< super::super::__buffa::view::ConformancePayloadView<'a>, >, pub __buffa_unknown_fields: ::buffa::UnknownFieldsView<'a>, @@ -2348,6 +3274,124 @@ impl ::buffa::ViewReborrow for ServerStreamResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ServerStreamResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`ServerStreamResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ServerStreamResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ServerStreamResponseOwnedView( + ::buffa::OwnedView>, +); +impl ServerStreamResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerStreamResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerStreamResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ServerStreamResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ServerStreamResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ServerStreamResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ServerStreamResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ServerStreamResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The conformance payload to respond with + /// + /// Field 1: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ConformancePayloadView<'_>, + > { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ServerStreamResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ServerStreamResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ServerStreamResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ServerStreamResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ServerStreamResponse { + type View<'a> = ServerStreamResponseView<'a>; + type ViewHandle = ServerStreamResponseOwnedView; +} +impl ::serde::Serialize for ServerStreamResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct ClientStreamRequestView<'a> { /// Tells the server how to reply once all client messages are @@ -2601,6 +3645,134 @@ impl ::buffa::ViewReborrow for ClientStreamRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `ClientStreamRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`ClientStreamRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ClientStreamRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ClientStreamRequestOwnedView( + ::buffa::OwnedView>, +); +impl ClientStreamRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientStreamRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientStreamRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ClientStreamRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientStreamRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ClientStreamRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ClientStreamRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ClientStreamRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Tells the server how to reply once all client messages are + /// complete. Required in the first message in the stream, but + /// should be ignored in subsequent messages. + /// + /// Field 1: `response_definition` + #[must_use] + pub fn response_definition( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::UnaryResponseDefinitionView<'_>, + > { + &self.0.reborrow().response_definition + } + /// Additional data for subsequent messages in the stream. Also + /// used to pad the request size to test large request messages. + /// + /// Field 2: `request_data` + #[must_use] + pub fn request_data(&self) -> &'_ [u8] { + self.0.reborrow().request_data + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ClientStreamRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ClientStreamRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ClientStreamRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ClientStreamRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ClientStreamRequest { + type View<'a> = ClientStreamRequestView<'a>; + type ViewHandle = ClientStreamRequestOwnedView; +} +impl ::serde::Serialize for ClientStreamRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct ClientStreamResponseView<'a> { /// The conformance payload to respond with @@ -2810,6 +3982,124 @@ impl ::buffa::ViewReborrow for ClientStreamResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ClientStreamResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`ClientStreamResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ClientStreamResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ClientStreamResponseOwnedView( + ::buffa::OwnedView>, +); +impl ClientStreamResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientStreamResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientStreamResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ClientStreamResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ClientStreamResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ClientStreamResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ClientStreamResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ClientStreamResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The conformance payload to respond with + /// + /// Field 1: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ConformancePayloadView<'_>, + > { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ClientStreamResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ClientStreamResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ClientStreamResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ClientStreamResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ClientStreamResponse { + type View<'a> = ClientStreamResponseView<'a>; + type ViewHandle = ClientStreamResponseOwnedView; +} +impl ::serde::Serialize for ClientStreamResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct BidiStreamRequestView<'a> { /// Tells the server how to reply; required in the first message @@ -3100,6 +4390,152 @@ impl ::buffa::ViewReborrow for BidiStreamRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `BidiStreamRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`BidiStreamRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`BidiStreamRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct BidiStreamRequestOwnedView( + ::buffa::OwnedView>, +); +impl BidiStreamRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BidiStreamRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BidiStreamRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::BidiStreamRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BidiStreamRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`BidiStreamRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &BidiStreamRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::BidiStreamRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Tells the server how to reply; required in the first message + /// in the stream. Should be ignored in subsequent messages. + /// + /// Field 1: `response_definition` + #[must_use] + pub fn response_definition( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::StreamResponseDefinitionView<'_>, + > { + &self.0.reborrow().response_definition + } + /// Tells the server whether it should wait for each request + /// before sending a response. + /// + /// If true, it indicates the server should effectively interleave the + /// stream so messages are sent in request-\>response pairs. + /// + /// If false, then the response stream will be sent once all request messages + /// are finished sending with the only delays between messages + /// being the optional fixed milliseconds defined in the response + /// definition. + /// + /// This field is only relevant in the first message in the stream + /// and should be ignored in subsequent messages. + /// + /// Field 2: `full_duplex` + #[must_use] + pub fn full_duplex(&self) -> bool { + self.0.reborrow().full_duplex + } + /// Additional data for subsequent messages in the stream. Also + /// used to pad the request size to test large request messages. + /// + /// Field 3: `request_data` + #[must_use] + pub fn request_data(&self) -> &'_ [u8] { + self.0.reborrow().request_data + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for BidiStreamRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + BidiStreamRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: BidiStreamRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for BidiStreamRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::BidiStreamRequest { + type View<'a> = BidiStreamRequestView<'a>; + type ViewHandle = BidiStreamRequestOwnedView; +} +impl ::serde::Serialize for BidiStreamRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct BidiStreamResponseView<'a> { /// The conformance payload to respond with @@ -3309,6 +4745,124 @@ impl ::buffa::ViewReborrow for BidiStreamResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `BidiStreamResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`BidiStreamResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`BidiStreamResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct BidiStreamResponseOwnedView( + ::buffa::OwnedView>, +); +impl BidiStreamResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BidiStreamResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BidiStreamResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::BidiStreamResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + BidiStreamResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`BidiStreamResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &BidiStreamResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::BidiStreamResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The conformance payload to respond with + /// + /// Field 1: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ConformancePayloadView<'_>, + > { + &self.0.reborrow().payload + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for BidiStreamResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + BidiStreamResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: BidiStreamResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for BidiStreamResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::BidiStreamResponse { + type View<'a> = BidiStreamResponseView<'a>; + type ViewHandle = BidiStreamResponseOwnedView; +} +impl ::serde::Serialize for BidiStreamResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct UnimplementedRequestView<'a> { pub __buffa_unknown_fields: ::buffa::UnknownFieldsView<'a>, @@ -3458,6 +5012,113 @@ impl ::buffa::ViewReborrow for UnimplementedRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `UnimplementedRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`UnimplementedRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`UnimplementedRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct UnimplementedRequestOwnedView( + ::buffa::OwnedView>, +); +impl UnimplementedRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnimplementedRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnimplementedRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::UnimplementedRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnimplementedRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`UnimplementedRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &UnimplementedRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::UnimplementedRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for UnimplementedRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + UnimplementedRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: UnimplementedRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for UnimplementedRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::UnimplementedRequest { + type View<'a> = UnimplementedRequestView<'a>; + type ViewHandle = UnimplementedRequestOwnedView; +} +impl ::serde::Serialize for UnimplementedRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct UnimplementedResponseView<'a> { pub __buffa_unknown_fields: ::buffa::UnknownFieldsView<'a>, @@ -3607,6 +5268,113 @@ impl ::buffa::ViewReborrow for UnimplementedResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `UnimplementedResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`UnimplementedResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`UnimplementedResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct UnimplementedResponseOwnedView( + ::buffa::OwnedView>, +); +impl UnimplementedResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnimplementedResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnimplementedResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::UnimplementedResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + UnimplementedResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`UnimplementedResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &UnimplementedResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::UnimplementedResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for UnimplementedResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + UnimplementedResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: UnimplementedResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for UnimplementedResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::UnimplementedResponse { + type View<'a> = UnimplementedResponseView<'a>; + type ViewHandle = UnimplementedResponseOwnedView; +} +impl ::serde::Serialize for UnimplementedResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct ConformancePayloadView<'a> { /// Any response data specified in the response definition to the server should be @@ -3849,10 +5617,136 @@ impl<'v> ::buffa::DefaultViewInstance for ConformancePayloadView<'v> { )) } } -impl ::buffa::ViewReborrow for ConformancePayloadView<'static> { - type Reborrowed<'b> = ConformancePayloadView<'b>; - fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> { - this +impl ::buffa::ViewReborrow for ConformancePayloadView<'static> { + type Reborrowed<'b> = ConformancePayloadView<'b>; + fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> { + this + } +} +/** Self-contained, `'static` owned view of a `ConformancePayload` message. + + Wraps [`::buffa::OwnedView`]`<`[`ConformancePayloadView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ConformancePayloadView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ConformancePayloadOwnedView( + ::buffa::OwnedView>, +); +impl ConformancePayloadOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConformancePayloadOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConformancePayloadOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ConformancePayload, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConformancePayloadOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ConformancePayloadView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ConformancePayloadView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ConformancePayload { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Any response data specified in the response definition to the server should be + /// echoed back here. + /// + /// Field 1: `data` + #[must_use] + pub fn data(&self) -> &'_ [u8] { + self.0.reborrow().data + } + /// Echoes back information about the request stream observed so far. + /// + /// Field 2: `request_info` + #[must_use] + pub fn request_info( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::conformance_payload::RequestInfoView<'_>, + > { + &self.0.reborrow().request_info + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ConformancePayloadOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ConformancePayloadOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ConformancePayloadOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ConformancePayloadOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ConformancePayload { + type View<'a> = ConformancePayloadView<'a>; + type ViewHandle = ConformancePayloadOwnedView; +} +impl ::serde::Serialize for ConformancePayloadOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) } } pub mod conformance_payload { @@ -4233,6 +6127,170 @@ pub mod conformance_payload { this } } + /** Self-contained, `'static` owned view of a `RequestInfo` message. + + Wraps [`::buffa::OwnedView`]`<`[`RequestInfoView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`RequestInfoView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ + #[derive(Clone, Debug)] + pub struct RequestInfoOwnedView(::buffa::OwnedView>); + impl RequestInfoOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RequestInfoOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RequestInfoOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::super::conformance_payload::RequestInfo, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RequestInfoOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`RequestInfoView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &RequestInfoView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message( + &self, + ) -> super::super::super::conformance_payload::RequestInfo { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The server echos back the request headers it observed here. + /// + /// Field 1: `request_headers` + #[must_use] + pub fn request_headers( + &self, + ) -> &::buffa::RepeatedView< + '_, + super::super::super::__buffa::view::HeaderView<'_>, + > { + &self.0.reborrow().request_headers + } + /// The timeout observed that was included in the request. Other timeouts use a + /// type of uint32, but we want to be lenient here to allow whatever value the RPC + /// server observes, even if it's outside the range of uint32. + /// + /// Field 2: `timeout_ms` + #[must_use] + pub fn timeout_ms(&self) -> ::core::option::Option { + self.0.reborrow().timeout_ms + } + /// The server should echo back all requests received. + /// For unary and server-streaming requests, this should always contain a single request + /// For client-streaming and half-duplex bidi-streaming, this should contain + /// all client requests in the order received and be present in each response. + /// For full-duplex bidirectional-streaming, this should contain all requests in the order + /// they were received since the last sent response. + /// + /// Field 3: `requests` + #[must_use] + pub fn requests( + &self, + ) -> &::buffa::RepeatedView< + '_, + ::buffa_types::google::protobuf::__buffa::view::AnyView<'_>, + > { + &self.0.reborrow().requests + } + /// If present, the request used the Connect protocol and a GET method. This + /// captures other relevant information about the request. If a server implementation + /// is unable to populate this (due to the server framework not exposing all of these + /// details to application code), it may be an empty message. This implies that the + /// server framework, at a minimum, at least expose to application code whether the + /// request used GET vs. POST. + /// + /// Field 4: `connect_get_info` + #[must_use] + pub fn connect_get_info( + &self, + ) -> &::buffa::MessageFieldView< + super::super::super::__buffa::view::conformance_payload::ConnectGetInfoView< + '_, + >, + > { + &self.0.reborrow().connect_get_info + } + } + impl ::core::convert::From<::buffa::OwnedView>> + for RequestInfoOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + RequestInfoOwnedView(inner) + } + } + impl ::core::convert::From + for ::buffa::OwnedView> { + fn from(wrapper: RequestInfoOwnedView) -> Self { + wrapper.0 + } + } + impl ::core::convert::AsRef<::buffa::OwnedView>> + for RequestInfoOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } + } + impl ::buffa::HasMessageView + for super::super::super::conformance_payload::RequestInfo { + type View<'a> = RequestInfoView<'a>; + type ViewHandle = RequestInfoOwnedView; + } + impl ::serde::Serialize for RequestInfoOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } + } #[derive(Clone, Debug, Default)] pub struct ConnectGetInfoView<'a> { /// The query params observed in the request URL. @@ -4440,6 +6498,126 @@ pub mod conformance_payload { this } } + /** Self-contained, `'static` owned view of a `ConnectGetInfo` message. + + Wraps [`::buffa::OwnedView`]`<`[`ConnectGetInfoView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ConnectGetInfoView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ + #[derive(Clone, Debug)] + pub struct ConnectGetInfoOwnedView(::buffa::OwnedView>); + impl ConnectGetInfoOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConnectGetInfoOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConnectGetInfoOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::super::conformance_payload::ConnectGetInfo, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConnectGetInfoOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ConnectGetInfoView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ConnectGetInfoView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message( + &self, + ) -> super::super::super::conformance_payload::ConnectGetInfo { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The query params observed in the request URL. + /// + /// Field 1: `query_params` + #[must_use] + pub fn query_params( + &self, + ) -> &::buffa::RepeatedView< + '_, + super::super::super::__buffa::view::HeaderView<'_>, + > { + &self.0.reborrow().query_params + } + } + impl ::core::convert::From<::buffa::OwnedView>> + for ConnectGetInfoOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ConnectGetInfoOwnedView(inner) + } + } + impl ::core::convert::From + for ::buffa::OwnedView> { + fn from(wrapper: ConnectGetInfoOwnedView) -> Self { + wrapper.0 + } + } + impl ::core::convert::AsRef<::buffa::OwnedView>> + for ConnectGetInfoOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } + } + impl ::buffa::HasMessageView + for super::super::super::conformance_payload::ConnectGetInfo { + type View<'a> = ConnectGetInfoView<'a>; + type ViewHandle = ConnectGetInfoOwnedView; + } + impl ::serde::Serialize for ConnectGetInfoOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } + } } /// An error definition used for specifying a desired error response #[derive(Clone, Debug, Default)] @@ -4711,6 +6889,133 @@ impl ::buffa::ViewReborrow for ErrorView<'static> { this } } +/** Self-contained, `'static` owned view of a `Error` message. + + Wraps [`::buffa::OwnedView`]`<`[`ErrorView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ErrorView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ErrorOwnedView(::buffa::OwnedView>); +impl ErrorOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(ErrorOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ErrorOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Error, + ) -> ::core::result::Result { + ::core::result::Result::Ok(ErrorOwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`ErrorView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ErrorView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Error { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The error code. + /// For a list of Connect error codes see: + /// + /// Field 1: `code` + #[must_use] + pub fn code(&self) -> ::buffa::EnumValue { + self.0.reborrow().code + } + /// If this value is absent in a test case response definition, the contents of the + /// actual error message will not be checked. This is useful for certain kinds of + /// error conditions where the exact message to be used is not specified, only the + /// code. + /// + /// Field 2: `message` + #[must_use] + pub fn message(&self) -> ::core::option::Option<&'_ str> { + self.0.reborrow().message + } + /// Errors in Connect and gRPC protocols can have arbitrary messages + /// attached to them, which are known as error details. + /// + /// Field 3: `details` + #[must_use] + pub fn details( + &self, + ) -> &::buffa::RepeatedView< + '_, + ::buffa_types::google::protobuf::__buffa::view::AnyView<'_>, + > { + &self.0.reborrow().details + } +} +impl ::core::convert::From<::buffa::OwnedView>> for ErrorOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ErrorOwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: ErrorOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> for ErrorOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Error { + type View<'a> = ErrorView<'a>; + type ViewHandle = ErrorOwnedView; +} +impl ::serde::Serialize for ErrorOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// A tuple of name and values (ASCII) for a header or trailer entry. #[derive(Clone, Debug, Default)] pub struct HeaderView<'a> { @@ -4921,6 +7226,119 @@ impl ::buffa::ViewReborrow for HeaderView<'static> { this } } +/** Self-contained, `'static` owned view of a `Header` message. + + Wraps [`::buffa::OwnedView`]`<`[`HeaderView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`HeaderView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct HeaderOwnedView(::buffa::OwnedView>); +impl HeaderOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(HeaderOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + HeaderOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Header, + ) -> ::core::result::Result { + ::core::result::Result::Ok(HeaderOwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`HeaderView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &HeaderView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Header { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Header/trailer name (key). + /// + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// Header/trailer value. This is repeated to explicitly support headers and + /// trailers where a key is repeated. In such a case, these values must be in + /// the same order as which values appeared in the header or trailer block. + /// + /// Field 2: `value` + #[must_use] + pub fn value(&self) -> &::buffa::RepeatedView<'_, &'_ str> { + &self.0.reborrow().value + } +} +impl ::core::convert::From<::buffa::OwnedView>> for HeaderOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + HeaderOwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: HeaderOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for HeaderOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Header { + type View<'a> = HeaderView<'a>; + type ViewHandle = HeaderOwnedView; +} +impl ::serde::Serialize for HeaderOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// RawHTTPRequest models a raw HTTP request. This can be used to craft /// custom requests with odd properties (including certain kinds of /// malformed requests) to test edge cases in servers. @@ -5410,28 +7828,188 @@ impl<'__a> ::serde::Serialize for RawHTTPRequestView<'__a> { __map.end() } } -impl<'a> ::buffa::MessageName for RawHTTPRequestView<'a> { - const PACKAGE: &'static str = "connectrpc.conformance.v1"; - const NAME: &'static str = "RawHTTPRequest"; - const FULL_NAME: &'static str = "connectrpc.conformance.v1.RawHTTPRequest"; - const TYPE_URL: &'static str = "type.googleapis.com/connectrpc.conformance.v1.RawHTTPRequest"; +impl<'a> ::buffa::MessageName for RawHTTPRequestView<'a> { + const PACKAGE: &'static str = "connectrpc.conformance.v1"; + const NAME: &'static str = "RawHTTPRequest"; + const FULL_NAME: &'static str = "connectrpc.conformance.v1.RawHTTPRequest"; + const TYPE_URL: &'static str = "type.googleapis.com/connectrpc.conformance.v1.RawHTTPRequest"; +} +impl<'v> ::buffa::DefaultViewInstance for RawHTTPRequestView<'v> { + fn default_view_instance<'a>() -> &'a Self + where + Self: 'a, + { + static VALUE: ::buffa::__private::OnceBox> = ::buffa::__private::OnceBox::new(); + VALUE + .get_or_init(|| ::buffa::alloc::boxed::Box::new( + >::default(), + )) + } +} +impl ::buffa::ViewReborrow for RawHTTPRequestView<'static> { + type Reborrowed<'b> = RawHTTPRequestView<'b>; + fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> { + this + } +} +/** Self-contained, `'static` owned view of a `RawHTTPRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`RawHTTPRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`RawHTTPRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct RawHTTPRequestOwnedView(::buffa::OwnedView>); +impl RawHTTPRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RawHTTPRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RawHTTPRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::RawHTTPRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RawHTTPRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`RawHTTPRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &RawHTTPRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::RawHTTPRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The HTTP verb (i.e. GET , POST). + /// + /// Field 1: `verb` + #[must_use] + pub fn verb(&self) -> &'_ str { + self.0.reborrow().verb + } + /// The URI to send the request to. + /// + /// Field 2: `uri` + #[must_use] + pub fn uri(&self) -> &'_ str { + self.0.reborrow().uri + } + /// Any headers to set on the request. + /// + /// Field 3: `headers` + #[must_use] + pub fn headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().headers + } + /// These query params will be encoded and added to the uri before + /// the request is sent. + /// + /// Field 4: `raw_query_params` + #[must_use] + pub fn raw_query_params( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().raw_query_params + } + /// This provides an easier way to define a complex binary query param + /// than having to write literal base64-encoded bytes in raw_query_params. + /// + /// Field 5: `encoded_query_params` + #[must_use] + pub fn encoded_query_params( + &self, + ) -> &::buffa::RepeatedView< + '_, + super::super::__buffa::view::raw_http_request::EncodedQueryParamView<'_>, + > { + &self.0.reborrow().encoded_query_params + } + /// Oneof `body`. + #[must_use] + pub fn body( + &self, + ) -> ::core::option::Option< + &super::super::__buffa::view::oneof::raw_http_request::Body<'_>, + > { + self.0.reborrow().body.as_ref() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for RawHTTPRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + RawHTTPRequestOwnedView(inner) + } } -impl<'v> ::buffa::DefaultViewInstance for RawHTTPRequestView<'v> { - fn default_view_instance<'a>() -> &'a Self - where - Self: 'a, - { - static VALUE: ::buffa::__private::OnceBox> = ::buffa::__private::OnceBox::new(); - VALUE - .get_or_init(|| ::buffa::alloc::boxed::Box::new( - >::default(), - )) +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: RawHTTPRequestOwnedView) -> Self { + wrapper.0 } } -impl ::buffa::ViewReborrow for RawHTTPRequestView<'static> { - type Reborrowed<'b> = RawHTTPRequestView<'b>; - fn reborrow<'b>(this: &'b Self) -> &'b Self::Reborrowed<'b> { - this +impl ::core::convert::AsRef<::buffa::OwnedView>> +for RawHTTPRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::RawHTTPRequest { + type View<'a> = RawHTTPRequestView<'a>; + type ViewHandle = RawHTTPRequestOwnedView; +} +impl ::serde::Serialize for RawHTTPRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) } } pub mod raw_http_request { @@ -5710,6 +8288,142 @@ pub mod raw_http_request { this } } + /** Self-contained, `'static` owned view of a `EncodedQueryParam` message. + + Wraps [`::buffa::OwnedView`]`<`[`EncodedQueryParamView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`EncodedQueryParamView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ + #[derive(Clone, Debug)] + pub struct EncodedQueryParamOwnedView( + ::buffa::OwnedView>, + ); + impl EncodedQueryParamOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EncodedQueryParamOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EncodedQueryParamOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::super::raw_http_request::EncodedQueryParam, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EncodedQueryParamOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`EncodedQueryParamView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &EncodedQueryParamView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message( + &self, + ) -> super::super::super::raw_http_request::EncodedQueryParam { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Query param name. + /// + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// Query param value. + /// + /// Field 2: `value` + #[must_use] + pub fn value( + &self, + ) -> &::buffa::MessageFieldView< + super::super::super::__buffa::view::MessageContentsView<'_>, + > { + &self.0.reborrow().value + } + /// If true, the message contents will be base64-encoded and the + /// resulting string used as the query parameter value. + /// + /// Field 3: `base64_encode` + #[must_use] + pub fn base64_encode(&self) -> bool { + self.0.reborrow().base64_encode + } + } + impl ::core::convert::From<::buffa::OwnedView>> + for EncodedQueryParamOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + EncodedQueryParamOwnedView(inner) + } + } + impl ::core::convert::From + for ::buffa::OwnedView> { + fn from(wrapper: EncodedQueryParamOwnedView) -> Self { + wrapper.0 + } + } + impl ::core::convert::AsRef<::buffa::OwnedView>> + for EncodedQueryParamOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } + } + impl ::buffa::HasMessageView + for super::super::super::raw_http_request::EncodedQueryParam { + type View<'a> = EncodedQueryParamView<'a>; + type ViewHandle = EncodedQueryParamOwnedView; + } + impl ::serde::Serialize for EncodedQueryParamOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } + } } /// MessageContents represents a message in a request body. #[derive(Clone, Debug, Default)] @@ -6068,6 +8782,128 @@ impl ::buffa::ViewReborrow for MessageContentsView<'static> { this } } +/** Self-contained, `'static` owned view of a `MessageContents` message. + + Wraps [`::buffa::OwnedView`]`<`[`MessageContentsView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`MessageContentsView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct MessageContentsOwnedView(::buffa::OwnedView>); +impl MessageContentsOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MessageContentsOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MessageContentsOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::MessageContents, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + MessageContentsOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`MessageContentsView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &MessageContentsView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::MessageContents { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// If specified and not identity, the above data will be + /// compressed using the given algorithm. + /// + /// Field 4: `compression` + #[must_use] + pub fn compression(&self) -> ::buffa::EnumValue { + self.0.reborrow().compression + } + /// Oneof `data`. + #[must_use] + pub fn data( + &self, + ) -> ::core::option::Option< + &super::super::__buffa::view::oneof::message_contents::Data<'_>, + > { + self.0.reborrow().data.as_ref() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for MessageContentsOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + MessageContentsOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: MessageContentsOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for MessageContentsOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::MessageContents { + type View<'a> = MessageContentsView<'a>; + type ViewHandle = MessageContentsOwnedView; +} +impl ::serde::Serialize for MessageContentsOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// StreamContents represents a sequence of messages in a request body. #[derive(Clone, Debug, Default)] pub struct StreamContentsView<'a> { @@ -6270,6 +9106,123 @@ impl ::buffa::ViewReborrow for StreamContentsView<'static> { this } } +/** Self-contained, `'static` owned view of a `StreamContents` message. + + Wraps [`::buffa::OwnedView`]`<`[`StreamContentsView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`StreamContentsView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct StreamContentsOwnedView(::buffa::OwnedView>); +impl StreamContentsOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamContentsOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamContentsOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::StreamContents, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamContentsOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`StreamContentsView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &StreamContentsView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::StreamContents { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The messages in the stream. + /// + /// Field 1: `items` + #[must_use] + pub fn items( + &self, + ) -> &::buffa::RepeatedView< + '_, + super::super::__buffa::view::stream_contents::StreamItemView<'_>, + > { + &self.0.reborrow().items + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for StreamContentsOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + StreamContentsOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: StreamContentsOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for StreamContentsOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::StreamContents { + type View<'a> = StreamContentsView<'a>; + type ViewHandle = StreamContentsOwnedView; +} +impl ::serde::Serialize for StreamContentsOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} pub mod stream_contents { #[allow(unused_imports)] use super::*; @@ -6554,6 +9507,136 @@ pub mod stream_contents { this } } + /** Self-contained, `'static` owned view of a `StreamItem` message. + + Wraps [`::buffa::OwnedView`]`<`[`StreamItemView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`StreamItemView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ + #[derive(Clone, Debug)] + pub struct StreamItemOwnedView(::buffa::OwnedView>); + impl StreamItemOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamItemOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamItemOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::super::stream_contents::StreamItem, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + StreamItemOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`StreamItemView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &StreamItemView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message( + &self, + ) -> super::super::super::stream_contents::StreamItem { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// must be in the range 0 to 255. + /// + /// Field 1: `flags` + #[must_use] + pub fn flags(&self) -> u32 { + self.0.reborrow().flags + } + /// if absent use actual length of payload + /// + /// Field 2: `length` + #[must_use] + pub fn length(&self) -> ::core::option::Option { + self.0.reborrow().length + } + /// Field 3: `payload` + #[must_use] + pub fn payload( + &self, + ) -> &::buffa::MessageFieldView< + super::super::super::__buffa::view::MessageContentsView<'_>, + > { + &self.0.reborrow().payload + } + } + impl ::core::convert::From<::buffa::OwnedView>> + for StreamItemOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + StreamItemOwnedView(inner) + } + } + impl ::core::convert::From + for ::buffa::OwnedView> { + fn from(wrapper: StreamItemOwnedView) -> Self { + wrapper.0 + } + } + impl ::core::convert::AsRef<::buffa::OwnedView>> + for StreamItemOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } + } + impl ::buffa::HasMessageView for super::super::super::stream_contents::StreamItem { + type View<'a> = StreamItemView<'a>; + type ViewHandle = StreamItemOwnedView; + } + impl ::serde::Serialize for StreamItemOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } + } } /// RawHTTPResponse models a raw HTTP response. This can be used to craft /// custom responses with odd properties (including certain kinds of @@ -6994,3 +10077,142 @@ impl ::buffa::ViewReborrow for RawHTTPResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `RawHTTPResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`RawHTTPResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`RawHTTPResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct RawHTTPResponseOwnedView(::buffa::OwnedView>); +impl RawHTTPResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RawHTTPResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RawHTTPResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::RawHTTPResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + RawHTTPResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`RawHTTPResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &RawHTTPResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::RawHTTPResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// If status code is not specified, it will default to a 200 response code. + /// + /// Field 1: `status_code` + #[must_use] + pub fn status_code(&self) -> u32 { + self.0.reborrow().status_code + } + /// Headers to be set on the response. + /// + /// Field 2: `headers` + #[must_use] + pub fn headers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().headers + } + /// Trailers to be set on the response. + /// + /// Field 5: `trailers` + #[must_use] + pub fn trailers( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::HeaderView<'_>> { + &self.0.reborrow().trailers + } + /// Oneof `body`. + #[must_use] + pub fn body( + &self, + ) -> ::core::option::Option< + &super::super::__buffa::view::oneof::raw_http_response::Body<'_>, + > { + self.0.reborrow().body.as_ref() + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for RawHTTPResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + RawHTTPResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: RawHTTPResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for RawHTTPResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::RawHTTPResponse { + type View<'a> = RawHTTPResponseView<'a>; + type ViewHandle = RawHTTPResponseOwnedView; +} +impl ::serde::Serialize for RawHTTPResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.service.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.service.rs index bf17d97..e01374b 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.service.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.service.rs @@ -3402,7 +3402,11 @@ pub mod conformance_payload { #[doc(inline)] pub use super::__buffa::view::conformance_payload::RequestInfoView; #[doc(inline)] + pub use super::__buffa::view::conformance_payload::RequestInfoOwnedView; + #[doc(inline)] pub use super::__buffa::view::conformance_payload::ConnectGetInfoView; + #[doc(inline)] + pub use super::__buffa::view::conformance_payload::ConnectGetInfoOwnedView; } /// An error definition used for specifying a desired error response #[derive(Clone, PartialEq, Default)] @@ -4633,6 +4637,8 @@ pub mod raw_http_request { #[doc(inline)] pub use super::__buffa::view::raw_http_request::EncodedQueryParamView; #[doc(inline)] + pub use super::__buffa::view::raw_http_request::EncodedQueryParamOwnedView; + #[doc(inline)] pub use super::__buffa::view::oneof::raw_http_request::Body as BodyView; } /// MessageContents represents a message in a request body. @@ -5403,6 +5409,8 @@ pub mod stream_contents { }; #[doc(inline)] pub use super::__buffa::view::stream_contents::StreamItemView; + #[doc(inline)] + pub use super::__buffa::view::stream_contents::StreamItemOwnedView; } /// RawHTTPResponse models a raw HTTP response. This can be used to craft /// custom responses with odd properties (including certain kinds of diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.__view.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.__view.rs index 79ec7d3..2153cf0 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.__view.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.__view.rs @@ -735,6 +735,219 @@ impl ::buffa::ViewReborrow for TestSuiteView<'static> { this } } +/** Self-contained, `'static` owned view of a `TestSuite` message. + + Wraps [`::buffa::OwnedView`]`<`[`TestSuiteView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`TestSuiteView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct TestSuiteOwnedView(::buffa::OwnedView>); +impl TestSuiteOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TestSuiteOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TestSuiteOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::TestSuite, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TestSuiteOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`TestSuiteView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &TestSuiteView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::TestSuite { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Test suite name. When writing test suites, this is a required field. + /// + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// The mode (client or server) that this test suite applies to. This is used + /// in conjunction with the `--mode` flag passed to the conformance runner + /// binary. If the mode on the suite is set to client, the tests will only be + /// run if `--mode client` is set on the command to the test runner. + /// Likewise if mode is server. If this is unset, the test case will be run in both modes. + /// + /// Field 2: `mode` + #[must_use] + pub fn mode(&self) -> ::buffa::EnumValue { + self.0.reborrow().mode + } + /// The actual test cases in the suite. + /// + /// Field 3: `test_cases` + #[must_use] + pub fn test_cases( + &self, + ) -> &::buffa::RepeatedView<'_, super::super::__buffa::view::TestCaseView<'_>> { + &self.0.reborrow().test_cases + } + /// If non-empty, the protocols to which this suite applies. If empty, + /// this suite applies to all protocols. + /// + /// Field 4: `relevant_protocols` + #[must_use] + pub fn relevant_protocols( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().relevant_protocols + } + /// If non-empty, the HTTP versions to which this suite applies. If empty, + /// this suite applies to all HTTP versions. + /// + /// Field 5: `relevant_http_versions` + #[must_use] + pub fn relevant_http_versions( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().relevant_http_versions + } + /// If non-empty, the codecs to which this suite applies. If empty, this + /// suite applies to all codecs. + /// + /// Field 6: `relevant_codecs` + #[must_use] + pub fn relevant_codecs( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().relevant_codecs + } + /// If non-empty, the compression encodings to which this suite applies. + /// If empty, this suite applies to all encodings. + /// + /// Field 7: `relevant_compressions` + #[must_use] + pub fn relevant_compressions( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().relevant_compressions + } + /// Indicates the Connect version validation behavior that this suite + /// relies on. + /// + /// Field 8: `connect_version_mode` + #[must_use] + pub fn connect_version_mode( + &self, + ) -> ::buffa::EnumValue { + self.0.reborrow().connect_version_mode + } + /// If true, the cases in this suite rely on TLS and will only be run against + /// TLS server configurations. + /// + /// Field 9: `relies_on_tls` + #[must_use] + pub fn relies_on_tls(&self) -> bool { + self.0.reborrow().relies_on_tls + } + /// If true, the cases in this suite rely on the client using TLS + /// certificates to authenticate with the server. (Should only be + /// true if relies_on_tls is also true.) + /// + /// Field 10: `relies_on_tls_client_certs` + #[must_use] + pub fn relies_on_tls_client_certs(&self) -> bool { + self.0.reborrow().relies_on_tls_client_certs + } + /// If true, the cases in this suite rely on the Connect GET protocol. + /// + /// Field 11: `relies_on_connect_get` + #[must_use] + pub fn relies_on_connect_get(&self) -> bool { + self.0.reborrow().relies_on_connect_get + } + /// If true, the cases in this suite rely on support for limiting the + /// size of received messages. When true, mode should be set to indicate + /// whether it is the client or the server that must support the limit. + /// + /// Field 12: `relies_on_message_receive_limit` + #[must_use] + pub fn relies_on_message_receive_limit(&self) -> bool { + self.0.reborrow().relies_on_message_receive_limit + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for TestSuiteOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + TestSuiteOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: TestSuiteOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for TestSuiteOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::TestSuite { + type View<'a> = TestSuiteView<'a>; + type ViewHandle = TestSuiteOwnedView; +} +impl ::serde::Serialize for TestSuiteOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} #[derive(Clone, Debug, Default)] pub struct TestCaseView<'a> { /// Defines the RPC that the client should invoke. The first eight fields @@ -1172,6 +1385,189 @@ impl ::buffa::ViewReborrow for TestCaseView<'static> { this } } +/** Self-contained, `'static` owned view of a `TestCase` message. + + Wraps [`::buffa::OwnedView`]`<`[`TestCaseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`TestCaseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct TestCaseOwnedView(::buffa::OwnedView>); +impl TestCaseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(TestCaseOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TestCaseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::TestCase, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + TestCaseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`TestCaseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &TestCaseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::TestCase { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Defines the RPC that the client should invoke. The first eight fields + /// are not fully specified. Instead the first field, test_name, must be + /// present but is a prefix -- other characteristics that identify one + /// permutation of the test case will be appended to this name. The next + /// seven fields (http_version, protocol, codec, compression, host, port, + /// and server_tls_cert) must not be present. They are all populated by + /// the test harness based on the test environment (e.g. actual server and + /// port to use) and characteristics of a single permutation. + /// + /// Field 1: `request` + #[must_use] + pub fn request( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ClientCompatRequestView<'_>, + > { + &self.0.reborrow().request + } + /// To support extremely large messages, as well as very precisely-sized + /// messages, without having to encode them fully or perfectly in YAML + /// test cases, this value can be specified. When non-empty, this value + /// should have no more entries than there are messages in the request + /// stream. The first value is applied to the first request message, and + /// so on. For each entry, if the size is present, it is used to expand + /// the data field in the request (which is actually part of the response + /// definition). The specified size is added to the current limit on + /// message size that the server will accept. That sum is the size of the + /// the serialized message that will be sent, and the data field will be + /// padded as needed to reach that size. + /// + /// Field 2: `expand_requests` + #[must_use] + pub fn expand_requests( + &self, + ) -> &::buffa::RepeatedView< + '_, + super::super::__buffa::view::test_case::ExpandedSizeView<'_>, + > { + &self.0.reborrow().expand_requests + } + /// Defines the expected response to the above RPC. The expected response for + /// a test is auto-generated based on the request details. The conformance runner + /// will determine what the response should be according to the values specified + /// in the test suite and individual test cases. + /// + /// This value can also be specified explicitly in the test case YAML. However, + /// this is typically only needed for exception test cases. If the expected + /// response is mostly re-stating the response definition that appears in the + /// requests, test cases should rely on the auto-generation if possible. + /// Otherwise, specifying an expected response can make the test YAML overly + /// verbose and harder to read, write, and maintain. + /// + /// If the test induces behavior that prevents the server from sending or client + /// from receiving the full response definition, it will be necessary to define + /// the expected response explicitly. Timeouts, cancellations, and exceeding + /// message size limits are good examples of this. + /// + /// Specifying an expected response explicitly in test definitions will override + /// the auto-generation of the test runner. + /// + /// Field 3: `expected_response` + #[must_use] + pub fn expected_response( + &self, + ) -> &::buffa::MessageFieldView< + super::super::__buffa::view::ClientResponseResultView<'_>, + > { + &self.0.reborrow().expected_response + } + /// When expected_response indicates that an error is expected, in some cases, the + /// actual error code returned may be flexible. In that case, this field provides + /// other acceptable error codes, in addition to the one indicated in the + /// expected_response. As long as the actual error's code matches any of these, the + /// error is considered conformant, and the test case can pass. + /// + /// Field 4: `other_allowed_error_codes` + #[must_use] + pub fn other_allowed_error_codes( + &self, + ) -> &::buffa::RepeatedView<'_, ::buffa::EnumValue> { + &self.0.reborrow().other_allowed_error_codes + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for TestCaseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + TestCaseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: TestCaseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for TestCaseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::TestCase { + type View<'a> = TestCaseView<'a>; + type ViewHandle = TestCaseOwnedView; +} +impl ::serde::Serialize for TestCaseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} pub mod test_case { #[allow(unused_imports)] use super::*; @@ -1366,4 +1762,119 @@ pub mod test_case { this } } + /** Self-contained, `'static` owned view of a `ExpandedSize` message. + + Wraps [`::buffa::OwnedView`]`<`[`ExpandedSizeView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ExpandedSizeView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ + #[derive(Clone, Debug)] + pub struct ExpandedSizeOwnedView(::buffa::OwnedView>); + impl ExpandedSizeOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ExpandedSizeOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ExpandedSizeOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::super::test_case::ExpandedSize, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ExpandedSizeOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ExpandedSizeView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ExpandedSizeView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::super::test_case::ExpandedSize { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The size, in bytes, relative to the limit. For example, to expand to a + /// size that is exactly equal to the limit, this should be set to zero. + /// Any value greater than zero indicates that the request size will be that + /// many bytes over the limit. + /// + /// Field 1: `size_relative_to_limit` + #[must_use] + pub fn size_relative_to_limit(&self) -> ::core::option::Option { + self.0.reborrow().size_relative_to_limit + } + } + impl ::core::convert::From<::buffa::OwnedView>> + for ExpandedSizeOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ExpandedSizeOwnedView(inner) + } + } + impl ::core::convert::From + for ::buffa::OwnedView> { + fn from(wrapper: ExpandedSizeOwnedView) -> Self { + wrapper.0 + } + } + impl ::core::convert::AsRef<::buffa::OwnedView>> + for ExpandedSizeOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } + } + impl ::buffa::HasMessageView for super::super::super::test_case::ExpandedSize { + type View<'a> = ExpandedSizeView<'a>; + type ViewHandle = ExpandedSizeOwnedView; + } + impl ::serde::Serialize for ExpandedSizeOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } + } } diff --git a/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.rs b/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.rs index 8750b8c..9c94e59 100644 --- a/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.rs +++ b/conformance/src/generated/buffa/connectrpc.conformance.v1.suite.rs @@ -713,6 +713,17 @@ pub mod test_suite { /// reference client, to verify how the server reacts to such requests. TEST_MODE_SERVER = 2i32, } + impl TestMode { + ///Idiomatic alias for [`Self::TEST_MODE_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::TEST_MODE_UNSPECIFIED; + ///Idiomatic alias for [`Self::TEST_MODE_CLIENT`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Client: Self = Self::TEST_MODE_CLIENT; + ///Idiomatic alias for [`Self::TEST_MODE_SERVER`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Server: Self = Self::TEST_MODE_SERVER; + } impl ::core::default::Default for TestMode { fn default() -> Self { Self::TEST_MODE_UNSPECIFIED @@ -858,6 +869,17 @@ pub mod test_suite { /// header or query param. CONNECT_VERSION_MODE_IGNORE = 2i32, } + impl ConnectVersionMode { + ///Idiomatic alias for [`Self::CONNECT_VERSION_MODE_UNSPECIFIED`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Unspecified: Self = Self::CONNECT_VERSION_MODE_UNSPECIFIED; + ///Idiomatic alias for [`Self::CONNECT_VERSION_MODE_REQUIRE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Require: Self = Self::CONNECT_VERSION_MODE_REQUIRE; + ///Idiomatic alias for [`Self::CONNECT_VERSION_MODE_IGNORE`]; `Debug` prints the variant name. + #[allow(non_upper_case_globals)] + pub const Ignore: Self = Self::CONNECT_VERSION_MODE_IGNORE; + } impl ::core::default::Default for ConnectVersionMode { fn default() -> Self { Self::CONNECT_VERSION_MODE_UNSPECIFIED @@ -1498,4 +1520,6 @@ pub mod test_case { }; #[doc(inline)] pub use super::__buffa::view::test_case::ExpandedSizeView; + #[doc(inline)] + pub use super::__buffa::view::test_case::ExpandedSizeOwnedView; } diff --git a/conformance/src/generated/connect/connectrpc.conformance.v1.service.__connect.rs b/conformance/src/generated/connect/connectrpc.conformance.v1.service.__connect.rs index 1599294..e0bd97e 100644 --- a/conformance/src/generated/connect/connectrpc.conformance.v1.service.__connect.rs +++ b/conformance/src/generated/connect/connectrpc.conformance.v1.service.__connect.rs @@ -83,7 +83,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -111,7 +111,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -139,7 +139,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -167,7 +167,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -195,7 +195,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -223,7 +223,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -289,19 +289,31 @@ pub const CONFORMANCE_SERVICE_IDEMPOTENT_UNARY_SPEC: ::connectrpc::Spec = ::conn /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -314,10 +326,11 @@ pub const CONFORMANCE_SERVICE_IDEMPOTENT_UNARY_SPEC: ::connectrpc::Spec = ::conn /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -335,10 +348,19 @@ pub trait ConformanceService: Send + Sync + 'static { /// The returned payload should only contain the request info. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn unary<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedUnaryRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::connectrpc::conformance::v1::UnaryRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -363,10 +385,19 @@ pub trait ConformanceService: Send + Sync + 'static { /// and return without error if one is not. Stream headers and trailers should /// still be set on the stream if provided regardless of whether a response is /// sent or an error is thrown. + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call (until the response stream is returned); + /// message fields are read directly on it (zero-copy). Data the + /// returned stream needs must be copied out or converted via + /// `.to_owned_message()`. fn server_stream( &self, ctx: ::connectrpc::RequestContext, - request: OwnedServerStreamRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::connectrpc::conformance::v1::ServerStreamRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< ::connectrpc::ServiceStream< @@ -392,10 +423,20 @@ pub trait ConformanceService: Send + Sync + 'static { /// The returned payload should only contain the request info. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// Each `requests` item is a [`StreamMessage`](::connectrpc::StreamMessage): + /// it owns its buffer, is `Send + 'static`, and exposes zero-copy + /// accessor methods (`item.name()`), `.view()`, and + /// `.to_owned_message()`. Items can be yielded back unchanged + /// (`StreamMessage` implements `Encodable`). fn client_stream<'a>( &'a self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream, + requests: ::connectrpc::ServiceStream< + ::connectrpc::StreamMessage< + crate::proto::connectrpc::conformance::v1::ClientStreamRequest, + >, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -439,10 +480,20 @@ pub trait ConformanceService: Send + Sync + 'static { /// responses should only include the message data in the data field. /// - if the response_delay_ms duration is specified, the server should wait that /// long in between sending each response message. + /// + /// Each `requests` item is a [`StreamMessage`](::connectrpc::StreamMessage): + /// it owns its buffer, is `Send + 'static`, and exposes zero-copy + /// accessor methods (`item.name()`), `.view()`, and + /// `.to_owned_message()`. Items can be yielded back unchanged + /// (`StreamMessage` implements `Encodable`). fn bidi_stream( &self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream, + requests: ::connectrpc::ServiceStream< + ::connectrpc::StreamMessage< + crate::proto::connectrpc::conformance::v1::BidiStreamRequest, + >, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< ::connectrpc::ServiceStream< @@ -456,10 +507,19 @@ pub trait ConformanceService: Send + Sync + 'static { /// return an unimplemented error when invoked. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn unimplemented<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedUnimplementedRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::connectrpc::conformance::v1::UnimplementedRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -472,10 +532,19 @@ pub trait ConformanceService: Send + Sync + 'static { /// leverage query parameters to send data. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn idempotent_unary<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedIdempotentUnaryRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::connectrpc::conformance::v1::IdempotentUnaryRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -517,10 +586,21 @@ impl ConformanceServiceExt for S { "Unary", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::connectrpc::conformance::v1::__buffa::view::UnaryRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.unary(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::UnaryRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.unary(ctx, sreq) .await? .encode::< crate::proto::connectrpc::conformance::v1::UnaryResponse, @@ -539,9 +619,21 @@ impl ConformanceServiceExt for S { "ServerStream", ::connectrpc::view_streaming_handler_fn({ let svc = ::std::sync::Arc::clone(&self); - move |ctx, req| { + move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::connectrpc::conformance::v1::__buffa::view::ServerStreamRequestView< + 'static, + >, + >| + { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.server_stream(ctx, req).await } + async move { + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::ServerStreamRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.server_stream(ctx, sreq).await + } } }), ) @@ -554,6 +646,9 @@ impl ConformanceServiceExt for S { move |ctx, req, format| { let svc = ::std::sync::Arc::clone(&svc); async move { + let req = ::connectrpc::dispatcher::codegen::into_stream_messages::< + crate::proto::connectrpc::conformance::v1::ClientStreamRequest, + >(req); svc.client_stream(ctx, req) .await? .encode::< @@ -575,7 +670,12 @@ impl ConformanceServiceExt for S { let svc = ::std::sync::Arc::clone(&self); move |ctx, req| { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.bidi_stream(ctx, req).await } + async move { + let req = ::connectrpc::dispatcher::codegen::into_stream_messages::< + crate::proto::connectrpc::conformance::v1::BidiStreamRequest, + >(req); + svc.bidi_stream(ctx, req).await + } } }), ) @@ -585,10 +685,21 @@ impl ConformanceServiceExt for S { "Unimplemented", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::connectrpc::conformance::v1::__buffa::view::UnimplementedRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.unimplemented(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::UnimplementedRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.unimplemented(ctx, sreq) .await? .encode::< crate::proto::connectrpc::conformance::v1::UnimplementedResponse, @@ -603,10 +714,21 @@ impl ConformanceServiceExt for S { "IdempotentUnary", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::connectrpc::conformance::v1::__buffa::view::IdempotentUnaryRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.idempotent_unary(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::IdempotentUnaryRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.idempotent_unary(ctx, sreq) .await? .encode::< crate::proto::connectrpc::conformance::v1::IdempotentUnaryResponse, @@ -716,9 +838,17 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe "Unary" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::connectrpc::conformance::v1::__buffa::view::UnaryRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::connectrpc::conformance::v1::UnaryRequest, >(request.encoded()?, format)?; + let req: crate::proto::connectrpc::conformance::v1::__buffa::view::UnaryRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::UnaryRequest, + >::from_parts(&req, &body); svc.unary(ctx, req) .await? .encode::< @@ -729,9 +859,17 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe "Unimplemented" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::connectrpc::conformance::v1::__buffa::view::UnimplementedRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::connectrpc::conformance::v1::UnimplementedRequest, >(request.encoded()?, format)?; + let req: crate::proto::connectrpc::conformance::v1::__buffa::view::UnimplementedRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::UnimplementedRequest, + >::from_parts(&req, &body); svc.unimplemented(ctx, req) .await? .encode::< @@ -742,9 +880,17 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe "IdempotentUnary" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::connectrpc::conformance::v1::__buffa::view::IdempotentUnaryRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::connectrpc::conformance::v1::IdempotentUnaryRequest, >(request.encoded()?, format)?; + let req: crate::proto::connectrpc::conformance::v1::__buffa::view::IdempotentUnaryRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::IdempotentUnaryRequest, + >::from_parts(&req, &body); svc.idempotent_unary(ctx, req) .await? .encode::< @@ -771,9 +917,17 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe "ServerStream" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::connectrpc::conformance::v1::__buffa::view::ServerStreamRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::connectrpc::conformance::v1::ServerStreamRequest, >(request, format)?; + let req: crate::proto::connectrpc::conformance::v1::__buffa::view::ServerStreamRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::conformance::v1::ServerStreamRequest, + >::from_parts(&req, &body); let resp = svc.server_stream(ctx, req).await?; Ok( resp @@ -804,8 +958,8 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe "ClientStream" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::< - crate::proto::connectrpc::conformance::v1::__buffa::view::ClientStreamRequestView, + let req_stream = ::connectrpc::dispatcher::codegen::decode_message_request_stream::< + crate::proto::connectrpc::conformance::v1::ClientStreamRequest, >(requests, format); svc.client_stream(ctx, req_stream) .await? @@ -833,8 +987,8 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe "BidiStream" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::< - crate::proto::connectrpc::conformance::v1::__buffa::view::BidiStreamRequestView, + let req_stream = ::connectrpc::dispatcher::codegen::decode_message_request_stream::< + crate::proto::connectrpc::conformance::v1::BidiStreamRequest, >(requests, format); let resp = svc.bidi_stream(ctx, req_stream).await?; Ok( @@ -887,11 +1041,12 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.unary(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.unary(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -900,6 +1055,12 @@ impl ::connectrpc::Dispatcher for ConformanceServiceServe /// ```rust,ignore /// let owned = client.unary(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct ConformanceServiceClient { transport: T, diff --git a/connectrpc-codegen/src/codegen.rs b/connectrpc-codegen/src/codegen.rs index 3933aa7..e972439 100644 --- a/connectrpc-codegen/src/codegen.rs +++ b/connectrpc-codegen/src/codegen.rs @@ -56,6 +56,15 @@ pub struct Options { /// absolute paths into service stubs (set a `(".", "crate::proto")` /// catch-all so every type resolves); it is ignored by /// [`generate_files`] (the unified `super::`-relative path). + /// + /// Every `extern_path` target must be buffa-generated code from + /// buffa ≥ 0.7.0 with views enabled (and, if the crate feature-gates + /// its generated impls, with that feature turned on): the service + /// stubs rely on the `buffa::HasMessageView` impls and `FooOwnedView` + /// wrappers emitted alongside each message, the same way they rely on + /// the JSON/`Serialize` impls. `buffa-types` 0.7+ satisfies this for + /// the well-known types. A crate generated without them fails to + /// compile against the stubs (missing `HasMessageView` impl). pub buffa: CodeGenConfig, } @@ -404,6 +413,10 @@ pub fn generate_services( /// to a Rust module path. Repeatable; longest-prefix-match wins. /// `extern_path=.=` is the catch-all (equivalent to `buffa_module`). /// At least one catch-all mapping is required so every type resolves. +/// Every mapped path must point at buffa-generated code from +/// buffa ≥ 0.7.0 with views enabled — the stubs use the +/// `buffa::HasMessageView` impls and owned-view wrappers generated with +/// each message (`buffa-types` 0.7+ qualifies for the well-known types). /// - `file_per_package` — emit one `.rs` per proto package /// instead of the per-proto split + stitcher. Set `protoc-gen-buffa`'s /// own `file_per_package` option to the same value — the BSR/`tonic` @@ -713,11 +726,15 @@ fn generate_connect_services( // files can be `include!`d into the same module without E0252 duplicate // import errors. + // The view-family impls (`buffa::HasMessageView`) are emitted by buffa's + // own codegen alongside each message's view and owned-view wrapper, so + // nothing service-specific is needed here for `ServiceRequest` / + // `StreamMessage` to be usable. tokens.extend(generate_owned_view_aliases(file, resolver, batch)?); tokens.extend(generate_encodable_view_impls(file, resolver, batch)?); for service in &file.service { - tokens.extend(generate_service(file, service, resolver, batch)?); + tokens.extend(generate_service(file, service, resolver)?); } Ok(tokens) @@ -743,27 +760,54 @@ fn alias_collides(batch: &BatchState, current_package: &str, proto_fqn: &str) -> .contains(&(current_package.to_string(), alias)) } -/// Trait-method input-type tokens for an RPC: either the local -/// `OwnedView` alias (the common case) or the inlined -/// `::buffa::view::OwnedViewView<'static>>` form for -/// types whose alias would collide with another type in the same target -/// Rust module (issue #75). The inlined form mirrors what the generated -/// client method signatures already emit for response types. -fn owned_view_input_arg_type( +/// Statement converting the Router-path `ServiceStream>` into +/// `StreamMessage` items before calling the handler. Applies to every +/// input type, including ones mapped via `extern_path`: the backing +/// `buffa::HasMessageView` impl is emitted by buffa's codegen in the crate +/// that owns the type (`extern_path` targets are required to be generated +/// with buffa ≥ 0.7.0 and views enabled). +fn router_stream_items_tokens( resolver: &TypeResolver<'_>, - batch: &BatchState, - proto_fqn: &str, - current_package: &str, -) -> Result { - if alias_collides(batch, current_package, proto_fqn) { - let view = resolver.rust_view_type(proto_fqn, current_package)?; - Ok(quote!(::buffa::view::OwnedView<#view<'static>>)) - } else { - let alias = owned_view_alias_ident(proto_fqn); - Ok(quote!(#alias)) + method: &MethodDescriptorProto, + package: &str, +) -> TokenStream { + let input_fqn = method.input_type.as_deref().unwrap_or(""); + // Panic on resolver errors like the surrounding route-registration code + // does. (Threading `Result` through the registration builder is a + // follow-up.) + let input_owned = resolver + .rust_type(input_fqn, package) + .expect("rust_type failed for streaming input type"); + quote! { + let req = ::connectrpc::dispatcher::codegen::into_stream_messages::<#input_owned>(req); } } +/// Doc lines describing the inbound stream item type on a client-streaming / +/// bidi trait method. +fn stream_items_doc() -> TokenStream { + quote! { + #[doc = ""] + #[doc = " Each `requests` item is a [`StreamMessage`](::connectrpc::StreamMessage):"] + #[doc = " it owns its buffer, is `Send + 'static`, and exposes zero-copy"] + #[doc = " accessor methods (`item.name()`), `.view()`, and"] + #[doc = " `.to_owned_message()`. Items can be yielded back unchanged"] + #[doc = " (`StreamMessage` implements `Encodable`)."] + } +} + +/// Inbound stream item type for a client-streaming / bidi RPC: +/// `StreamMessage` keyed by the owned message. +fn stream_item_arg( + resolver: &TypeResolver<'_>, + method: &MethodDescriptorProto, + package: &str, +) -> Result { + let input_fqn = method.input_type.as_deref().unwrap_or(""); + let input_owned = resolver.rust_type(input_fqn, package)?; + Ok(quote! { ::connectrpc::StreamMessage<#input_owned> }) +} + /// Walk every service's method input/output FQNs across `file_to_generate` /// and identify `(package, alias_ident)` pairs where two or more distinct /// FQNs would produce the same `OwnedView` alias in the same target @@ -820,16 +864,15 @@ fn collect_alias_collisions( /// Emit `pub type Owned#{Msg}View = OwnedView<#{Msg}View<'static>>;` for /// every distinct RPC input/output type referenced by services in this -/// file. The alias is what handlers see in trait method signatures and -/// what users write in their `impl` blocks. +/// file. The alias names the owned-view form of a message in handler code +/// (e.g. an `OwnedOutView` response body or a decoded client response). /// /// Aliases whose name would collide with another distinct type's alias /// in the same target package (per [`BatchState::colliding_aliases`]) are -/// suppressed — the trait method signature inlines the -/// `OwnedView<…<'static>>` form for those types instead (see -/// [`owned_view_input_arg_type`]). This is the issue [#75] fix; the -/// non-colliding common case (including well-known types like -/// `.google.protobuf.Empty`) keeps its alias. +/// suppressed — users spell the inlined `OwnedView<…<'static>>` form for +/// those types instead. This is the issue [#75] fix; the non-colliding +/// common case (including well-known types like `.google.protobuf.Empty`) +/// keeps its alias. /// /// Deduped on `(package, fqn)` across the batch so two files in the same /// package don't both emit the alias (E0428). @@ -921,7 +964,7 @@ fn generate_encodable_view_impls( fn encode(&self, codec: ::connectrpc::CodecFormat) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } }); @@ -962,7 +1005,6 @@ fn generate_service( file: &FileDescriptorProto, service: &ServiceDescriptorProto, resolver: &TypeResolver<'_>, - batch: &BatchState, ) -> Result { let package = file.package.as_deref().unwrap_or(""); let service_name = service.name.as_deref().unwrap_or(""); @@ -1001,18 +1043,28 @@ fn generate_service( let full_doc = format!( "{base_doc}\n\n\ # Implementing handlers\n\n\ - Handlers receive requests as `OwnedFooView` (an alias for\n\ - `OwnedView>`), which gives zero-copy borrowed access\n\ - to fields (e.g. `request.name` is a `&str` into the decoded buffer).\n\ - The view can be held across `.await` points. When two RPC types in\n\ - the same package would alias to the same `Owned<…>View` name (e.g.\n\ - a local message plus an imported one with the same short name), the\n\ - alias is suppressed for both and the request type is spelled as\n\ - `OwnedView<…View<'static>>` directly in the trait signature.\n\n\ Implement methods with plain `async fn`; the returned future satisfies\n\ - the `Send` bound automatically. See the\n\ - [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations)\n\ - for zero-copy access patterns and when `to_owned_message()` is needed.\n\n\ + the `Send` bound automatically.\n\n\ + **Unary and server-streaming requests** arrive as\n\ + [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy\n\ + view of the request plus its body, valid for the duration of the call.\n\ + Fields are read directly (`request.name` is a `&str` into the decoded\n\ + buffer) and the borrow may be held across `.await` points. Anything\n\ + that must outlive the call — `tokio::spawn`, channels, server state,\n\ + or data captured by a returned response stream — takes owned data:\n\ + call `request.to_owned_message()` (or copy the specific fields)\n\ + first.\n\n\ + **Client-streaming and bidi requests** arrive as\n\ + `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`.\n\ + Each item owns its decoded buffer and is `Send + 'static`, so items\n\ + can be buffered or moved into spawned tasks; read fields zero-copy\n\ + through the generated accessor methods (`item.name()`) or `.view()`,\n\ + convert with `.to_owned_message()`, or yield an item back unchanged —\n\ + `StreamMessage` implements `Encodable`.\n\n\ + Request types resolved through `extern_path` (e.g. well-known types\n\ + from another crate) use the same wrappers; the crate that owns the\n\ + type must be generated with buffa ≥ 0.7.0 and views enabled so the\n\ + backing `HasMessageView` impl exists.\n\n\ The `impl Encodable` return bound accepts the owned `Out`, the\n\ generated `OutView<'_>` / `OwnedOutView`,\n\ [`MaybeBorrowed`](::connectrpc::MaybeBorrowed), or\n\ @@ -1023,10 +1075,11 @@ fn generate_service( WKT/extern outputs.\n\n\ Server-streaming and bidi-streaming methods return\n\ `ServiceStream + Send + use>`. The\n\ - `use` precise-capturing clause excludes `&self`'s lifetime\n\ - (unary methods use `use<'a, Self>` and may borrow), so stream items\n\ - must be `'static`. To stream view-encoded data, encode each item\n\ - inside the stream body and yield\n\ + `use` precise-capturing clause excludes `&self`'s lifetime and\n\ + the request's lifetime (unary methods use `use<'a, Self>` and may\n\ + borrow from `&self`), so stream items must be `'static` and cannot\n\ + borrow from the request. To stream view-encoded data, encode each\n\ + item inside the stream body and yield\n\ [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming\n\ example` doc." ); @@ -1036,7 +1089,7 @@ fn generate_service( let trait_methods: Vec = service .method .iter() - .map(|m| generate_trait_method(file, service, m, resolver, batch, package)) + .map(|m| generate_trait_method(file, service, m, resolver, package)) .collect::>>()?; // Generate route registrations for extension trait @@ -1062,15 +1115,26 @@ fn generate_service( let output_type = resolver .rust_type(m.output_type.as_deref().unwrap_or(""), package) .unwrap(); + let input_fqn = m.input_type.as_deref().unwrap_or(""); + let input_view = resolver.rust_view_type(input_fqn, package).unwrap(); + let input_owned = resolver.rust_type(input_fqn, package).unwrap(); + let call_handler = quote! { + let sreq = ::connectrpc::ServiceRequest::<#input_owned>::from_parts(req.reborrow(), req.bytes()); + svc.#method_snake(ctx, sreq).await + }; quote! { .route_view_server_stream::<_, _, #output_type>( #service_name_const, #method_name, ::connectrpc::view_streaming_handler_fn({ let svc = ::std::sync::Arc::clone(&self); - move |ctx, req| { + move |ctx, req: ::buffa::view::OwnedView<#input_view<'static>>| { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.#method_snake(ctx, req).await } + async move { + // `req` (an OwnedView) is owned by this future; the + // handler borrows from it until it returns the stream. + #call_handler + } } }), ) @@ -1080,6 +1144,7 @@ fn generate_service( let output_type = resolver .rust_type(m.output_type.as_deref().unwrap_or(""), package) .unwrap(); + let into_items = router_stream_items_tokens(resolver, m, package); quote! { .route_view_client_stream( #service_name_const, @@ -1089,6 +1154,7 @@ fn generate_service( move |ctx, req, format| { let svc = ::std::sync::Arc::clone(&svc); async move { + #into_items svc.#method_snake(ctx, req).await?.encode::<#output_type>(format) } } @@ -1101,6 +1167,7 @@ fn generate_service( let output_type = resolver .rust_type(m.output_type.as_deref().unwrap_or(""), package) .unwrap(); + let into_items = router_stream_items_tokens(resolver, m, package); quote! { .route_view_bidi_stream::<_, _, #output_type>( #service_name_const, @@ -1109,7 +1176,10 @@ fn generate_service( let svc = ::std::sync::Arc::clone(&self); move |ctx, req| { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.#method_snake(ctx, req).await } + async move { + #into_items + svc.#method_snake(ctx, req).await + } } }), ) @@ -1130,6 +1200,16 @@ fn generate_service( let output_type = resolver .rust_type(m.output_type.as_deref().unwrap_or(""), package) .unwrap(); + // The closure parameter is annotated because the handler now + // takes a borrowed request, so `ReqView` is no longer + // inferable from the call alone. + let input_fqn = m.input_type.as_deref().unwrap_or(""); + let input_view = resolver.rust_view_type(input_fqn, package).unwrap(); + let input_owned = resolver.rust_type(input_fqn, package).unwrap(); + let call_handler = quote! { + let sreq = ::connectrpc::ServiceRequest::<#input_owned>::from_parts(req.reborrow(), req.bytes()); + svc.#method_snake(ctx, sreq).await?.encode::<#output_type>(format) + }; quote! { .#route_method( @@ -1137,10 +1217,12 @@ fn generate_service( #method_name, { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move |ctx, req: ::buffa::view::OwnedView<#input_view<'static>>, format| { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.#method_snake(ctx, req).await?.encode::<#output_type>(format) + // `req` (an OwnedView) is owned by this future; the + // handler borrows from it for the call. + #call_handler } }) }, @@ -1227,11 +1309,12 @@ let response = client.{example_method}(request).await?; # Working with the response Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -The `OwnedView` derefs to the view, so field access is zero-copy: +[`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +message, so field access is zero-copy: ```rust,ignore -let resp = client.{example_method}(request).await?.into_view(); -let name: &str = resp.name; // borrow into the response buffer +let resp = client.{example_method}(request).await?; +let name: &str = resp.view().name; // borrow into the response buffer ``` If you need the owned struct (e.g. to store or pass by value), use @@ -1239,7 +1322,13 @@ If you need the owned struct (e.g. to store or pass by value), use ```rust,ignore let owned = client.{example_method}(request).await?.into_owned(); -```"# +``` + +[`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +zero-copy decoded body (an `OwnedView`) without copying; field access on it +goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +received message from `.message().await` — bind `msg.reborrow()` for field +access, or convert with `.to_owned_message()`."# ); let client_doc_tokens = doc_attrs(&client_doc); @@ -1454,13 +1543,21 @@ fn generate_service_server( let cs = m.client_streaming.unwrap_or(false); let ss = m.server_streaming.unwrap_or(false); + // Inbound stream decoding for client-streaming / bidi: typed + // `StreamMessage` items. + let stream_decode = { + let input_fqn = m.input_type.as_deref().unwrap_or(""); + let input_owned = resolver.rust_type(input_fqn, package)?; + quote! { ::connectrpc::dispatcher::codegen::decode_message_request_stream::<#input_owned>(requests, format) } + }; + if cs && ss { // Bidi streaming call_bidi_arms.push(quote! { #method_name => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::<#input_view>(requests, format); + let req_stream = #stream_decode; let resp = svc.#method_snake(ctx, req_stream).await?; Ok(resp.map_body(|s| ::connectrpc::dispatcher::codegen::encode_response_stream::<#output_type, _, _>(s, format))) }) @@ -1472,25 +1569,40 @@ fn generate_service_server( #method_name => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::<#input_view>(requests, format); + let req_stream = #stream_decode; svc.#method_snake(ctx, req_stream).await?.encode::<#output_type>(format) }) } }); } else if ss { // Server streaming + let input_fqn = m.input_type.as_deref().unwrap_or(""); + let input_owned = resolver.rust_type(input_fqn, package)?; + let call_handler = quote! { + let req = ::connectrpc::ServiceRequest::<#input_owned>::from_parts(&req, &body); + let resp = svc.#method_snake(ctx, req).await?; + }; call_ss_arms.push(quote! { #method_name => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::<#input_view>(request, format)?; - let resp = svc.#method_snake(ctx, req).await?; + // The normalized body is owned by this future; the handler + // borrows from it until it returns the response stream. + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::<#input_owned>(request, format)?; + let req: #input_view<'_> = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view(&body)?; + #call_handler Ok(resp.map_body(|s| ::connectrpc::dispatcher::codegen::encode_response_stream::<#output_type, _, _>(s, format))) }) } }); } else { // Unary + let input_fqn = m.input_type.as_deref().unwrap_or(""); + let input_owned = resolver.rust_type(input_fqn, package)?; + let call_handler = quote! { + let req = ::connectrpc::ServiceRequest::<#input_owned>::from_parts(&req, &body); + svc.#method_snake(ctx, req).await?.encode::<#output_type>(format) + }; call_unary_arms.push(quote! { #method_name => { let svc = ::std::sync::Arc::clone(&self.inner); @@ -1499,8 +1611,11 @@ fn generate_service_server( // cache an interceptor may have populated cannot be reused. // `encoded()` returns the (post-replacement) wire bytes — // a cheap `Bytes` clone for the common no-replacement case. - let req = ::connectrpc::dispatcher::codegen::decode_request_view::<#input_view>(request.encoded()?, format)?; - svc.#method_snake(ctx, req).await?.encode::<#output_type>(format) + // The normalized body is owned by this future; the handler + // borrows from it for the duration of the call. + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::<#input_owned>(request.encoded()?, format)?; + let req: #input_view<'_> = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view(&body)?; + #call_handler }) } }); @@ -1640,17 +1755,10 @@ fn generate_trait_method( service: &ServiceDescriptorProto, method: &MethodDescriptorProto, resolver: &TypeResolver<'_>, - batch: &BatchState, package: &str, ) -> Result { let method_name = method.name.as_deref().unwrap_or(""); let method_snake = make_field_ident(&method_name.to_snake_case()); - let input_arg = owned_view_input_arg_type( - resolver, - batch, - method.input_type.as_deref().unwrap_or(""), - package, - )?; let output_type = resolver.rust_type(method.output_type.as_deref().unwrap_or(""), package)?; // Get method documentation @@ -1674,46 +1782,92 @@ fn generate_trait_method( // `use` opts out of capturing `&self`'s lifetime (RPITITs in // trait methods otherwise capture it by default), since stream // items have to be `'static`. Without it, the generated route - // registration's `Arc::clone` closures fail E0597. + // registration's `Arc::clone` closures fail E0597. The borrowed + // `ServiceRequest` lifetime is likewise excluded, so the returned + // stream cannot borrow from the request — anything the stream needs + // must be copied or converted to owned before returning it. + let input_fqn = method.input_type.as_deref().unwrap_or(""); + let input_owned = resolver.rust_type(input_fqn, package)?; + let request_param = quote! { ::connectrpc::ServiceRequest<'_, #input_owned> }; + let request_doc = quote! { + #[doc = ""] + #[doc = " `request` is borrowed from the request body and is valid for the"] + #[doc = " duration of the call (until the response stream is returned);"] + #[doc = " message fields are read directly on it (zero-copy). Data the"] + #[doc = " returned stream needs must be copied out or converted via"] + #[doc = " `.to_owned_message()`."] + }; Ok(quote! { #method_doc_tokens + #request_doc fn #method_snake( &self, ctx: ::connectrpc::RequestContext, - request: #input_arg, + request: #request_param, ) -> impl ::std::future::Future + Send + use>>> + Send; }) } else if client_streaming && !server_streaming { - // Client streaming method + // Client streaming method. Inbound items are `StreamMessage` — + // each received message owns its decoded buffer (zero-copy reads via + // `.view()`, conversion via `.to_owned_message()`, and items can be + // forwarded as-is since `StreamMessage: Encodable`). + let stream_item_arg = stream_item_arg(resolver, method, package)?; + let items_doc = stream_items_doc(); Ok(quote! { #method_doc_tokens #borrow_doc + #items_doc fn #method_snake<'a>( &'a self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream<#input_arg>, + requests: ::connectrpc::ServiceStream<#stream_item_arg>, ) -> impl ::std::future::Future + Send + use<'a, Self>>> + Send; }) } else if client_streaming && server_streaming { // Bidi streaming method. Same `impl Encodable<...>` item type and - // `use` capture clause as server streaming above. + // `use` capture clause as server streaming above; inbound items + // are `StreamMessage` as for client streaming. + let stream_item_arg = stream_item_arg(resolver, method, package)?; + let items_doc = stream_items_doc(); Ok(quote! { #method_doc_tokens + #items_doc fn #method_snake( &self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream<#input_arg>, + requests: ::connectrpc::ServiceStream<#stream_item_arg>, ) -> impl ::std::future::Future + Send + use>>> + Send; }) } else { - // Unary method + // Unary method. The request is *borrowed*: the generated dispatcher + // owns the request body for the duration of the call and hands the + // handler a `ServiceRequest<'_, Req>` (zero-copy view + raw body) + // borrowed from it, so field access (`request.field`) is plain + // borrow-checked access with no synthetic `'static` involved. The + // handler future captures that borrow (RPITIT captures all in-scope + // lifetimes), which is fine because the dispatcher awaits it while + // still owning the body. The response's `use<'a, Self>` deliberately + // excludes the request lifetime: the response must not borrow from + // the request. + let input_fqn = method.input_type.as_deref().unwrap_or(""); + let input_owned = resolver.rust_type(input_fqn, package)?; + let request_param = quote! { ::connectrpc::ServiceRequest<'_, #input_owned> }; + let request_doc = quote! { + #[doc = ""] + #[doc = " `request` is borrowed from the request body and is valid for the"] + #[doc = " duration of the call; message fields are read directly on it"] + #[doc = " (zero-copy). The response cannot borrow from `request` — use"] + #[doc = " `.to_owned_message()` (or copy the specific fields) for anything"] + #[doc = " returned, stored, or moved into `tokio::spawn`."] + }; Ok(quote! { #method_doc_tokens #borrow_doc + #request_doc fn #method_snake<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: #input_arg, + request: #request_param, ) -> impl ::std::future::Future + Send + use<'a, Self>>> + Send; }) } @@ -2051,11 +2205,7 @@ mod tests { let resolver = TypeResolver::new(files, &target_name, &config, require_extern); let file = &files[target_idx]; let service = &file.service[0]; - let batch = BatchState { - colliding_aliases: collect_alias_collisions(files, &target_name), - ..BatchState::default() - }; - Ok(generate_service(file, service, &resolver, &batch)?.to_string()) + Ok(generate_service(file, service, &resolver)?.to_string()) } /// Assert that `formatted` (a Rust source string) contains no `use` @@ -2137,10 +2287,18 @@ mod tests { code.contains("pub type OwnedPingRespView = :: buffa :: view :: OwnedView"), "missing OwnedPingRespView alias: {code}" ); - // Trait method uses the alias for the request param. + // Unary trait methods take a borrowed ServiceRequest; the alias is + // still emitted (used by streaming shapes and user code). + assert!( + code.contains("request : :: connectrpc :: ServiceRequest < '_"), + "unary trait method should take request: ServiceRequest<'_, PingReq>: {code}" + ); + // The view-family impls backing ServiceRequest come from buffa's own + // codegen (alongside each message's view types), so connect-codegen + // emits none of its own. assert!( - code.contains("request : OwnedPingReqView ,"), - "trait method should take request: OwnedPingReqView: {code}" + !code.contains("impl :: connectrpc :: HasMessageView for"), + "connect-codegen must not emit view-family impls (buffa does): {code}" ); } @@ -2184,9 +2342,11 @@ mod tests { !code.contains("request : OwnedMyMessageView"), "colliding input must not reference the suppressed alias: {code}" ); + // The unary request is a borrowed ServiceRequest over the owned type, + // so the alias collision only affects the (still-suppressed) aliases. assert!( - code.contains("request : :: buffa :: view :: OwnedView <"), - "colliding input should be inlined as OwnedView<…<'static>>: {code}" + code.contains("request : :: connectrpc :: ServiceRequest < '_"), + "colliding unary input should still use ServiceRequest: {code}" ); } @@ -2218,9 +2378,16 @@ mod tests { code.contains("pub type OwnedEmptyView = :: buffa :: view :: OwnedView"), "WKT cross-package input should keep its alias: {code}" ); + // `.google.protobuf.Empty` resolves through the default extern_path to + // `::buffa_types::…`. extern_path targets are required to be + // buffa ≥ 0.7.0 generated code with views enabled, so the unary input + // uses the same `ServiceRequest<'_, Req>` form as local types — the + // backing `buffa::HasMessageView` impl ships with buffa-types. assert!( - code.contains("request : OwnedEmptyView ,"), - "trait method should still use OwnedEmptyView for non-colliding cross-package input: {code}" + code.contains( + "request : :: connectrpc :: ServiceRequest < '_ , :: buffa_types :: google :: protobuf :: Empty >" + ), + "extern unary input should use ServiceRequest over the extern owned type: {code}" ); } @@ -2291,22 +2458,23 @@ mod tests { "no method shape should reference the suppressed alias: {code}" ); - // Each method shape uses the inlined OwnedView<…<'static>> form. - // Unary + server-streaming take a single request param; client- - // streaming + bidi take a ServiceStream<…>. + // Unary and server-streaming both take the borrowed ServiceRequest + // keyed by the owned message; the alias collision is irrelevant to it. assert!( - code.matches("request : :: buffa :: view :: OwnedView <") + code.matches("request : :: connectrpc :: ServiceRequest < '_") .count() >= 2, - "unary and server-streaming should both inline the request type: {code}" + "unary and server-streaming should take the borrowed ServiceRequest form: {code}" ); + // Client-streaming and bidi inbound items are StreamMessage keyed + // by the owned message — the alias collision is irrelevant to them. assert!( code.matches( - "requests : :: connectrpc :: ServiceStream < :: buffa :: view :: OwnedView <" + "requests : :: connectrpc :: ServiceStream < :: connectrpc :: StreamMessage <" ) .count() >= 2, - "client-streaming and bidi should both inline the streamed request type: {code}" + "client-streaming and bidi should both take StreamMessage items: {code}" ); } diff --git a/connectrpc/src/client/mod.rs b/connectrpc/src/client/mod.rs index 9694e53..8366794 100644 --- a/connectrpc/src/client/mod.rs +++ b/connectrpc/src/client/mod.rs @@ -116,6 +116,7 @@ use http_body_util::combinators::BoxBody; use buffa::view::MessageView; use buffa::view::OwnedView; +use buffa::view::ViewReborrow; use crate::codec::CodecFormat; use crate::codec::content_type; @@ -1037,33 +1038,14 @@ impl UnaryResponse { &self.headers } - /// Borrow the response body. - /// - /// For generated clients the body is an [`OwnedView`], which derefs to - /// the view type — so field access is zero-copy: - /// - /// ```rust,ignore - /// let resp = client.foo(req).await?; - /// assert_eq!(resp.view().name, "expected"); // &str, no allocation - /// ``` - /// - /// See also [`into_view()`](Self::into_view) to consume and - /// [`into_owned()`](Self::into_owned) for an owned struct. - #[must_use] - pub fn view(&self) -> &Resp { - &self.body - } - /// Consume the response, returning just the body. /// /// For generated clients this is an [`OwnedView`] — zero-copy, move - /// semantics. If you need the owned struct instead, use + /// semantics, suitable for keeping the decoded body around without + /// copying. Field access on it goes through + /// [`reborrow()`](OwnedView::reborrow); for inline reads prefer + /// [`view()`](Self::view), and for an owned struct use /// [`into_owned()`](Self::into_owned). - /// - /// ```rust,ignore - /// let view = client.foo(req).await?.into_view(); - /// assert_eq!(view.name, "expected"); // &str via Deref - /// ``` #[must_use] pub fn into_view(self) -> Resp { self.body @@ -1093,9 +1075,8 @@ where /// /// This allocates and copies all borrowed fields (strings, bytes, nested /// messages). Prefer zero-copy view access via - /// [`view()`](UnaryResponse::view) / [`into_view()`](UnaryResponse::into_view) - /// unless you need to pass the owned struct to code that expects it, or - /// store it in a collection. + /// [`view()`](UnaryResponse::view) unless you need to pass the owned + /// struct to code that expects it, or store it in a collection. /// /// ```rust,ignore /// let owned: FooResponse = client.foo(req).await?.into_owned(); @@ -1106,6 +1087,30 @@ where } } +/// Zero-copy read access for [`OwnedView`] bodies whose view supports +/// reborrowing (every buffa-generated view does). +impl UnaryResponse> +where + V: MessageView<'static> + ViewReborrow, +{ + /// Borrow the response message view, tied to `&self`. + /// + /// Field access on the returned view is zero-copy: + /// + /// ```rust,ignore + /// let resp = client.foo(req).await?; + /// assert_eq!(resp.view().name, "expected"); // &str, no allocation + /// ``` + /// + /// See also [`into_view()`](UnaryResponse::into_view) to keep the decoded + /// body and [`into_owned()`](UnaryResponse::into_owned) for an owned + /// struct. + #[must_use] + pub fn view(&self) -> &V::Reborrowed<'_> { + self.body.reborrow() + } +} + /// Decode a response message as an `OwnedView` from bytes. /// /// For proto-encoded responses, this is a true zero-copy decode — the view borrows diff --git a/connectrpc/src/dispatcher.rs b/connectrpc/src/dispatcher.rs index 2ff4692..08257a6 100644 --- a/connectrpc/src/dispatcher.rs +++ b/connectrpc/src/dispatcher.rs @@ -347,7 +347,9 @@ pub mod codegen { // Re-exports that generated code needs direct access to. pub use crate::handler::BoxFuture; + pub use crate::handler::decode_borrowed_request_view; pub use crate::handler::decode_request_view; + pub use crate::handler::unary_request_proto_bytes; pub use crate::response::EncodedResponse; pub use super::MethodDescriptor; @@ -412,6 +414,40 @@ pub mod codegen { requests.map(move |r| r.and_then(|raw| decode_request_view::(raw, format))), ) } + + /// Convert a stream of decoded `OwnedView` items into + /// [`StreamMessage`](crate::StreamMessage)s. + /// + /// Used by generated Router-registration glue, whose runtime handler + /// wrappers produce `ServiceStream>`. + pub fn into_stream_messages( + requests: crate::ServiceStream>>, + ) -> crate::ServiceStream> + where + M: crate::HasMessageView + 'static, + M::View<'static>: 'static, + { + Box::pin(requests.map(|r| r.map(crate::StreamMessage::from_owned_view))) + } + + /// Map a stream of raw request bytes into typed + /// [`StreamMessage`](crate::StreamMessage) items. + /// + /// Used by generated `call_client_streaming` and `call_bidi_streaming` + /// arms; the per-item decode is shared with + /// [`decode_view_request_stream`]. + pub fn decode_message_request_stream( + requests: BoxStream>, + format: CodecFormat, + ) -> crate::ServiceStream> + where + M: crate::HasMessageView + DeserializeOwned + 'static, + M::View<'static>: 'static, + { + into_stream_messages::(decode_view_request_stream::>( + requests, format, + )) + } } #[cfg(test)] diff --git a/connectrpc/src/handler.rs b/connectrpc/src/handler.rs index 0b855d4..6a22e9e 100644 --- a/connectrpc/src/handler.rs +++ b/connectrpc/src/handler.rs @@ -681,6 +681,58 @@ where } } +/// Normalize a unary request body to protobuf wire bytes. +/// +/// For proto-encoded requests this is a pass-through of the input `Bytes`. +/// For JSON-encoded requests the body is deserialized to the owned message +/// and re-encoded to proto bytes. The returned buffer is what a scoped +/// request view (`FooRequestView<'_>`) borrows from in the generated +/// dispatch glue — the dispatcher keeps it alive for the duration of the +/// handler call, so the view's borrows are tied to the call frame. +/// +/// # Errors +/// +/// Returns `ConnectError::invalid_argument` if the JSON body cannot be +/// deserialized into the request message. +#[doc(hidden)] // exposed only for dispatcher::codegen (generated code) +pub fn unary_request_proto_bytes( + request: Bytes, + format: CodecFormat, +) -> Result +where + Req: Message + DeserializeOwned, +{ + match format { + CodecFormat::Proto => Ok(request), + CodecFormat::Json => { + let owned: Req = serde_json::from_slice(&request).map_err(|e| { + ConnectError::invalid_argument(format!("failed to decode JSON request: {e}")) + })?; + Ok(Bytes::from(owned.encode_to_vec())) + } + } +} + +/// Decode a scoped (borrowed) request view from normalized proto bytes. +/// +/// Companion to [`unary_request_proto_bytes`]: the generated dispatch glue +/// keeps the returned view's backing buffer alive across the handler call, +/// so the view's borrows are tied to the call frame rather than promoted to +/// a synthetic `'static`. +/// +/// # Errors +/// +/// Returns `ConnectError::invalid_argument` if the bytes are not a valid +/// encoding of the request message. +#[doc(hidden)] // exposed only for dispatcher::codegen (generated code) +pub fn decode_borrowed_request_view<'a, ReqView>(body: &'a [u8]) -> Result +where + ReqView: MessageView<'a>, +{ + ReqView::decode_view(body) + .map_err(|e| ConnectError::invalid_argument(format!("failed to decode proto request: {e}"))) +} + /// Trait for unary RPC handlers using zero-copy request views. /// /// `call` returns the response **already encoded** so the body's @@ -1192,14 +1244,14 @@ mod tests { let msg = StringValue::from("view-test"); let encoded = Bytes::from(msg.encode_to_vec()); let view = decode_request_view::(encoded, CodecFormat::Proto).unwrap(); - assert_eq!(view.value, "view-test"); + assert_eq!(view.reborrow().value, "view-test"); } #[test] fn test_decode_request_view_json() { let encoded = Bytes::from_static(b"\"json-view\""); let view = decode_request_view::(encoded, CodecFormat::Json).unwrap(); - assert_eq!(view.value, "json-view"); + assert_eq!(view.reborrow().value, "json-view"); } #[test] diff --git a/connectrpc/src/lib.rs b/connectrpc/src/lib.rs index 1a53a22..25f886e 100644 --- a/connectrpc/src/lib.rs +++ b/connectrpc/src/lib.rs @@ -193,10 +193,12 @@ pub mod handler; pub mod interceptor; pub mod payload; pub mod protocol; +pub mod request; pub mod response; pub mod router; pub mod service; pub mod spec; +pub mod stream_message; // Optional: HTTP client pub mod client; @@ -251,6 +253,8 @@ pub use handler::view_bidi_streaming_handler_fn; pub use handler::view_client_streaming_handler_fn; pub use handler::view_handler_fn; pub use handler::view_streaming_handler_fn; +pub use request::HasMessageView; +pub use request::ServiceRequest; pub use response::Encodable; pub use response::EncodedResponse; pub use response::MaybeBorrowed; @@ -259,6 +263,7 @@ pub use response::RequestContext; pub use response::Response; pub use response::ServiceResult; pub use response::ServiceStream; +pub use stream_message::StreamMessage; /// Re-exports for generated code. Not part of the public API; subject /// to change without a semver bump. diff --git a/connectrpc/src/payload.rs b/connectrpc/src/payload.rs index c201c0b..155f011 100644 --- a/connectrpc/src/payload.rs +++ b/connectrpc/src/payload.rs @@ -413,9 +413,9 @@ mod tests { fn view_zero_copy_proto() { let p = proto_payload("zero copy"); let v = p.view::().unwrap(); - assert_eq!(v.value, "zero copy"); + assert_eq!(v.reborrow().value, "zero copy"); // Borrows the payload's bytes — same backing storage. - let value_ptr = v.value.as_ptr() as usize; + let value_ptr = v.reborrow().value.as_ptr() as usize; let bytes_range = p.bytes().as_ptr() as usize..p.bytes().as_ptr() as usize + p.bytes().len(); assert!( @@ -454,7 +454,7 @@ mod tests { assert_eq!(m.value, "after"); // view() re-encodes the replacement and views it. let v = p.view::().unwrap(); - assert_eq!(v.value, "after"); + assert_eq!(v.reborrow().value, "after"); // encoded() re-encodes for the original format. let encoded = p.encoded().unwrap(); let rt: StringValue = decode_proto(&encoded).unwrap(); @@ -549,7 +549,7 @@ mod tests { ..Default::default() }); let v = p.view::().unwrap(); - assert_eq!(v.value, "after"); + assert_eq!(v.reborrow().value, "after"); } #[test] diff --git a/connectrpc/src/request.rs b/connectrpc/src/request.rs new file mode 100644 index 0000000..368f4a0 --- /dev/null +++ b/connectrpc/src/request.rs @@ -0,0 +1,169 @@ +//! Borrowed request wrapper for single-request RPCs: [`ServiceRequest`]. +//! +//! Unary and server-streaming handler methods receive a +//! [`ServiceRequest<'_, Req>`] — a zero-copy view of the request message plus +//! the raw request body, both borrowed from buffers that the generated +//! dispatch glue owns for the duration of the call. The name mirrors +//! [`ServiceResult`](crate::response::ServiceResult) on the response side. +//! +//! Not to be confused with the interceptor-facing request types +//! (`UnaryRequest` / `StreamRequest`), which wrap the *wire-level* request a +//! middleware sees; `ServiceRequest` is what a service trait implementation +//! receives after decoding. + +use buffa::view::MessageView; +use bytes::Bytes; + +/// Re-export of buffa's view-family trait. +/// +/// Generated buffa code implements this for every message (when views are +/// generated), linking the owned type to its borrowed view (`Req::View<'a>`) +/// and its `'static` handle (`Req::ViewHandle`, the `FooOwnedView` wrapper). +/// [`ServiceRequest<'_, Req>`] and +/// [`StreamMessage`](crate::StreamMessage) are bounded on it. +/// +/// The per-field accessor methods (`msg.name()`, …) are inherent on the +/// concrete generated wrapper and on the view's public fields; code that is +/// generic over `M: HasMessageView` reaches the message through +/// `as_ref()`/[`view`](crate::StreamMessage::view) / +/// [`to_owned_message`](crate::StreamMessage::to_owned_message) instead of +/// named fields. +pub use buffa::HasMessageView; + +/// A borrowed single-message RPC request (unary and server-streaming): a +/// zero-copy view of `Req` plus the raw request body, valid for the duration +/// of the handler call. +/// +/// `ServiceRequest` dereferences to the request's view type, so message +/// fields are read directly (`request.name`, `request.id`) with their +/// borrows tied to the call frame — they cannot outlive the request body. +/// Anything that must outlive the call (`tokio::spawn`, channels, server +/// state) takes owned data: call [`to_owned_message`](Self::to_owned_message) +/// (or copy the specific fields) first and move the owned value instead. +/// +/// The wrapper is `Copy` (it is two references), so it can be passed to +/// helper functions freely without `&` ceremony. +pub struct ServiceRequest<'a, Req: HasMessageView> { + view: &'a Req::View<'a>, + body: &'a Bytes, +} + +impl<'a, Req: HasMessageView> ServiceRequest<'a, Req> { + /// Assemble a request from a decoded view and the buffer it borrows from. + /// + /// Called by the generated dispatch glue; not normally used directly. + /// `view` should have been decoded from `body`: that is what makes + /// [`to_owned_message`](Self::to_owned_message)'s zero-copy `bytes`-field + /// path apply. If the buffers don't match, conversion still succeeds — + /// `bytes` fields are copied instead of sliced. + #[doc(hidden)] + pub fn from_parts(view: &'a Req::View<'a>, body: &'a Bytes) -> Self { + Self { view, body } + } + + /// The zero-copy view of the request message. + /// + /// Equivalent to the `Deref` target; useful when a `&FooRequestView<'_>` + /// is needed explicitly (struct patterns, lifetime-parameterised helpers). + #[must_use] + pub fn view(&self) -> &'a Req::View<'a> { + self.view + } + + /// Convert to the owned request message. + /// + /// `bytes` fields are sliced zero-copy out of the retained body where + /// possible; string and repeated fields are allocated. Use this for data + /// that must outlive the handler call. + #[must_use] + pub fn to_owned_message(&self) -> Req { + self.view.to_owned_from_source(Some(self.body)) + } + + /// The request body as protobuf wire bytes. + /// + /// For JSON-encoded requests this is the body re-encoded to protobuf + /// (the same buffer the view borrows from), not the original JSON text. + #[must_use] + pub fn bytes(&self) -> &'a Bytes { + self.body + } +} + +// Manual `Clone`/`Copy`: a derive would bound `Req` itself rather than the +// stored references, and `ServiceRequest` is two references regardless of `Req`. +impl Clone for ServiceRequest<'_, Req> { + fn clone(&self) -> Self { + *self + } +} +impl Copy for ServiceRequest<'_, Req> {} + +impl<'a, Req: HasMessageView> core::ops::Deref for ServiceRequest<'a, Req> { + type Target = Req::View<'a>; + + fn deref(&self) -> &Req::View<'a> { + self.view + } +} + +impl<'a, Req: HasMessageView> core::fmt::Debug for ServiceRequest<'a, Req> +where + Req::View<'a>: core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.view.fmt(f) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use buffa::Message; + use buffa_types::google::protobuf::__buffa::view::StringValueView; + use buffa_types::google::protobuf::StringValue; + + // `StringValue: HasMessageView` comes from buffa-types' generated code — + // no local glue impls are needed. + + fn encode(value: &str) -> Bytes { + Bytes::from( + StringValue { + value: value.into(), + ..Default::default() + } + .encode_to_vec(), + ) + } + + #[test] + fn deref_field_access_and_view() { + let body = encode("zero-copy"); + let view = StringValueView::decode_view(&body).unwrap(); + let req = ServiceRequest::::from_parts(&view, &body); + + // Field access through Deref, plus the explicit view() escape hatch. + assert_eq!(req.value, "zero-copy"); + assert_eq!(req.view().value, "zero-copy"); + + // The borrow points into the request body, not a copy. + let range = body.as_ptr_range(); + assert!(range.contains(&req.value.as_ptr())); + } + + #[test] + fn to_owned_message_and_bytes() { + let body = encode("keep me"); + let view = StringValueView::decode_view(&body).unwrap(); + let req = ServiceRequest::::from_parts(&view, &body); + + let owned: StringValue = req.to_owned_message(); + assert_eq!(owned.value, "keep me"); + assert_eq!(req.bytes().as_ref(), body.as_ref()); + + // Copy semantics: passing by value doesn't consume the original. + let copy = req; + assert_eq!(copy.value, req.value); + assert_eq!(format!("{req:?}"), format!("{copy:?}")); + } +} diff --git a/connectrpc/src/stream_message.rs b/connectrpc/src/stream_message.rs new file mode 100644 index 0000000..5f81ad3 --- /dev/null +++ b/connectrpc/src/stream_message.rs @@ -0,0 +1,193 @@ +//! Owned per-item wrapper for inbound streaming messages: [`StreamMessage`]. +//! +//! Items on a streaming RPC arrive over time, so unlike the unary +//! [`ServiceRequest`](crate::ServiceRequest) they cannot borrow from a buffer +//! owned by the dispatch glue — each item must own its bytes. `StreamMessage` +//! is that owner: one received message on a streaming RPC, holding its +//! decoded zero-copy view together with the buffer it borrows from. + +use buffa::view::{OwnedView, ViewReborrow}; +use bytes::Bytes; +use serde::Serialize; + +use crate::codec::CodecFormat; +use crate::error::ConnectError; +use crate::request::HasMessageView; +use crate::response::Encodable; + +/// One received message on a streaming RPC, owning its decoded buffer. +/// +/// `StreamMessage` dereferences to the buffa-generated `FooOwnedView` +/// wrapper, so message fields are read zero-copy through accessor methods +/// (`msg.name()`, `msg.id()`); [`view()`](Self::view) gives the full view for +/// struct patterns and iteration, and +/// [`to_owned_message()`](Self::to_owned_message) converts for data that must +/// be mutated or stored. Received items can also be forwarded as-is — +/// `StreamMessage` implements [`Encodable`], so an echo/relay handler +/// can yield them directly without re-encoding (the retained wire bytes are +/// reused on the proto path). +/// +/// The wrapper is `Send + Sync + 'static`, so items can be moved into +/// spawned tasks or buffered freely. +/// +/// # Field-name collisions +/// +/// `StreamMessage`'s own methods (`view`, `to_owned_message`, `bytes`) and +/// the wrapper's reserved methods take precedence over generated field +/// accessors. A proto field with one of those names has no accessor (buffa +/// emits a build warning for it); read it through the view instead: +/// `msg.view().bytes`. +pub struct StreamMessage { + inner: M::ViewHandle, +} + +impl StreamMessage { + /// Wrap an already-decoded [`OwnedView`]. + /// + /// Called by the generated dispatch glue; not normally used directly. + #[doc(hidden)] + pub fn from_owned_view(inner: OwnedView>) -> Self { + Self { + inner: M::ViewHandle::from(inner), + } + } + + /// The zero-copy view of this message, borrowed from the retained buffer. + #[must_use] + pub fn view<'b>(&'b self) -> &'b M::View<'b> + where + M::View<'static>: ViewReborrow = M::View<'b>>, + { + self.inner.as_ref().reborrow() + } + + /// Convert to the owned message. + /// + /// `bytes` fields are sliced zero-copy out of the retained buffer where + /// possible; string and repeated fields are allocated. + #[must_use] + pub fn to_owned_message(&self) -> M { + self.inner.as_ref().to_owned_message() + } + + /// The message's protobuf wire bytes. + /// + /// For JSON-encoded streams this is the message re-encoded to protobuf + /// (the buffer the view borrows from), not the original JSON text. + #[must_use] + pub fn bytes(&self) -> &Bytes { + self.inner.as_ref().bytes() + } +} + +/// Per-field accessor methods (`msg.name()`, `msg.id()`, …) come from the +/// buffa-generated `FooOwnedView` wrapper via `Deref`. +impl core::ops::Deref for StreamMessage { + type Target = M::ViewHandle; + + fn deref(&self) -> &M::ViewHandle { + &self.inner + } +} + +impl Clone for StreamMessage +where + M::ViewHandle: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + +impl core::fmt::Debug for StreamMessage +where + M::ViewHandle: core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.inner.fmt(f) + } +} + +/// Forward a received message without re-encoding. +/// +/// The proto path reuses the retained wire bytes (a cheap `Bytes` clone); the +/// JSON path converts to the owned message and serializes it, matching the +/// owned-message [`Encodable`] impl. +/// +/// # Codec asymmetry +/// +/// The two codecs are deliberately not byte-for-byte symmetric. On the proto +/// path the *original* wire bytes are forwarded, so unknown fields and any +/// non-canonical encoding the peer produced are preserved. On the JSON path +/// the message is re-serialized from the decoded form, so unknown fields are +/// dropped and the output is canonical — the original JSON text is not +/// retained after decoding (keeping it would mean buffering every inbound +/// message twice), so byte-preserving JSON forwarding is not possible. +/// Handlers that need exact relay semantics for both codecs should forward at +/// the byte/HTTP layer instead. +impl Encodable for StreamMessage +where + M: HasMessageView + Serialize, +{ + fn encode(&self, codec: CodecFormat) -> Result { + match codec { + CodecFormat::Proto => Ok(self.inner.as_ref().bytes().clone()), + CodecFormat::Json => serde_json::to_vec(&self.to_owned_message()) + .map(Bytes::from) + .map_err(|e| { + ConnectError::internal(format!("failed to encode JSON response: {e}")) + }), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use buffa::Message; + use buffa_types::google::protobuf::StringValue; + + fn message(value: &str) -> StreamMessage { + let bytes = Bytes::from( + StringValue { + value: value.into(), + ..Default::default() + } + .encode_to_vec(), + ); + StreamMessage::from_owned_view(OwnedView::decode(bytes).expect("decode")) + } + + #[test] + fn view_to_owned_and_bytes() { + let msg = message("streamed"); + assert_eq!(msg.view().value, "streamed"); + assert_eq!(msg.to_owned_message().value, "streamed"); + + // The view borrows from the retained buffer, not a copy. + let range = msg.bytes().as_ptr_range(); + assert!(range.contains(&msg.view().value.as_ptr())); + + // Clone + Debug forward to the inner view. + let cloned = msg.clone(); + assert_eq!(format!("{msg:?}"), format!("{cloned:?}")); + } + + #[test] + fn encodable_forwards_proto_bytes_without_reencoding() { + let msg = message("forward me"); + let original = msg.bytes().clone(); + + let proto = msg.encode(CodecFormat::Proto).expect("proto encode"); + assert_eq!(proto, original); + // Zero re-encode: same backing allocation, not just equal contents. + assert_eq!(proto.as_ptr(), original.as_ptr()); + + // JSON matches what the owned message would produce. + let json = msg.encode(CodecFormat::Json).expect("json encode"); + let owned_json = serde_json::to_vec(&msg.to_owned_message()).unwrap(); + assert_eq!(json.as_ref(), owned_json.as_slice()); + } +} diff --git a/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.eliza.__view.rs b/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.eliza.__view.rs index 4b4ea26..8a79025 100644 --- a/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.eliza.__view.rs +++ b/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.eliza.__view.rs @@ -178,6 +178,114 @@ impl ::buffa::ViewReborrow for SayRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `SayRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`SayRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`SayRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct SayRequestOwnedView(::buffa::OwnedView>); +impl SayRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + SayRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + SayRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::SayRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + SayRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`SayRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &SayRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::SayRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `sentence` + #[must_use] + pub fn sentence(&self) -> &'_ str { + self.0.reborrow().sentence + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for SayRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + SayRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: SayRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for SayRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::SayRequest { + type View<'a> = SayRequestView<'a>; + type ViewHandle = SayRequestOwnedView; +} +impl ::serde::Serialize for SayRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// SayResponse is a single-sentence response. #[derive(Clone, Debug, Default)] pub struct SayResponseView<'a> { @@ -355,6 +463,114 @@ impl ::buffa::ViewReborrow for SayResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `SayResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`SayResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`SayResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct SayResponseOwnedView(::buffa::OwnedView>); +impl SayResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + SayResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + SayResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::SayResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + SayResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`SayResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &SayResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::SayResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `sentence` + #[must_use] + pub fn sentence(&self) -> &'_ str { + self.0.reborrow().sentence + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for SayResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + SayResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: SayResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for SayResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::SayResponse { + type View<'a> = SayResponseView<'a>; + type ViewHandle = SayResponseOwnedView; +} +impl ::serde::Serialize for SayResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// ConverseRequest is a single sentence request sent as part of a /// back-and-forth conversation. #[derive(Clone, Debug, Default)] @@ -533,6 +749,116 @@ impl ::buffa::ViewReborrow for ConverseRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `ConverseRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`ConverseRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ConverseRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ConverseRequestOwnedView(::buffa::OwnedView>); +impl ConverseRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConverseRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConverseRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ConverseRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConverseRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ConverseRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ConverseRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ConverseRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `sentence` + #[must_use] + pub fn sentence(&self) -> &'_ str { + self.0.reborrow().sentence + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ConverseRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ConverseRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ConverseRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ConverseRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ConverseRequest { + type View<'a> = ConverseRequestView<'a>; + type ViewHandle = ConverseRequestOwnedView; +} +impl ::serde::Serialize for ConverseRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// ConverseResponse is a single sentence response sent in answer to a /// ConverseRequest. #[derive(Clone, Debug, Default)] @@ -711,6 +1037,116 @@ impl ::buffa::ViewReborrow for ConverseResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ConverseResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`ConverseResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ConverseResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ConverseResponseOwnedView(::buffa::OwnedView>); +impl ConverseResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConverseResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConverseResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ConverseResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ConverseResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ConverseResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ConverseResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ConverseResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `sentence` + #[must_use] + pub fn sentence(&self) -> &'_ str { + self.0.reborrow().sentence + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ConverseResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ConverseResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ConverseResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ConverseResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ConverseResponse { + type View<'a> = ConverseResponseView<'a>; + type ViewHandle = ConverseResponseOwnedView; +} +impl ::serde::Serialize for ConverseResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// IntroduceRequest asks Eliza to introduce itself to the named user. #[derive(Clone, Debug, Default)] pub struct IntroduceRequestView<'a> { @@ -888,6 +1324,116 @@ impl ::buffa::ViewReborrow for IntroduceRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `IntroduceRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`IntroduceRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`IntroduceRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct IntroduceRequestOwnedView(::buffa::OwnedView>); +impl IntroduceRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IntroduceRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IntroduceRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::IntroduceRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IntroduceRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`IntroduceRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &IntroduceRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::IntroduceRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for IntroduceRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + IntroduceRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: IntroduceRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for IntroduceRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::IntroduceRequest { + type View<'a> = IntroduceRequestView<'a>; + type ViewHandle = IntroduceRequestOwnedView; +} +impl ::serde::Serialize for IntroduceRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// IntroduceResponse is one sentence of Eliza's introductory monologue. #[derive(Clone, Debug, Default)] pub struct IntroduceResponseView<'a> { @@ -1065,3 +1611,115 @@ impl ::buffa::ViewReborrow for IntroduceResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `IntroduceResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`IntroduceResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`IntroduceResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct IntroduceResponseOwnedView( + ::buffa::OwnedView>, +); +impl IntroduceResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IntroduceResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IntroduceResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::IntroduceResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + IntroduceResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`IntroduceResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &IntroduceResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::IntroduceResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Field 1: `sentence` + #[must_use] + pub fn sentence(&self) -> &'_ str { + self.0.reborrow().sentence + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for IntroduceResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + IntroduceResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: IntroduceResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for IntroduceResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::IntroduceResponse { + type View<'a> = IntroduceResponseView<'a>; + type ViewHandle = IntroduceResponseOwnedView; +} +impl ::serde::Serialize for IntroduceResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.mod.rs b/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.mod.rs index 67965c9..1be16f8 100644 --- a/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.mod.rs +++ b/examples/eliza/src/generated/buffa/connectrpc.eliza.v1.mod.rs @@ -33,14 +33,26 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::SayRequestView; #[doc(inline)] +pub use self::__buffa::view::SayRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::SayResponseView; #[doc(inline)] +pub use self::__buffa::view::SayResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ConverseRequestView; #[doc(inline)] +pub use self::__buffa::view::ConverseRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::ConverseResponseView; #[doc(inline)] +pub use self::__buffa::view::ConverseResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::IntroduceRequestView; #[doc(inline)] +pub use self::__buffa::view::IntroduceRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::IntroduceResponseView; #[doc(inline)] +pub use self::__buffa::view::IntroduceResponseOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/examples/eliza/src/generated/connect/connectrpc.eliza.v1.eliza.__connect.rs b/examples/eliza/src/generated/connect/connectrpc.eliza.v1.eliza.__connect.rs index 24146b0..0f30331 100644 --- a/examples/eliza/src/generated/connect/connectrpc.eliza.v1.eliza.__connect.rs +++ b/examples/eliza/src/generated/connect/connectrpc.eliza.v1.eliza.__connect.rs @@ -39,7 +39,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable @@ -59,7 +59,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable @@ -79,7 +79,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -120,19 +120,31 @@ pub const ELIZA_SERVICE_INTRODUCE_SPEC: ::connectrpc::Spec = ::connectrpc::Spec: /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -145,10 +157,11 @@ pub const ELIZA_SERVICE_INTRODUCE_SPEC: ::connectrpc::Spec = ::connectrpc::Spec: /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -156,10 +169,19 @@ pub trait ElizaService: Send + Sync + 'static { /// Say is a unary RPC. Eliza responds to the prompt with a single sentence. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn say<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedSayRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::connectrpc::eliza::v1::SayRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -170,10 +192,20 @@ pub trait ElizaService: Send + Sync + 'static { /// Converse is a bidirectional RPC. The caller may exchange multiple /// back-and-forth messages with Eliza over a long-lived connection. Eliza /// responds to each ConverseRequest with a ConverseResponse. + /// + /// Each `requests` item is a [`StreamMessage`](::connectrpc::StreamMessage): + /// it owns its buffer, is `Send + 'static`, and exposes zero-copy + /// accessor methods (`item.name()`), `.view()`, and + /// `.to_owned_message()`. Items can be yielded back unchanged + /// (`StreamMessage` implements `Encodable`). fn converse( &self, ctx: ::connectrpc::RequestContext, - requests: ::connectrpc::ServiceStream, + requests: ::connectrpc::ServiceStream< + ::connectrpc::StreamMessage< + crate::proto::connectrpc::eliza::v1::ConverseRequest, + >, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< ::connectrpc::ServiceStream< @@ -185,10 +217,19 @@ pub trait ElizaService: Send + Sync + 'static { > + Send; /// Introduce is a server streaming RPC. Given the caller's name, Eliza /// returns a stream of sentences to introduce itself. + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call (until the response stream is returned); + /// message fields are read directly on it (zero-copy). Data the + /// returned stream needs must be copied out or converted via + /// `.to_owned_message()`. fn introduce( &self, ctx: ::connectrpc::RequestContext, - request: OwnedIntroduceRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::connectrpc::eliza::v1::IntroduceRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< ::connectrpc::ServiceStream< @@ -232,10 +273,21 @@ impl ElizaServiceExt for S { "Say", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::connectrpc::eliza::v1::__buffa::view::SayRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.say(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::eliza::v1::SayRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.say(ctx, sreq) .await? .encode::< crate::proto::connectrpc::eliza::v1::SayResponse, @@ -256,7 +308,12 @@ impl ElizaServiceExt for S { let svc = ::std::sync::Arc::clone(&self); move |ctx, req| { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.converse(ctx, req).await } + async move { + let req = ::connectrpc::dispatcher::codegen::into_stream_messages::< + crate::proto::connectrpc::eliza::v1::ConverseRequest, + >(req); + svc.converse(ctx, req).await + } } }), ) @@ -270,9 +327,21 @@ impl ElizaServiceExt for S { "Introduce", ::connectrpc::view_streaming_handler_fn({ let svc = ::std::sync::Arc::clone(&self); - move |ctx, req| { + move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::connectrpc::eliza::v1::__buffa::view::IntroduceRequestView< + 'static, + >, + >| + { let svc = ::std::sync::Arc::clone(&svc); - async move { svc.introduce(ctx, req).await } + async move { + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::eliza::v1::IntroduceRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.introduce(ctx, sreq).await + } } }), ) @@ -358,9 +427,17 @@ impl ::connectrpc::Dispatcher for ElizaServiceServer { "Say" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::connectrpc::eliza::v1::__buffa::view::SayRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::connectrpc::eliza::v1::SayRequest, >(request.encoded()?, format)?; + let req: crate::proto::connectrpc::eliza::v1::__buffa::view::SayRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::eliza::v1::SayRequest, + >::from_parts(&req, &body); svc.say(ctx, req) .await? .encode::< @@ -386,9 +463,17 @@ impl ::connectrpc::Dispatcher for ElizaServiceServer { "Introduce" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::connectrpc::eliza::v1::__buffa::view::IntroduceRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::connectrpc::eliza::v1::IntroduceRequest, >(request, format)?; + let req: crate::proto::connectrpc::eliza::v1::__buffa::view::IntroduceRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::connectrpc::eliza::v1::IntroduceRequest, + >::from_parts(&req, &body); let resp = svc.introduce(ctx, req).await?; Ok( resp @@ -433,8 +518,8 @@ impl ::connectrpc::Dispatcher for ElizaServiceServer { "Converse" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req_stream = ::connectrpc::dispatcher::codegen::decode_view_request_stream::< - crate::proto::connectrpc::eliza::v1::__buffa::view::ConverseRequestView, + let req_stream = ::connectrpc::dispatcher::codegen::decode_message_request_stream::< + crate::proto::connectrpc::eliza::v1::ConverseRequest, >(requests, format); let resp = svc.converse(ctx, req_stream).await?; Ok( @@ -487,11 +572,12 @@ impl ::connectrpc::Dispatcher for ElizaServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.say(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.say(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -500,6 +586,12 @@ impl ::connectrpc::Dispatcher for ElizaServiceServer { /// ```rust,ignore /// let owned = client.say(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct ElizaServiceClient { transport: T, diff --git a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.greet.__view.rs b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.greet.__view.rs index 6243381..54a4cdd 100644 --- a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.greet.__view.rs +++ b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.greet.__view.rs @@ -180,6 +180,116 @@ impl ::buffa::ViewReborrow for GreetRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `GreetRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`GreetRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`GreetRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct GreetRequestOwnedView(::buffa::OwnedView>); +impl GreetRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GreetRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GreetRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::GreetRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GreetRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`GreetRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &GreetRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::GreetRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The name to greet. + /// + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for GreetRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + GreetRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: GreetRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for GreetRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::GreetRequest { + type View<'a> = GreetRequestView<'a>; + type ViewHandle = GreetRequestOwnedView; +} +impl ::serde::Serialize for GreetRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// GreetResponse is the response message for the Greet RPC. #[derive(Clone, Debug, Default)] pub struct GreetResponseView<'a> { @@ -359,3 +469,113 @@ impl ::buffa::ViewReborrow for GreetResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `GreetResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`GreetResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`GreetResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct GreetResponseOwnedView(::buffa::OwnedView>); +impl GreetResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GreetResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GreetResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::GreetResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + GreetResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`GreetResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &GreetResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::GreetResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The greeting message. + /// + /// Field 1: `message` + #[must_use] + pub fn message(&self) -> &'_ str { + self.0.reborrow().message + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for GreetResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + GreetResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: GreetResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for GreetResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::GreetResponse { + type View<'a> = GreetResponseView<'a>; + type ViewHandle = GreetResponseOwnedView; +} +impl ::serde::Serialize for GreetResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.mod.rs b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.mod.rs index b143cc4..932bcfe 100644 --- a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.mod.rs +++ b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.greet.v1.mod.rs @@ -29,6 +29,10 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::GreetRequestView; #[doc(inline)] +pub use self::__buffa::view::GreetRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::GreetResponseView; #[doc(inline)] +pub use self::__buffa::view::GreetResponseOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.math.__view.rs b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.math.__view.rs index cc47966..7b16bdc 100644 --- a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.math.__view.rs +++ b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.math.__view.rs @@ -221,6 +221,123 @@ impl ::buffa::ViewReborrow for AddRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `AddRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`AddRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`AddRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct AddRequestOwnedView(::buffa::OwnedView>); +impl AddRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + AddRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + AddRequestOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::AddRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + AddRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`AddRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &AddRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::AddRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// First number to add. + /// + /// Field 1: `a` + #[must_use] + pub fn a(&self) -> i32 { + self.0.reborrow().a + } + /// Second number to add. + /// + /// Field 2: `b` + #[must_use] + pub fn b(&self) -> i32 { + self.0.reborrow().b + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for AddRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + AddRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: AddRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for AddRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::AddRequest { + type View<'a> = AddRequestView<'a>; + type ViewHandle = AddRequestOwnedView; +} +impl ::serde::Serialize for AddRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// AddResponse is the response message for the Add RPC. #[derive(Clone, Debug, Default)] pub struct AddResponseView<'a> { @@ -406,3 +523,113 @@ impl ::buffa::ViewReborrow for AddResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `AddResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`AddResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`AddResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct AddResponseOwnedView(::buffa::OwnedView>); +impl AddResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + AddResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + AddResponseOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::AddResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + AddResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`AddResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &AddResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::AddResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The result of the addition. + /// + /// Field 1: `result` + #[must_use] + pub fn result(&self) -> i32 { + self.0.reborrow().result + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for AddResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + AddResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: AddResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for AddResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::AddResponse { + type View<'a> = AddResponseView<'a>; + type ViewHandle = AddResponseOwnedView; +} +impl ::serde::Serialize for AddResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.mod.rs b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.mod.rs index 68d7407..16ec7f7 100644 --- a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.mod.rs +++ b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.math.v1.mod.rs @@ -29,6 +29,10 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::AddRequestView; #[doc(inline)] +pub use self::__buffa::view::AddRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::AddResponseView; #[doc(inline)] +pub use self::__buffa::view::AddResponseOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.mod.rs b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.mod.rs index 7b2dc73..c4f4b9d 100644 --- a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.mod.rs +++ b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.mod.rs @@ -34,16 +34,30 @@ pub mod __buffa { #[doc(inline)] pub use self::__buffa::view::CreateEventRequestView; #[doc(inline)] +pub use self::__buffa::view::CreateEventRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::CreateEventResponseView; #[doc(inline)] +pub use self::__buffa::view::CreateEventResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::EventView; #[doc(inline)] +pub use self::__buffa::view::EventOwnedView; +#[doc(inline)] pub use self::__buffa::view::CalculateDurationRequestView; #[doc(inline)] +pub use self::__buffa::view::CalculateDurationRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::CalculateDurationResponseView; #[doc(inline)] +pub use self::__buffa::view::CalculateDurationResponseOwnedView; +#[doc(inline)] pub use self::__buffa::view::ProcessMetadataRequestView; #[doc(inline)] +pub use self::__buffa::view::ProcessMetadataRequestOwnedView; +#[doc(inline)] pub use self::__buffa::view::ProcessMetadataResponseView; #[doc(inline)] +pub use self::__buffa::view::ProcessMetadataResponseOwnedView; +#[doc(inline)] pub use self::__buffa::register_types; diff --git a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.wkt.__view.rs b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.wkt.__view.rs index d17b441..840eaed 100644 --- a/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.wkt.__view.rs +++ b/examples/multiservice/src/generated/buffa/anthropic.connectrpc.wkt.v1.wkt.__view.rs @@ -300,6 +300,142 @@ impl ::buffa::ViewReborrow for CreateEventRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `CreateEventRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`CreateEventRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`CreateEventRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct CreateEventRequestOwnedView( + ::buffa::OwnedView>, +); +impl CreateEventRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CreateEventRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CreateEventRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::CreateEventRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CreateEventRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`CreateEventRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &CreateEventRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::CreateEventRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Name of the event. + /// + /// Field 1: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// When the event occurred. If not provided, server uses current time. + /// + /// Field 2: `occurred_at` + #[must_use] + pub fn occurred_at( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::TimestampView<'_>, + > { + &self.0.reborrow().occurred_at + } + /// How long the event lasted. + /// + /// Field 3: `duration` + #[must_use] + pub fn duration( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::DurationView<'_>, + > { + &self.0.reborrow().duration + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for CreateEventRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + CreateEventRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: CreateEventRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for CreateEventRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::CreateEventRequest { + type View<'a> = CreateEventRequestView<'a>; + type ViewHandle = CreateEventRequestOwnedView; +} +impl ::serde::Serialize for CreateEventRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// CreateEventResponse is the response for CreateEvent. #[derive(Clone, Debug, Default)] pub struct CreateEventResponseView<'a> { @@ -508,6 +644,122 @@ impl ::buffa::ViewReborrow for CreateEventResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `CreateEventResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`CreateEventResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`CreateEventResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct CreateEventResponseOwnedView( + ::buffa::OwnedView>, +); +impl CreateEventResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CreateEventResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CreateEventResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::CreateEventResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CreateEventResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`CreateEventResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &CreateEventResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::CreateEventResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// The created event. + /// + /// Field 1: `event` + #[must_use] + pub fn event( + &self, + ) -> &::buffa::MessageFieldView> { + &self.0.reborrow().event + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for CreateEventResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + CreateEventResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: CreateEventResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for CreateEventResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::CreateEventResponse { + type View<'a> = CreateEventResponseView<'a>; + type ViewHandle = CreateEventResponseOwnedView; +} +impl ::serde::Serialize for CreateEventResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// Event represents an event with timing information. #[derive(Clone, Debug, Default)] pub struct EventView<'a> { @@ -896,6 +1148,149 @@ impl ::buffa::ViewReborrow for EventView<'static> { this } } +/** Self-contained, `'static` owned view of a `Event` message. + + Wraps [`::buffa::OwnedView`]`<`[`EventView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`EventView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct EventOwnedView(::buffa::OwnedView>); +impl EventOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok(EventOwnedView(::buffa::OwnedView::decode(bytes)?)) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + EventOwnedView(::buffa::OwnedView::decode_with_options(bytes, opts)?), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::Event, + ) -> ::core::result::Result { + ::core::result::Result::Ok(EventOwnedView(::buffa::OwnedView::from_owned(msg)?)) + } + /// Borrow the full [`EventView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &EventView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::Event { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Unique identifier for the event. + /// + /// Field 1: `id` + #[must_use] + pub fn id(&self) -> &'_ str { + self.0.reborrow().id + } + /// Name of the event. + /// + /// Field 2: `name` + #[must_use] + pub fn name(&self) -> &'_ str { + self.0.reborrow().name + } + /// When the event occurred. + /// + /// Field 3: `occurred_at` + #[must_use] + pub fn occurred_at( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::TimestampView<'_>, + > { + &self.0.reborrow().occurred_at + } + /// How long the event lasted. + /// + /// Field 4: `duration` + #[must_use] + pub fn duration( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::DurationView<'_>, + > { + &self.0.reborrow().duration + } + /// When the event record was created. + /// + /// Field 5: `created_at` + #[must_use] + pub fn created_at( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::TimestampView<'_>, + > { + &self.0.reborrow().created_at + } +} +impl ::core::convert::From<::buffa::OwnedView>> for EventOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + EventOwnedView(inner) + } +} +impl ::core::convert::From for ::buffa::OwnedView> { + fn from(wrapper: EventOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> for EventOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::Event { + type View<'a> = EventView<'a>; + type ViewHandle = EventOwnedView; +} +impl ::serde::Serialize for EventOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// CalculateDurationRequest is the request for CalculateDuration. #[derive(Clone, Debug, Default)] pub struct CalculateDurationRequestView<'a> { @@ -1168,6 +1563,135 @@ impl ::buffa::ViewReborrow for CalculateDurationRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `CalculateDurationRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`CalculateDurationRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`CalculateDurationRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct CalculateDurationRequestOwnedView( + ::buffa::OwnedView>, +); +impl CalculateDurationRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CalculateDurationRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CalculateDurationRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::CalculateDurationRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CalculateDurationRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`CalculateDurationRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &CalculateDurationRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::CalculateDurationRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Start timestamp. + /// + /// Field 1: `start` + #[must_use] + pub fn start( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::TimestampView<'_>, + > { + &self.0.reborrow().start + } + /// End timestamp. + /// + /// Field 2: `end` + #[must_use] + pub fn end( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::TimestampView<'_>, + > { + &self.0.reborrow().end + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for CalculateDurationRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + CalculateDurationRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: CalculateDurationRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for CalculateDurationRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::CalculateDurationRequest { + type View<'a> = CalculateDurationRequestView<'a>; + type ViewHandle = CalculateDurationRequestOwnedView; +} +impl ::serde::Serialize for CalculateDurationRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// CalculateDurationResponse is the response for CalculateDuration. #[derive(Clone, Debug, Default)] pub struct CalculateDurationResponseView<'a> { @@ -1380,6 +1904,124 @@ impl ::buffa::ViewReborrow for CalculateDurationResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `CalculateDurationResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`CalculateDurationResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`CalculateDurationResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct CalculateDurationResponseOwnedView( + ::buffa::OwnedView>, +); +impl CalculateDurationResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CalculateDurationResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CalculateDurationResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::CalculateDurationResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + CalculateDurationResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`CalculateDurationResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &CalculateDurationResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::CalculateDurationResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Duration between start and end. + /// + /// Field 1: `duration` + #[must_use] + pub fn duration( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::DurationView<'_>, + > { + &self.0.reborrow().duration + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for CalculateDurationResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + CalculateDurationResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: CalculateDurationResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for CalculateDurationResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::CalculateDurationResponse { + type View<'a> = CalculateDurationResponseView<'a>; + type ViewHandle = CalculateDurationResponseOwnedView; +} +impl ::serde::Serialize for CalculateDurationResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// ProcessMetadataRequest is the request for ProcessMetadata. #[derive(Clone, Debug, Default)] pub struct ProcessMetadataRequestView<'a> { @@ -1590,6 +2232,124 @@ impl ::buffa::ViewReborrow for ProcessMetadataRequestView<'static> { this } } +/** Self-contained, `'static` owned view of a `ProcessMetadataRequest` message. + + Wraps [`::buffa::OwnedView`]`<`[`ProcessMetadataRequestView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ProcessMetadataRequestView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ProcessMetadataRequestOwnedView( + ::buffa::OwnedView>, +); +impl ProcessMetadataRequestOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ProcessMetadataRequestOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ProcessMetadataRequestOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ProcessMetadataRequest, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ProcessMetadataRequestOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ProcessMetadataRequestView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ProcessMetadataRequestView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ProcessMetadataRequest { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Arbitrary metadata as a Struct. + /// + /// Field 1: `metadata` + #[must_use] + pub fn metadata( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::StructView<'_>, + > { + &self.0.reborrow().metadata + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ProcessMetadataRequestOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ProcessMetadataRequestOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ProcessMetadataRequestOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ProcessMetadataRequestOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ProcessMetadataRequest { + type View<'a> = ProcessMetadataRequestView<'a>; + type ViewHandle = ProcessMetadataRequestOwnedView; +} +impl ::serde::Serialize for ProcessMetadataRequestOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} /// ProcessMetadataResponse is the response for ProcessMetadata. #[derive(Clone, Debug, Default)] pub struct ProcessMetadataResponseView<'a> { @@ -1837,3 +2597,128 @@ impl ::buffa::ViewReborrow for ProcessMetadataResponseView<'static> { this } } +/** Self-contained, `'static` owned view of a `ProcessMetadataResponse` message. + + Wraps [`::buffa::OwnedView`]`<`[`ProcessMetadataResponseView`]`<'static>>`: the decoded view and the [`::buffa::bytes::Bytes`] buffer it borrows from travel together, so the handle is `'static` and `Send + Sync` — suitable for async handlers, spawned tasks, and anywhere a `'static` bound is required. + + Field accessors return borrows tied to `&self`. Use [`Self::view`] to get the full [`ProcessMetadataResponseView`] when you need struct patterns, iteration helpers, or to pass the view to lifetime-parameterised code.*/ +#[derive(Clone, Debug)] +pub struct ProcessMetadataResponseOwnedView( + ::buffa::OwnedView>, +); +impl ProcessMetadataResponseOwnedView { + /// Decode an owned view from a [`::buffa::bytes::Bytes`] buffer. + /// + /// The view borrows directly from the buffer's data; the buffer is + /// retained inside the returned handle. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer contains invalid + /// protobuf data. + pub fn decode( + bytes: ::buffa::bytes::Bytes, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ProcessMetadataResponseOwnedView(::buffa::OwnedView::decode(bytes)?), + ) + } + /// Decode with custom [`::buffa::DecodeOptions`] (recursion limit, + /// max message size). + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the buffer is invalid or + /// exceeds the configured limits. + pub fn decode_with_options( + bytes: ::buffa::bytes::Bytes, + opts: &::buffa::DecodeOptions, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ProcessMetadataResponseOwnedView( + ::buffa::OwnedView::decode_with_options(bytes, opts)?, + ), + ) + } + /// Build from an owned message via an encode → decode round-trip. + /// + /// # Errors + /// + /// Returns [`::buffa::DecodeError`] if the re-encoded bytes are + /// somehow invalid (should not happen for well-formed messages). + pub fn from_owned( + msg: &super::super::ProcessMetadataResponse, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + ProcessMetadataResponseOwnedView(::buffa::OwnedView::from_owned(msg)?), + ) + } + /// Borrow the full [`ProcessMetadataResponseView`] with its lifetime tied to `&self`. + #[must_use] + pub fn view(&self) -> &ProcessMetadataResponseView<'_> { + self.0.reborrow() + } + /// Convert to the owned message type. + #[must_use] + pub fn to_owned_message(&self) -> super::super::ProcessMetadataResponse { + self.0.to_owned_message() + } + /// The underlying bytes buffer. + #[must_use] + pub fn bytes(&self) -> &::buffa::bytes::Bytes { + self.0.bytes() + } + /// Consume the handle, returning the underlying bytes buffer. + #[must_use] + pub fn into_bytes(self) -> ::buffa::bytes::Bytes { + self.0.into_bytes() + } + /// Echoed metadata with additional server-added fields. + /// + /// Field 1: `metadata` + #[must_use] + pub fn metadata( + &self, + ) -> &::buffa::MessageFieldView< + ::buffa_types::google::protobuf::__buffa::view::StructView<'_>, + > { + &self.0.reborrow().metadata + } + /// Number of fields in the input metadata. + /// + /// Field 2: `field_count` + #[must_use] + pub fn field_count(&self) -> i32 { + self.0.reborrow().field_count + } +} +impl ::core::convert::From<::buffa::OwnedView>> +for ProcessMetadataResponseOwnedView { + fn from(inner: ::buffa::OwnedView>) -> Self { + ProcessMetadataResponseOwnedView(inner) + } +} +impl ::core::convert::From +for ::buffa::OwnedView> { + fn from(wrapper: ProcessMetadataResponseOwnedView) -> Self { + wrapper.0 + } +} +impl ::core::convert::AsRef<::buffa::OwnedView>> +for ProcessMetadataResponseOwnedView { + fn as_ref(&self) -> &::buffa::OwnedView> { + &self.0 + } +} +impl ::buffa::HasMessageView for super::super::ProcessMetadataResponse { + type View<'a> = ProcessMetadataResponseView<'a>; + type ViewHandle = ProcessMetadataResponseOwnedView; +} +impl ::serde::Serialize for ProcessMetadataResponseOwnedView { + fn serialize<__S: ::serde::Serializer>( + &self, + __s: __S, + ) -> ::core::result::Result<__S::Ok, __S::Error> { + ::serde::Serialize::serialize(&self.0, __s) + } +} diff --git a/examples/multiservice/src/generated/connect/anthropic.connectrpc.greet.v1.greet.__connect.rs b/examples/multiservice/src/generated/connect/anthropic.connectrpc.greet.v1.greet.__connect.rs index 1b46cfa..31a1cf0 100644 --- a/examples/multiservice/src/generated/connect/anthropic.connectrpc.greet.v1.greet.__connect.rs +++ b/examples/multiservice/src/generated/connect/anthropic.connectrpc.greet.v1.greet.__connect.rs @@ -35,7 +35,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -53,19 +53,31 @@ pub const GREET_SERVICE_GREET_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::ser /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -78,10 +90,11 @@ pub const GREET_SERVICE_GREET_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::ser /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -90,10 +103,19 @@ pub trait GreetService: Send + Sync + 'static { /// This method has no side effects and supports GET requests. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn greet<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedGreetRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::anthropic::connectrpc::greet::v1::GreetRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -135,10 +157,21 @@ impl GreetServiceExt for S { "Greet", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::anthropic::connectrpc::greet::v1::__buffa::view::GreetRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.greet(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::greet::v1::GreetRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.greet(ctx, sreq) .await? .encode::< crate::proto::anthropic::connectrpc::greet::v1::GreetResponse, @@ -218,9 +251,17 @@ impl ::connectrpc::Dispatcher for GreetServiceServer { "Greet" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::anthropic::connectrpc::greet::v1::__buffa::view::GreetRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::anthropic::connectrpc::greet::v1::GreetRequest, >(request.encoded()?, format)?; + let req: crate::proto::anthropic::connectrpc::greet::v1::__buffa::view::GreetRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::greet::v1::GreetRequest, + >::from_parts(&req, &body); svc.greet(ctx, req) .await? .encode::< @@ -316,11 +357,12 @@ impl ::connectrpc::Dispatcher for GreetServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.greet(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.greet(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -329,6 +371,12 @@ impl ::connectrpc::Dispatcher for GreetServiceServer { /// ```rust,ignore /// let owned = client.greet(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct GreetServiceClient { transport: T, diff --git a/examples/multiservice/src/generated/connect/anthropic.connectrpc.math.v1.math.__connect.rs b/examples/multiservice/src/generated/connect/anthropic.connectrpc.math.v1.math.__connect.rs index bb15ae6..f427a2a 100644 --- a/examples/multiservice/src/generated/connect/anthropic.connectrpc.math.v1.math.__connect.rs +++ b/examples/multiservice/src/generated/connect/anthropic.connectrpc.math.v1.math.__connect.rs @@ -27,7 +27,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -45,19 +45,31 @@ pub const MATH_SERVICE_ADD_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::server /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -70,10 +82,11 @@ pub const MATH_SERVICE_ADD_SPEC: ::connectrpc::Spec = ::connectrpc::Spec::server /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -81,10 +94,19 @@ pub trait MathService: Send + Sync + 'static { /// Add returns the sum of two numbers. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn add<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedAddRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::anthropic::connectrpc::math::v1::AddRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -126,10 +148,21 @@ impl MathServiceExt for S { "Add", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::anthropic::connectrpc::math::v1::__buffa::view::AddRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.add(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::math::v1::AddRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.add(ctx, sreq) .await? .encode::< crate::proto::anthropic::connectrpc::math::v1::AddResponse, @@ -209,9 +242,17 @@ impl ::connectrpc::Dispatcher for MathServiceServer { "Add" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::anthropic::connectrpc::math::v1::__buffa::view::AddRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::anthropic::connectrpc::math::v1::AddRequest, >(request.encoded()?, format)?; + let req: crate::proto::anthropic::connectrpc::math::v1::__buffa::view::AddRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::math::v1::AddRequest, + >::from_parts(&req, &body); svc.add(ctx, req) .await? .encode::< @@ -307,11 +348,12 @@ impl ::connectrpc::Dispatcher for MathServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.add(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.add(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -320,6 +362,12 @@ impl ::connectrpc::Dispatcher for MathServiceServer { /// ```rust,ignore /// let owned = client.add(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct MathServiceClient { transport: T, diff --git a/examples/multiservice/src/generated/connect/anthropic.connectrpc.wkt.v1.wkt.__connect.rs b/examples/multiservice/src/generated/connect/anthropic.connectrpc.wkt.v1.wkt.__connect.rs index 6fdfb78..3a3de0e 100644 --- a/examples/multiservice/src/generated/connect/anthropic.connectrpc.wkt.v1.wkt.__connect.rs +++ b/examples/multiservice/src/generated/connect/anthropic.connectrpc.wkt.v1.wkt.__connect.rs @@ -59,7 +59,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -87,7 +87,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } impl ::connectrpc::Encodable< @@ -115,7 +115,7 @@ for ::buffa::view::OwnedView< &self, codec: ::connectrpc::CodecFormat, ) -> ::std::result::Result<::buffa::bytes::Bytes, ::connectrpc::ConnectError> { - ::connectrpc::__codegen::encode_view_body(&**self, codec) + ::connectrpc::__codegen::encode_view_body(self.reborrow(), codec) } } /// Full service name for this service. @@ -151,19 +151,31 @@ pub const WELL_KNOWN_TYPES_SERVICE_PROCESS_METADATA_SPEC: ::connectrpc::Spec = : /// /// # Implementing handlers /// -/// Handlers receive requests as `OwnedFooView` (an alias for -/// `OwnedView>`), which gives zero-copy borrowed access -/// to fields (e.g. `request.name` is a `&str` into the decoded buffer). -/// The view can be held across `.await` points. When two RPC types in -/// the same package would alias to the same `Owned<…>View` name (e.g. -/// a local message plus an imported one with the same short name), the -/// alias is suppressed for both and the request type is spelled as -/// `OwnedView<…View<'static>>` directly in the trait signature. -/// /// Implement methods with plain `async fn`; the returned future satisfies -/// the `Send` bound automatically. See the -/// [buffa user guide](https://github.com/anthropics/buffa/blob/main/docs/guide.md#ownedview-in-async-trait-implementations) -/// for zero-copy access patterns and when `to_owned_message()` is needed. +/// the `Send` bound automatically. +/// +/// **Unary and server-streaming requests** arrive as +/// [`ServiceRequest<'_, Req>`](::connectrpc::ServiceRequest): a zero-copy +/// view of the request plus its body, valid for the duration of the call. +/// Fields are read directly (`request.name` is a `&str` into the decoded +/// buffer) and the borrow may be held across `.await` points. Anything +/// that must outlive the call — `tokio::spawn`, channels, server state, +/// or data captured by a returned response stream — takes owned data: +/// call `request.to_owned_message()` (or copy the specific fields) +/// first. +/// +/// **Client-streaming and bidi requests** arrive as +/// `ServiceStream<`[`StreamMessage`](::connectrpc::StreamMessage)`>`. +/// Each item owns its decoded buffer and is `Send + 'static`, so items +/// can be buffered or moved into spawned tasks; read fields zero-copy +/// through the generated accessor methods (`item.name()`) or `.view()`, +/// convert with `.to_owned_message()`, or yield an item back unchanged — +/// `StreamMessage` implements `Encodable`. +/// +/// Request types resolved through `extern_path` (e.g. well-known types +/// from another crate) use the same wrappers; the crate that owns the +/// type must be generated with buffa ≥ 0.7.0 and views enabled so the +/// backing `HasMessageView` impl exists. /// /// The `impl Encodable` return bound accepts the owned `Out`, the /// generated `OutView<'_>` / `OwnedOutView`, @@ -176,10 +188,11 @@ pub const WELL_KNOWN_TYPES_SERVICE_PROCESS_METADATA_SPEC: ::connectrpc::Spec = : /// /// Server-streaming and bidi-streaming methods return /// `ServiceStream + Send + use>`. The -/// `use` precise-capturing clause excludes `&self`'s lifetime -/// (unary methods use `use<'a, Self>` and may borrow), so stream items -/// must be `'static`. To stream view-encoded data, encode each item -/// inside the stream body and yield +/// `use` precise-capturing clause excludes `&self`'s lifetime and +/// the request's lifetime (unary methods use `use<'a, Self>` and may +/// borrow from `&self`), so stream items must be `'static` and cannot +/// borrow from the request. To stream view-encoded data, encode each +/// item inside the stream body and yield /// [`PreEncoded`](::connectrpc::PreEncoded) — see its `# Streaming /// example` doc. #[allow(clippy::type_complexity)] @@ -187,10 +200,19 @@ pub trait WellKnownTypesService: Send + Sync + 'static { /// CreateEvent creates an event with a timestamp. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn create_event<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedCreateEventRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::anthropic::connectrpc::wkt::v1::CreateEventRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -201,10 +223,19 @@ pub trait WellKnownTypesService: Send + Sync + 'static { /// CalculateDuration calculates the duration between two timestamps. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn calculate_duration<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedCalculateDurationRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::anthropic::connectrpc::wkt::v1::CalculateDurationRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -215,10 +246,19 @@ pub trait WellKnownTypesService: Send + Sync + 'static { /// ProcessMetadata processes arbitrary metadata as a Struct. /// /// `'a` lets the response body borrow from `&self` (e.g. server-resident state). + /// + /// `request` is borrowed from the request body and is valid for the + /// duration of the call; message fields are read directly on it + /// (zero-copy). The response cannot borrow from `request` — use + /// `.to_owned_message()` (or copy the specific fields) for anything + /// returned, stored, or moved into `tokio::spawn`. fn process_metadata<'a>( &'a self, ctx: ::connectrpc::RequestContext, - request: OwnedProcessMetadataRequestView, + request: ::connectrpc::ServiceRequest< + '_, + crate::proto::anthropic::connectrpc::wkt::v1::ProcessMetadataRequest, + >, ) -> impl ::std::future::Future< Output = ::connectrpc::ServiceResult< impl ::connectrpc::Encodable< @@ -260,10 +300,21 @@ impl WellKnownTypesServiceExt for S { "CreateEvent", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::CreateEventRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.create_event(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::wkt::v1::CreateEventRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.create_event(ctx, sreq) .await? .encode::< crate::proto::anthropic::connectrpc::wkt::v1::CreateEventResponse, @@ -278,10 +329,21 @@ impl WellKnownTypesServiceExt for S { "CalculateDuration", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::CalculateDurationRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.calculate_duration(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::wkt::v1::CalculateDurationRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.calculate_duration(ctx, sreq) .await? .encode::< crate::proto::anthropic::connectrpc::wkt::v1::CalculateDurationResponse, @@ -296,10 +358,21 @@ impl WellKnownTypesServiceExt for S { "ProcessMetadata", { let svc = ::std::sync::Arc::clone(&self); - ::connectrpc::view_handler_fn(move |ctx, req, format| { + ::connectrpc::view_handler_fn(move | + ctx, + req: ::buffa::view::OwnedView< + crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::ProcessMetadataRequestView< + 'static, + >, + >, + format| + { let svc = ::std::sync::Arc::clone(&svc); async move { - svc.process_metadata(ctx, req) + let sreq = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::wkt::v1::ProcessMetadataRequest, + >::from_parts(req.reborrow(), req.bytes()); + svc.process_metadata(ctx, sreq) .await? .encode::< crate::proto::anthropic::connectrpc::wkt::v1::ProcessMetadataResponse, @@ -393,9 +466,17 @@ for WellKnownTypesServiceServer { "CreateEvent" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::CreateEventRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::anthropic::connectrpc::wkt::v1::CreateEventRequest, >(request.encoded()?, format)?; + let req: crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::CreateEventRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::wkt::v1::CreateEventRequest, + >::from_parts(&req, &body); svc.create_event(ctx, req) .await? .encode::< @@ -406,9 +487,17 @@ for WellKnownTypesServiceServer { "CalculateDuration" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::CalculateDurationRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::anthropic::connectrpc::wkt::v1::CalculateDurationRequest, >(request.encoded()?, format)?; + let req: crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::CalculateDurationRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::wkt::v1::CalculateDurationRequest, + >::from_parts(&req, &body); svc.calculate_duration(ctx, req) .await? .encode::< @@ -419,9 +508,17 @@ for WellKnownTypesServiceServer { "ProcessMetadata" => { let svc = ::std::sync::Arc::clone(&self.inner); Box::pin(async move { - let req = ::connectrpc::dispatcher::codegen::decode_request_view::< - crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::ProcessMetadataRequestView, + let body = ::connectrpc::dispatcher::codegen::unary_request_proto_bytes::< + crate::proto::anthropic::connectrpc::wkt::v1::ProcessMetadataRequest, >(request.encoded()?, format)?; + let req: crate::proto::anthropic::connectrpc::wkt::v1::__buffa::view::ProcessMetadataRequestView< + '_, + > = ::connectrpc::dispatcher::codegen::decode_borrowed_request_view( + &body, + )?; + let req = ::connectrpc::ServiceRequest::< + crate::proto::anthropic::connectrpc::wkt::v1::ProcessMetadataRequest, + >::from_parts(&req, &body); svc.process_metadata(ctx, req) .await? .encode::< @@ -517,11 +614,12 @@ for WellKnownTypesServiceServer { /// # Working with the response /// /// Unary calls return [`UnaryResponse>`](::connectrpc::client::UnaryResponse). -/// The `OwnedView` derefs to the view, so field access is zero-copy: +/// [`view()`](::connectrpc::client::UnaryResponse::view) borrows the response +/// message, so field access is zero-copy: /// /// ```rust,ignore -/// let resp = client.create_event(request).await?.into_view(); -/// let name: &str = resp.name; // borrow into the response buffer +/// let resp = client.create_event(request).await?; +/// let name: &str = resp.view().name; // borrow into the response buffer /// ``` /// /// If you need the owned struct (e.g. to store or pass by value), use @@ -530,6 +628,12 @@ for WellKnownTypesServiceServer { /// ```rust,ignore /// let owned = client.create_event(request).await?.into_owned(); /// ``` +/// +/// [`into_view()`](::connectrpc::client::UnaryResponse::into_view) keeps the +/// zero-copy decoded body (an `OwnedView`) without copying; field access on it +/// goes through `.reborrow()`. Streaming responses yield one `OwnedView` per +/// received message from `.message().await` — bind `msg.reborrow()` for field +/// access, or convert with `.to_owned_message()`. #[derive(Clone)] pub struct WellKnownTypesServiceClient { transport: T, diff --git a/tests/streaming/src/lib.rs b/tests/streaming/src/lib.rs index 4a73186..b2b0204 100644 --- a/tests/streaming/src/lib.rs +++ b/tests/streaming/src/lib.rs @@ -11,14 +11,13 @@ mod tests { use connectrpc::client::{ClientConfig, ClientTransport, HttpClient}; use connectrpc::{ - ConnectError, ConnectRpcService, RequestContext, Response, Router, ServiceResult, - ServiceStream, + ConnectError, ConnectRpcService, RequestContext, Response, Router, ServiceRequest, + ServiceResult, ServiceStream, StreamMessage, }; use futures::StreamExt; use tokio::net::TcpListener; use super::*; - use buffa::view::OwnedView; const MSG_DELAY: Duration = Duration::from_millis(100); @@ -29,12 +28,37 @@ mod tests { async fn echo( &self, _ctx: RequestContext, - request: OwnedView>, + request: ServiceRequest<'_, EchoRequest>, ) -> ServiceResult { - let request = request.to_owned_message(); + // Borrowed request view: plain field access, with the borrow tied + // to the dispatcher-owned request body — no owned round-trip. + // + // This handler also exercises the async shapes that matter for the + // borrowed-request design (every existing unary test runs through + // it, on both the Router and the monomorphic dispatcher): + // + // 1. The borrow is held across an await point: `request` is read + // *after* the yield, so the handler future captures the borrow + // across the suspension and must still satisfy the trait's + // `Send` bound. + tokio::task::yield_now().await; + + // 2. Inner async blocks may borrow the request freely as long as + // they are awaited inside the handler (they are not 'static). + let data = async { request.data.to_owned() }.await; + + // 3. Anything that needs 'static — tokio::spawn, channels, state — + // takes owned data: convert (or copy fields) first, then move + // the owned value into the task. Capturing `request` itself in + // a spawned task does not compile. + let owned = request.to_owned_message(); + let sequence = tokio::spawn(async move { owned.sequence }) + .await + .expect("spawned background task"); + Response::ok(EchoResponse { - sequence: request.sequence, - data: request.data, + sequence, + data, ..Default::default() }) } @@ -42,9 +66,10 @@ mod tests { async fn server_stream( &self, _ctx: RequestContext, - request: OwnedView>, + request: ServiceRequest<'_, EchoRequest>, ) -> ServiceResult> { - let request = request.to_owned_message(); + // Borrowed request: copy out the one field the returned stream + // needs (the stream must be 'static and cannot borrow `request`). let count = request.sequence; let stream = futures::stream::unfold(0, move |i| async move { if i >= count { @@ -68,14 +93,16 @@ mod tests { async fn client_stream( &self, _ctx: RequestContext, - mut requests: ServiceStream>>, + mut requests: ServiceStream>, ) -> ServiceResult { let mut count = 0i32; let mut parts = Vec::new(); while let Some(req) = requests.next().await { - let req = req?.to_owned_message(); + // Per-item zero-copy reads via the generated accessor methods + // (Deref to `EchoRequestOwnedView`); copy out only what is kept. + let req = req?; count += 1; - parts.push(req.data); + parts.push(req.data().to_owned()); } Response::ok(EchoResponse { sequence: count, @@ -87,10 +114,11 @@ mod tests { async fn bidi_stream( &self, _ctx: RequestContext, - requests: ServiceStream>>, + mut requests: ServiceStream>, ) -> ServiceResult> { - // Map stream to owned types before spawning to satisfy Send bounds - let mut requests = Box::pin(requests.map(|r| r.map(|v| v.to_owned_message()))); + // `StreamMessage` items are Send + 'static, so the stream can be + // moved into a spawned task and read zero-copy there — no + // map-to-owned pass is needed any more. // Echo each request back immediately via an mpsc channel. let (tx, rx) = tokio::sync::mpsc::channel::>(1); tokio::spawn(async move { @@ -98,8 +126,8 @@ mod tests { match req { Ok(req) => { let resp = EchoResponse { - sequence: req.sequence, - data: req.data, + sequence: req.sequence(), + data: req.data().to_owned(), ..Default::default() }; if tx.send(Ok(resp)).await.is_err() { @@ -167,9 +195,8 @@ mod tests { }) .await .unwrap(); - let msg = resp.into_view(); - assert_eq!(msg.sequence, 42); - assert_eq!(msg.data, "hello"); + assert_eq!(resp.view().sequence, 42); + assert_eq!(resp.view().data, "hello"); } /// Documents the three ways to access a unary response, in order of @@ -186,22 +213,21 @@ mod tests { ..Default::default() }; - // Pattern 1: borrow the view via `.view()`. Zero-copy. Use this for - // simple assertions when you also need headers/trailers — `OwnedView` - // derefs to the view, so field access (`.sequence`, `.data` → &str) - // works directly. + // Pattern 1: borrow the message via `.view()`. Zero-copy field access + // (`.sequence`, `.data` → &str), and headers/trailers stay available. + // This is the default for reading a response. let resp = client.echo(req()).await.unwrap(); assert_eq!(resp.view().sequence, 7); assert_eq!(resp.view().data, "test"); // Headers/trailers are still available. let _ = resp.headers(); - // Pattern 2: consume via `.into_view()` to get the `OwnedView`. - // Still zero-copy (Deref-based field access), but discards headers/ - // trailers. Use this when you only care about the body. + // Pattern 2: consume via `.into_view()` to keep the decoded body + // (an `OwnedView`) without copying — e.g. to stash it or send it to + // another task. Field access goes through `.reborrow()`. let msg = client.echo(req()).await.unwrap().into_view(); - assert_eq!(msg.sequence, 7); - assert_eq!(msg.data, "test"); // &str via Deref — no allocation + assert_eq!(msg.reborrow().sequence, 7); + assert_eq!(msg.reborrow().data, "test"); // &str, no allocation // Pattern 3: `.into_owned()` to get the owned struct. Allocates and // copies all string/bytes fields. Only needed when you want the @@ -232,7 +258,7 @@ mod tests { while let Some(msg) = stream.message().await.unwrap() { let elapsed = start.elapsed(); - received.push((msg.sequence, elapsed)); + received.push((msg.reborrow().sequence, elapsed)); } assert_eq!(received.len(), num_messages as usize); @@ -297,8 +323,8 @@ mod tests { let resp = client.client_stream(messages).await.unwrap(); let msg = resp.into_view(); - assert_eq!(msg.sequence, 5); - assert_eq!(msg.data, "msg-0,msg-1,msg-2,msg-3,msg-4"); + assert_eq!(msg.reborrow().sequence, 5); + assert_eq!(msg.reborrow().data, "msg-0,msg-1,msg-2,msg-3,msg-4"); } #[tokio::test] @@ -312,8 +338,8 @@ mod tests { .unwrap(); let msg = resp.into_view(); - assert_eq!(msg.sequence, 0); - assert_eq!(msg.data, ""); + assert_eq!(msg.reborrow().sequence, 0); + assert_eq!(msg.reborrow().data, ""); } /// Regression: `call_client_stream` must stream the request body @@ -495,7 +521,7 @@ mod tests { }) .await .unwrap(); - assert_eq!(resp.into_view().data, "mono-unary"); + assert_eq!(resp.view().data, "mono-unary"); // Server streaming let mut stream = client @@ -521,7 +547,7 @@ mod tests { }) .collect(); let resp = client.client_stream(messages).await.unwrap(); - assert_eq!(resp.into_view().sequence, 4); + assert_eq!(resp.view().sequence, 4); // NotFound — wrong path should produce Unimplemented, not panic. // Use the raw HTTP client to hit a nonexistent method. @@ -550,12 +576,13 @@ mod tests { async fn echo( &self, _ctx: RequestContext, - request: OwnedView>, + request: ServiceRequest<'_, EchoRequest>, ) -> ServiceResult { - let request = request.to_owned_message(); + // Borrowed request view: plain field access, with the borrow tied + // to the dispatcher-owned request body — no owned round-trip. Response::ok(EchoResponse { sequence: request.sequence, - data: request.data, + data: request.data.to_owned(), ..Default::default() }) } @@ -563,7 +590,7 @@ mod tests { async fn server_stream( &self, _ctx: RequestContext, - request: OwnedView>, + request: ServiceRequest<'_, EchoRequest>, ) -> ServiceResult>> { let count = request.sequence; let stream = futures::stream::unfold(0, move |i| async move { @@ -588,7 +615,7 @@ mod tests { async fn client_stream( &self, _ctx: RequestContext, - mut requests: ServiceStream>>, + mut requests: ServiceStream>, ) -> ServiceResult { let mut count = 0i32; while requests.next().await.is_some() { @@ -604,7 +631,7 @@ mod tests { async fn bidi_stream( &self, _ctx: RequestContext, - mut requests: ServiceStream>>, + mut requests: ServiceStream>, ) -> ServiceResult>> { // Echo each request back as a `PreEncoded` item — same // build-view-encode-yield-bytes pattern as `server_stream`, @@ -616,9 +643,9 @@ mod tests { while let Some(req) = requests.next().await { match req { Ok(req) => { - let data = format!("bidi-{}", req.data); + let data = format!("bidi-{}", req.view().data); let view = EchoResponseView { - sequence: req.sequence, + sequence: req.view().sequence, data: &data, ..Default::default() }; @@ -669,7 +696,7 @@ mod tests { let mut got = Vec::new(); while let Some(msg) = stream.message().await.unwrap() { - got.push((msg.sequence, msg.data.to_string())); + got.push((msg.reborrow().sequence, msg.reborrow().data.to_string())); } assert_eq!( got, @@ -791,8 +818,8 @@ mod tests { .await .unwrap(); let msg = resp.into_view(); - assert_eq!(msg.sequence, 7); - assert_eq!(msg.data, "h2-direct"); + assert_eq!(msg.reborrow().sequence, 7); + assert_eq!(msg.reborrow().data, "h2-direct"); // Lazy connect variant — first request triggers the handshake. let lazy = Http2Connection::lazy_plaintext(uri.clone()).shared(64); @@ -805,7 +832,7 @@ mod tests { }) .await .unwrap(); - assert_eq!(resp.into_view().data, "h2-lazy"); + assert_eq!(resp.view().data, "h2-lazy"); // Concurrent requests on the shared handle — exercises the Buffer. let mut handles = Vec::new(); @@ -826,7 +853,7 @@ mod tests { } for (i, h) in handles.into_iter().enumerate() { let msg = h.await.unwrap().unwrap(); - assert_eq!(msg.sequence, i as i32); + assert_eq!(msg.reborrow().sequence, i as i32); } } @@ -874,7 +901,10 @@ mod tests { let mut received = 0; while let Some(resp) = stream.message().await.unwrap() { - assert_eq!(resp.data, format!("half-duplex-{}", resp.sequence)); + assert_eq!( + resp.reborrow().data, + format!("half-duplex-{}", resp.reborrow().sequence) + ); received += 1; } assert_eq!(received, 40); @@ -972,8 +1002,8 @@ mod tests { .await .unwrap(); let msg = resp.into_view(); - assert_eq!(msg.sequence, 1); - assert_eq!(msg.data, "tls-hello"); + assert_eq!(msg.reborrow().sequence, 1); + assert_eq!(msg.reborrow().data, "tls-hello"); } /// End-to-end TLS round-trip using Http2Connection::connect_tls. @@ -1008,8 +1038,8 @@ mod tests { .await .unwrap(); let msg = resp.into_view(); - assert_eq!(msg.sequence, 2); - assert_eq!(msg.data, "tls-h2-hello"); + assert_eq!(msg.reborrow().sequence, 2); + assert_eq!(msg.reborrow().data, "tls-h2-hello"); } /// Http2Connection::connect_tls must fail when the server doesn't @@ -1148,7 +1178,7 @@ mod tests { async fn echo( &self, ctx: RequestContext, - request: OwnedView>, + request: ServiceRequest<'_, EchoRequest>, ) -> ServiceResult { let proto = ctx .protocol() @@ -1171,7 +1201,7 @@ mod tests { async fn server_stream( &self, _ctx: RequestContext, - _request: OwnedView>, + _request: ServiceRequest<'_, EchoRequest>, ) -> ServiceResult> { unimplemented!() } @@ -1179,7 +1209,7 @@ mod tests { async fn client_stream( &self, _ctx: RequestContext, - _requests: ServiceStream>>, + _requests: ServiceStream>, ) -> ServiceResult { unimplemented!() } @@ -1187,7 +1217,7 @@ mod tests { async fn bidi_stream( &self, _ctx: RequestContext, - _requests: ServiceStream>>, + _requests: ServiceStream>, ) -> ServiceResult> { unimplemented!() } @@ -1259,7 +1289,7 @@ mod tests { ); assert_eq!(resp.headers().get("x-req-data").unwrap(), "ping"); // The handler echoes `sequence`; the interceptor adds 1000. - assert_eq!(resp.into_view().sequence, 1007); + assert_eq!(resp.view().sequence, 1007); } /// End-to-end: a registered streaming interceptor wraps server-streaming, @@ -1341,11 +1371,7 @@ mod tests { resp.headers().get("x-stream-intercepted").unwrap(), "/test.echo.v1.EchoService/ClientStream" ); - assert_eq!( - resp.into_view().sequence, - 2, - "all items must reach the handler" - ); + assert_eq!(resp.view().sequence, 2, "all items must reach the handler"); // Bidi streaming: N requests ↔ N responses (gRPC, full duplex). { @@ -1462,6 +1488,7 @@ mod tests { .await .unwrap() .into_view() + .reborrow() .data .to_owned() }