Skip to main content

protosocket/
encoding.rs

1use crate::{DeserializeError, Serialize};
2
3/// A codec combines an encoder and decoder for a message type.
4///
5/// You can make a codec via a tuple of `(Encoder, Decoder)` or
6/// by implementing one yourself.
7///
8/// ## Buffer lifecycles
9/// The lifecycle of a message, with respect to encoding and decoding, is:
10///
11/// ### 1 decode
12/// `Decoder::decode()` produces a Message from inbound bytes.
13/// If you want to reuse allocations, you can pull from your own pool in here.
14///
15/// ### 2 your application process
16/// If you want to reuse the decoder memory later, you will either need to use
17/// a smart pointer on Drop, or you will need to carry the buffer into your
18/// logical response message type. This way, it can be delivered back to the
19/// Codec via `Encoder::encode()` later.
20///
21/// ### 3 encode
22/// `Encoder::encode()` produces outbound bytes from a logical Message. This is
23/// where you can return decoder buffers to your pool, if you carried them through.
24///
25/// ### 4 buffer return
26/// After the encoded bytes are sent, `Encoder::return_buffer()` is called with
27/// the serialized buffer. You can reuse or drop it as appropriate.
28///
29/// ## About pooling
30/// The Encoder's encode->return_buffer cycle is independent of the Decoder's lifecycle.
31/// Pooling for the Encoder is easy, and you should totally do it. `protosocket`
32/// provides a `PooledEncoder` wrapper and a `Serialize` trait you can use for the easiest
33/// way to pool your outbound buffer allocations.
34///
35/// Decoder pooling is more application-specific, and depends very much on your encoding and
36/// application types for its usefulness, so you will need to implement it yourself.
37pub trait Codec: Encoder + Decoder {}
38
39impl<E, D> Codec for (E, D)
40where
41    E: Encoder,
42    D: Decoder,
43{
44}
45impl<E, D> Encoder for (E, D)
46where
47    E: Encoder,
48    D: Decoder,
49{
50    type Message = E::Message;
51    type Serialized = E::Serialized;
52    fn encode(&mut self, message: Self::Message) -> Self::Serialized {
53        self.0.encode(message)
54    }
55
56    fn return_buffer(&mut self, buffer: Self::Serialized) {
57        self.0.return_buffer(buffer);
58    }
59}
60impl<E, D> Decoder for (E, D)
61where
62    E: Encoder,
63    D: Decoder,
64{
65    type Message = D::Message;
66    fn decode(
67        &mut self,
68        buffer: impl bytes::Buf,
69    ) -> std::result::Result<(usize, Self::Message), DeserializeError> {
70        self.1.decode(buffer)
71    }
72}
73
74/// An encoder takes messages and produces outbound bytes.
75pub trait Encoder {
76    /// The message type consumed by this serializer.
77    type Message;
78
79    /// The type this serializer produces.
80    ///
81    /// If you want to write to raw vectors, consider wrapping your serializer
82    /// with [PooledEncoder] and using that instead.
83    type Serialized: bytes::Buf;
84
85    /// Encode a message into a buffer.
86    fn encode(&mut self, message: Self::Message) -> Self::Serialized;
87
88    /// Buffers are sent back to the encoder once the message is sent.
89    /// Buffers are not guaranteed to be advanced to the end.
90    /// You can reset and reuse your buffer, if appropriate.
91    fn return_buffer(&mut self, _buffer: Self::Serialized) {
92        // drop by default
93    }
94}
95
96/// A decoder takes inbound bytes and produces messages.
97pub trait Decoder {
98    /// The message type produced by this deserializer.
99    type Message;
100
101    /// Decode a message from the buffer, or tell why you can't.
102    ///
103    /// You must not consume more bytes than the message you produce.
104    fn decode(
105        &mut self,
106        buffer: impl bytes::Buf,
107    ) -> std::result::Result<(usize, Self::Message), DeserializeError>;
108}
109
110impl<T> Encoder for T
111where
112    T: Serialize,
113{
114    type Message = T::Message;
115    type Serialized = OwnedBuffer;
116
117    #[cfg_attr(
118        feature = "tracing",
119        tracing::instrument(skip_all, name = "raw_serialize")
120    )]
121    fn encode(&mut self, message: Self::Message) -> Self::Serialized {
122        let mut buffer = Vec::new();
123        self.serialize_into_buffer(message, &mut buffer);
124        OwnedBuffer::new(buffer)
125    }
126}
127
128/// A basic Buf wrapper for a byte array. This works for simple apis, but if you
129/// have latency, memory, or cpu constraints, you should be using PooledEncoder
130/// or another more sophisticated memory reuse mechanism.
131pub struct OwnedBuffer {
132    buffer: Vec<u8>,
133    cursor: usize,
134}
135impl OwnedBuffer {
136    fn new(buffer: Vec<u8>) -> Self {
137        Self { buffer, cursor: 0 }
138    }
139}
140impl bytes::Buf for OwnedBuffer {
141    #[inline(always)]
142    fn remaining(&self) -> usize {
143        self.buffer.len() - self.cursor
144    }
145
146    #[inline(always)]
147    fn chunk(&self) -> &[u8] {
148        &self.buffer[self.cursor..]
149    }
150
151    #[inline(always)]
152    fn advance(&mut self, cnt: usize) {
153        assert!(
154            self.cursor + cnt <= self.buffer.len(),
155            "can't advance past the end of the buffer"
156        );
157        self.cursor += cnt;
158    }
159}