bilrost/encoding/
message.rs

1use crate::buf::ReverseBuf;
2use crate::encoding::{
3    encode_varint, encoded_len_varint, implement_core_empty_state_rules, prepend_varint,
4    Canonicity, Capped, DecodeContext, DistinguishedValueBorrowDecoder, DistinguishedValueDecoder,
5    EmptyState, ForOverwrite, RestrictedDecodeContext, TagReader, ValueBorrowDecoder, ValueDecoder,
6    ValueEncoder, WireType, Wiretyped,
7};
8use crate::Canonicity::Canonical;
9use crate::DecodeError;
10use alloc::boxed::Box;
11use bytes::{Buf, BufMut};
12
13/// Encoding that performs the actual value-encoding of messages, to and from `RawMessage`-family
14/// traits into length-delineated values on the wire. By default this is directly delegated to by
15/// the general encodings.
16pub struct MessageEncoding;
17
18implement_core_empty_state_rules!(MessageEncoding);
19
20/// Merges fields from the given buffer, to its cap, into the given owned message value.
21/// Implemented as a private standalone method to discourage "merging" as a usage pattern.
22#[inline]
23pub(crate) fn merge<T: RawMessageDecoder, B: Buf + ?Sized>(
24    value: &mut T,
25    mut buf: Capped<B>,
26    ctx: DecodeContext,
27) -> Result<(), DecodeError> {
28    let tr = &mut TagReader::new();
29    let mut last_tag = None::<u32>;
30    while buf.has_remaining()? {
31        let (tag, wire_type) = tr.decode_key(buf.lend())?;
32        let duplicated = last_tag == Some(tag);
33        last_tag = Some(tag);
34        value.raw_decode_field(tag, wire_type, duplicated, buf.lend(), ctx.clone())?;
35    }
36    Ok(())
37}
38
39/// Merges fields from the given buffer, to its cap, into the given distinguished owned message
40/// value. Implemented as a private standalone method to discourage "merging" as a usage pattern.
41#[inline]
42pub(crate) fn merge_distinguished<T: RawDistinguishedMessageDecoder, B: Buf + ?Sized>(
43    value: &mut T,
44    mut buf: Capped<B>,
45    ctx: RestrictedDecodeContext,
46) -> Result<Canonicity, DecodeError> {
47    let tr = &mut TagReader::new();
48    let mut last_tag = None::<u32>;
49    let mut canon = Canonical;
50    while buf.has_remaining()? {
51        let (tag, wire_type) = tr.decode_key(buf.lend())?;
52        let duplicated = last_tag == Some(tag);
53        last_tag = Some(tag);
54        canon.update(value.raw_decode_field_distinguished(
55            tag,
56            wire_type,
57            duplicated,
58            buf.lend(),
59            ctx.clone(),
60        )?);
61    }
62    debug_assert!(
63        canon >= ctx.min_canonicity,
64        "a poorly behaved distinguished decoder did not check canonicity against the context and \
65        convert it into an error"
66    );
67    Ok(canon)
68}
69
70/// Merges fields from the given buffer, to its cap, into the given borrowed message value.
71/// Implemented as a private standalone method to discourage "merging" as a usage pattern.
72#[inline]
73pub(crate) fn borrow_merge<'a, T: RawMessageBorrowDecoder<'a>>(
74    value: &mut T,
75    mut buf: Capped<&'a [u8]>,
76    ctx: DecodeContext,
77) -> Result<(), DecodeError> {
78    let tr = &mut TagReader::new();
79    let mut last_tag = None::<u32>;
80    while buf.has_remaining()? {
81        let (tag, wire_type) = tr.decode_key(buf.lend())?;
82        let duplicated = last_tag == Some(tag);
83        last_tag = Some(tag);
84        value.raw_borrow_decode_field(tag, wire_type, duplicated, buf.lend(), ctx.clone())?;
85    }
86    Ok(())
87}
88
89/// Merges fields from the given buffer, to its cap, into the given distinguished borrowed message
90/// value. Implemented as a private standalone method to discourage "merging" as a usage pattern.
91#[inline]
92pub(crate) fn borrow_merge_distinguished<'a, T: RawDistinguishedMessageBorrowDecoder<'a>>(
93    value: &mut T,
94    mut buf: Capped<&'a [u8]>,
95    ctx: RestrictedDecodeContext,
96) -> Result<Canonicity, DecodeError> {
97    let tr = &mut TagReader::new();
98    let mut last_tag = None::<u32>;
99    let mut canon = Canonical;
100    while buf.has_remaining()? {
101        let (tag, wire_type) = tr.decode_key(buf.lend())?;
102        let duplicated = last_tag == Some(tag);
103        last_tag = Some(tag);
104        canon.update(value.raw_borrow_decode_field_distinguished(
105            tag,
106            wire_type,
107            duplicated,
108            buf.lend(),
109            ctx.clone(),
110        )?);
111    }
112    debug_assert!(
113        canon >= ctx.min_canonicity,
114        "a poorly behaved distinguished decoder did not check canonicity against the context and \
115        convert it into an error"
116    );
117    Ok(canon)
118}
119
120/// Encoding trait to be implemented by messages. The methods of this trait are meant to only be
121/// used by the `Message` implementation.
122pub trait RawMessage {
123    const __ASSERTIONS: ();
124
125    /// Returns an initialized message in an empty state.
126    fn empty() -> Self
127    where
128        Self: Sized;
129
130    /// Returns whether the message is currently empty.
131    fn is_empty(&self) -> bool;
132
133    /// Resets the message to an empty state.
134    fn clear(&mut self);
135
136    /// Encodes the message to a buffer.
137    ///
138    /// This method will panic if the buffer has insufficient capacity.
139    fn raw_encode<B: BufMut + ?Sized>(&self, buf: &mut B);
140
141    /// Prepends the message to a prepend buffer.
142    fn raw_prepend<B: ReverseBuf + ?Sized>(&self, buf: &mut B);
143
144    /// Returns the encoded length of the message without a length delimiter.
145    fn raw_encoded_len(&self) -> usize;
146}
147
148/// Decoding trait to be implemented by messages. The methods of this trait are meant to only be
149/// used by the `OwnedMessage` implementation.
150pub trait RawMessageDecoder: RawMessage {
151    /// Decodes a field from a buffer into `self`.
152    fn raw_decode_field<B: Buf + ?Sized>(
153        &mut self,
154        tag: u32,
155        wire_type: WireType,
156        duplicated: bool,
157        buf: Capped<B>,
158        ctx: DecodeContext,
159    ) -> Result<(), DecodeError>
160    where
161        Self: Sized;
162}
163
164/// Distinguished decoding trait to be implemented by messages. The methods of this trait are meant
165/// to only be used by the `DistinguishedOwnedMessage` implementation.
166pub trait RawDistinguishedMessageDecoder: RawMessage + Eq {
167    fn raw_decode_field_distinguished<B: Buf + ?Sized>(
168        &mut self,
169        tag: u32,
170        wire_type: WireType,
171        duplicated: bool,
172        buf: Capped<B>,
173        ctx: RestrictedDecodeContext,
174    ) -> Result<Canonicity, DecodeError>
175    where
176        Self: Sized;
177}
178
179/// Borrowed decoding trait to be implemented by messages. The methods of this trait are meant to
180/// only be used by the `BorrowedMessage` implementation.
181pub trait RawMessageBorrowDecoder<'a>: RawMessage {
182    /// Decodes a field from a buffer into `self` from a borrowed slice.
183    fn raw_borrow_decode_field(
184        &mut self,
185        tag: u32,
186        wire_type: WireType,
187        duplicated: bool,
188        buf: Capped<&'a [u8]>,
189        ctx: DecodeContext,
190    ) -> Result<(), DecodeError>
191    where
192        Self: Sized;
193}
194
195/// Borrowed distinguished decoding trait to be implemented by messages. The methods of this trait
196/// are meant to only be used by the `DistinguishedBorrowedMessage` implementation.
197pub trait RawDistinguishedMessageBorrowDecoder<'a>: RawMessage + Eq {
198    fn raw_borrow_decode_field_distinguished(
199        &mut self,
200        tag: u32,
201        wire_type: WireType,
202        duplicated: bool,
203        buf: Capped<&'a [u8]>,
204        ctx: RestrictedDecodeContext,
205    ) -> Result<Canonicity, DecodeError>
206    where
207        Self: Sized;
208}
209
210impl<T> RawMessage for Box<T>
211where
212    T: RawMessage + Sized,
213{
214    const __ASSERTIONS: () = ();
215
216    fn empty() -> Self
217    where
218        Self: Sized,
219    {
220        Box::new(T::empty())
221    }
222
223    fn is_empty(&self) -> bool {
224        self.as_ref().is_empty()
225    }
226
227    fn clear(&mut self) {
228        self.as_mut().clear();
229    }
230
231    fn raw_encode<B: BufMut + ?Sized>(&self, buf: &mut B) {
232        (**self).raw_encode(buf)
233    }
234
235    fn raw_prepend<B: ReverseBuf + ?Sized>(&self, buf: &mut B) {
236        (**self).raw_prepend(buf)
237    }
238
239    fn raw_encoded_len(&self) -> usize {
240        (**self).raw_encoded_len()
241    }
242}
243
244impl<T> RawMessageDecoder for Box<T>
245where
246    T: RawMessageDecoder,
247{
248    fn raw_decode_field<B: Buf + ?Sized>(
249        &mut self,
250        tag: u32,
251        wire_type: WireType,
252        duplicated: bool,
253        buf: Capped<B>,
254        ctx: DecodeContext,
255    ) -> Result<(), DecodeError>
256    where
257        Self: Sized,
258    {
259        (**self).raw_decode_field(tag, wire_type, duplicated, buf, ctx)
260    }
261}
262
263impl<'a, T> RawMessageBorrowDecoder<'a> for Box<T>
264where
265    T: RawMessageBorrowDecoder<'a>,
266{
267    fn raw_borrow_decode_field(
268        &mut self,
269        tag: u32,
270        wire_type: WireType,
271        duplicated: bool,
272        buf: Capped<&'a [u8]>,
273        ctx: DecodeContext,
274    ) -> Result<(), DecodeError>
275    where
276        Self: Sized,
277    {
278        (**self).raw_borrow_decode_field(tag, wire_type, duplicated, buf, ctx)
279    }
280}
281
282impl<T> RawDistinguishedMessageDecoder for Box<T>
283where
284    T: RawDistinguishedMessageDecoder,
285{
286    fn raw_decode_field_distinguished<B: Buf + ?Sized>(
287        &mut self,
288        tag: u32,
289        wire_type: WireType,
290        duplicated: bool,
291        buf: Capped<B>,
292        ctx: RestrictedDecodeContext,
293    ) -> Result<Canonicity, DecodeError>
294    where
295        Self: Sized,
296    {
297        (**self).raw_decode_field_distinguished(tag, wire_type, duplicated, buf, ctx)
298    }
299}
300
301impl<'a, T> RawDistinguishedMessageBorrowDecoder<'a> for Box<T>
302where
303    T: RawDistinguishedMessageBorrowDecoder<'a>,
304{
305    fn raw_borrow_decode_field_distinguished(
306        &mut self,
307        tag: u32,
308        wire_type: WireType,
309        duplicated: bool,
310        buf: Capped<&'a [u8]>,
311        ctx: RestrictedDecodeContext,
312    ) -> Result<Canonicity, DecodeError>
313    where
314        Self: Sized,
315    {
316        (**self).raw_borrow_decode_field_distinguished(tag, wire_type, duplicated, buf, ctx)
317    }
318}
319
320impl<T> ForOverwrite<MessageEncoding, T> for ()
321where
322    T: RawMessage,
323{
324    fn for_overwrite() -> T
325    where
326        T: Sized,
327    {
328        T::empty()
329    }
330}
331
332impl<T> EmptyState<MessageEncoding, T> for ()
333where
334    T: RawMessage,
335{
336    fn is_empty(val: &T) -> bool {
337        val.is_empty()
338    }
339
340    fn clear(val: &mut T) {
341        val.clear();
342    }
343}
344
345impl<T> Wiretyped<MessageEncoding, T> for ()
346where
347    T: RawMessage,
348{
349    const WIRE_TYPE: WireType = WireType::LengthDelimited;
350}
351
352impl<T> ValueEncoder<MessageEncoding, T> for ()
353where
354    T: RawMessage,
355{
356    #[inline]
357    fn encode_value<B: BufMut + ?Sized>(value: &T, buf: &mut B) {
358        encode_varint(value.raw_encoded_len() as u64, buf);
359        value.raw_encode(buf);
360    }
361
362    #[inline]
363    fn prepend_value<B: ReverseBuf + ?Sized>(value: &T, buf: &mut B) {
364        let end = buf.remaining();
365        value.raw_prepend(buf);
366        prepend_varint((buf.remaining() - end) as u64, buf);
367    }
368
369    #[inline]
370    fn value_encoded_len(value: &T) -> usize {
371        let inner_len = value.raw_encoded_len();
372        encoded_len_varint(inner_len as u64) + inner_len
373    }
374}
375
376impl<T> ValueDecoder<MessageEncoding, T> for ()
377where
378    T: RawMessageDecoder,
379{
380    #[inline]
381    fn decode_value<B: Buf + ?Sized>(
382        value: &mut T,
383        mut buf: Capped<B>,
384        ctx: DecodeContext,
385    ) -> Result<(), DecodeError> {
386        ctx.limit_reached()?;
387        merge(value, buf.take_length_delimited()?, ctx.enter_recursion())
388    }
389}
390
391impl<T> DistinguishedValueDecoder<MessageEncoding, T> for ()
392where
393    T: RawDistinguishedMessageDecoder + Eq,
394{
395    const CHECKS_EMPTY: bool = true; // Empty messages are always zero-length
396
397    #[inline]
398    fn decode_value_distinguished<const ALLOW_EMPTY: bool>(
399        value: &mut T,
400        mut buf: Capped<impl Buf + ?Sized>,
401        ctx: RestrictedDecodeContext,
402    ) -> Result<Canonicity, DecodeError> {
403        ctx.limit_reached()?;
404        let buf = buf.take_length_delimited()?;
405        // Empty message types always encode and decode from zero bytes. It is far cheaper to check
406        // here than to check after the value has been decoded and checking the message's
407        // `is_empty()`.
408        if !ALLOW_EMPTY && buf.remaining_before_cap() == 0 {
409            return ctx.check(Canonicity::NotCanonical);
410        }
411        merge_distinguished(value, buf, ctx.enter_recursion())
412    }
413}
414
415impl<'a, T> ValueBorrowDecoder<'a, MessageEncoding, T> for ()
416where
417    T: RawMessageBorrowDecoder<'a>,
418{
419    #[inline]
420    fn borrow_decode_value(
421        value: &mut T,
422        mut buf: Capped<&'a [u8]>,
423        ctx: DecodeContext,
424    ) -> Result<(), DecodeError> {
425        ctx.limit_reached()?;
426        borrow_merge(value, buf.take_length_delimited()?, ctx.enter_recursion())
427    }
428}
429
430impl<'a, T> DistinguishedValueBorrowDecoder<'a, MessageEncoding, T> for ()
431where
432    T: RawDistinguishedMessageBorrowDecoder<'a> + Eq,
433{
434    const CHECKS_EMPTY: bool = true; // Empty messages are always zero-length
435
436    #[inline]
437    fn borrow_decode_value_distinguished<const ALLOW_EMPTY: bool>(
438        value: &mut T,
439        mut buf: Capped<&'a [u8]>,
440        ctx: RestrictedDecodeContext,
441    ) -> Result<Canonicity, DecodeError> {
442        ctx.limit_reached()?;
443        let buf = buf.take_length_delimited()?;
444        // Empty message types always encode and decode from zero bytes. It is far cheaper to check
445        // here than to check after the value has been decoded and checking the message's
446        // `is_empty()`.
447        if !ALLOW_EMPTY && buf.remaining_before_cap() == 0 {
448            return ctx.check(Canonicity::NotCanonical);
449        }
450        borrow_merge_distinguished(value, buf, ctx.enter_recursion())
451    }
452}