Skip to main content

Encodable

Trait Encodable 

Source
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 M itself (blanket M: Message + JsonSerialize below);
  • MView<'_> and OwnedView<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);
  • PreEncoded for handlers that encode a non-'static view 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§

Source

fn encode(&self, codec: CodecFormat) -> Result<Bytes, ConnectError>

Encode self as wire bytes for M in the requested format.

Provided Methods§

Source

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§

Source§

impl<M, V> Encodable<M> for MaybeBorrowed<M, V>
where M: Encodable<M>, V: Encodable<M>,

Source§

impl<M: Message + JsonSerialize> Encodable<M> for M

Source§

impl<M: Message + JsonSerialize> Encodable<M> for PreEncoded<M>

Source§

impl<M> Encodable<M> for StreamMessage<M>

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.