pub trait Encodable<M> {
// Required method
fn encode(&self, codec: CodecFormat) -> Result<Bytes, ConnectError>;
// Provided method
fn encode_segments(
&self,
codec: CodecFormat,
) -> Result<EncodedBody, ConnectError> { ... }
}Expand description
Encodes to the same wire bytes as proto message M.
This is the bound on the response body in generated trait methods. Provided implementations:
- the owned
Mitself (blanketM: Message + JsonSerializebelow); MView<'_>andOwnedView<MView<'static>>, emitted by codegen per RPC output type;MaybeBorrowed<M, V>for handlers that conditionally return either;StreamMessage<M>for echoing inbound stream items back out (re-encodes from the retained wire bytes);PreEncodedfor handlers that encode a non-'staticview internally and pass the bytes across the handler boundary.
§Contract
Implementations must produce bytes that decode as a valid M in
the given format.
encode is fallible: the owned-message impl never errors. The
view-body impls are proto-only (view types lack Serialize) and return
ErrorCode::Unimplemented for
CodecFormat::Json. PreEncoded supports both codecs but the JSON
path is a slow fallback (decode + re-serialize) — see its
# Codec behaviour doc.
Required Methods§
Sourcefn encode(&self, codec: CodecFormat) -> Result<Bytes, ConnectError>
fn encode(&self, codec: CodecFormat) -> Result<Bytes, ConnectError>
Encode self as wire bytes for M in the requested format.
Provided Methods§
Sourcefn encode_segments(
&self,
codec: CodecFormat,
) -> Result<EncodedBody, ConnectError>
fn encode_segments( &self, codec: CodecFormat, ) -> Result<EncodedBody, ConnectError>
Encode self as wire bytes that may arrive in several reference-counted
segments rather than one contiguous buffer.
Concatenating the segments yields exactly what encode
would have returned, so this is an optimization and never a wire-format
difference. A payload the encoder can hand over by reference count — a
large bytes::Bytes field, or a view field borrowed from the buffer the
view was decoded from — becomes its own segment instead of being copied
into the output.
The default implementation returns encode’s single
buffer, which is always correct. Overriding it is worthwhile only for a
body that can carry a large payload by reference; a body whose fields
are String or Vec<u8> has nothing to hand over, and segmenting it
would add the rope’s cost for no saving.
How large a payload has to be before it earns its own segment is the
framing layer’s decision, not the implementation’s — anything smaller
is copied into the framing buffer downstream regardless, so a smaller
threshold spends effort without saving a copy. Implementations that
need to encode a view should call
__codegen::encode_view_body_segments,
which applies that threshold for them.
§Errors
Same conditions as encode.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl<M, V> Encodable<M> for MaybeBorrowed<M, V>
impl<M: Message + JsonSerialize> Encodable<M> for M
impl<M: Message + JsonSerialize> Encodable<M> for PreEncoded<M>
impl<M> Encodable<M> for StreamMessage<M>where
M: HasMessageView + JsonSerialize,
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.