Skip to main content

bilrost/encoding/
encoding_traits.rs

1use crate::buf::ReverseBuf;
2use crate::encoding::{
3    check_wire_type, Capped, DecodeContext, ForOverwrite, RestrictedDecodeContext, TagMeasurer,
4    TagRevWriter, TagWriter, WireType,
5};
6use crate::{Canonicity, DecodeError};
7use bytes::{Buf, BufMut};
8use core::ops::Deref;
9
10/// The core trait for encoding bilrost data.
11pub trait Encoder<E, T: ?Sized> {
12    /// Encodes the a field with the given tag and value.
13    fn encode<B: BufMut + ?Sized>(tag: u32, value: &T, buf: &mut B, tw: &mut TagWriter);
14
15    /// Prepends the encoding of the field with the given tag and value.
16    fn prepend_encode<B: ReverseBuf + ?Sized>(
17        tag: u32,
18        value: &T,
19        buf: &mut B,
20        tw: &mut TagRevWriter,
21    );
22
23    /// Returns the encoded length of the field, including the key.
24    fn encoded_len(tag: u32, value: &T, tm: &mut impl TagMeasurer) -> usize;
25}
26
27/// The core trait for decoding bilrost data. Data must always be copied from the buffer.
28pub trait Decoder<E, T>: Encoder<E, T> {
29    /// Decodes a field's value with the given wire type; the field's key should have already been
30    /// consumed from the buffer.
31    fn decode<B: Buf + ?Sized>(
32        wire_type: WireType,
33        value: &mut T,
34        buf: Capped<B>,
35        ctx: DecodeContext,
36    ) -> Result<(), DecodeError>;
37}
38
39/// Decoding trait for canonical decoding. Distinguished decoding is available via
40/// this trait, and any type that implements this trait is guaranteed to always emit canonical data
41/// via `Encoder`.
42pub trait DistinguishedDecoder<E, T>: Encoder<E, T> {
43    /// Decodes a field for the value, returning a value indicating how canonical the encoding was.
44    fn decode_distinguished<B: Buf + ?Sized>(
45        wire_type: WireType,
46        value: &mut T,
47        buf: Capped<B>,
48        ctx: RestrictedDecodeContext,
49    ) -> Result<Canonicity, DecodeError>;
50}
51
52/// Decoding trait that allows decoding borrowed data.
53pub trait BorrowDecoder<'a, E, T>: Encoder<E, T> {
54    fn borrow_decode(
55        wire_type: WireType,
56        value: &mut T,
57        buf: Capped<&'a [u8]>,
58        ctx: DecodeContext,
59    ) -> Result<(), DecodeError>;
60}
61
62/// Decoding trait that allows distinguished decoding of borrowed data.
63pub trait DistinguishedBorrowDecoder<'a, E, T>: Encoder<E, T> {
64    /// Decodes a field for the value, returning a value indicating how canonical the encoding was.
65    fn borrow_decode_distinguished(
66        wire_type: WireType,
67        value: &mut T,
68        buf: Capped<&'a [u8]>,
69        ctx: RestrictedDecodeContext,
70    ) -> Result<Canonicity, DecodeError>;
71}
72
73/// Encoders' wire-type is relied upon by both relaxed and distinguished encoders, but it is written
74/// to be a separate trait so that distinguished decoders don't necessarily implement relaxed
75/// decoding. This isn't important in general; it's very unlikely anything would implement
76/// distinguished decoding without also implementing the corresponding relaxed decoding, but
77/// this means that it can become a typo to use the relaxed decoding functions by accident when
78/// implementing the distinguished decoders, which could cause serious mishaps.
79pub trait Wiretyped<E, T: ?Sized> {
80    const WIRE_TYPE: WireType;
81}
82
83/// The core trait for encoding implementations for raw values that always encode to a single value.
84/// This is the basis for all the other plain, optional, and repeated encodings.
85pub trait ValueEncoder<E, T: ?Sized>: Wiretyped<E, T> {
86    /// Encodes the given value unconditionally. This is guaranteed to emit data to the buffer.
87    fn encode_value<B: BufMut + ?Sized>(value: &T, buf: &mut B);
88
89    /// Prepends the given value unconditionally. This is guaranteed to emit data to the buffer.
90    fn prepend_value<B: ReverseBuf + ?Sized>(value: &T, buf: &mut B);
91
92    /// Returns the number of bytes the given value would be encoded as.
93    fn value_encoded_len(value: &T) -> usize;
94
95    /// Returns the number of total bytes to encode all the values in the given container.
96    #[inline]
97    fn many_values_encoded_len<I>(values: I) -> usize
98    where
99        I: ExactSizeIterator,
100        I::Item: Deref<Target = T>,
101    {
102        let len = values.len();
103        Self::WIRE_TYPE.fixed_size().map_or_else(
104            || values.map(|val| Self::value_encoded_len(&val)).sum(),
105            |fixed_size| fixed_size * len, // Shortcut when values have a fixed size
106        )
107    }
108}
109
110/// The core trait for decoding single values in relaxed mode. Data is always copies when it is
111/// read from the buffer.
112pub trait ValueDecoder<E, T>: ValueEncoder<E, T> {
113    /// Decodes a field assuming the encoder's wire type directly from the buffer.
114    fn decode_value<B: Buf + ?Sized>(
115        value: &mut T,
116        buf: Capped<B>,
117        ctx: DecodeContext,
118    ) -> Result<(), DecodeError>;
119}
120
121/// The core trait for decoding single values in distinguished mode. Data is always copies when it
122/// is read from the buffer.
123pub trait DistinguishedValueDecoder<E, T>: ValueEncoder<E, T> + Eq {
124    /// Indicates whether the `ALLOW_EMPTY` argument in `decode_value_distinguished` has any effect.
125    /// Some decoder implementations can more cheaply determine whether they were empty during
126    /// decoding, and will return `NotCanonical` if `ALLOW_EMPTY` was false; for these
127    /// implementations, `CHECKS_EMPTY` should be set to `true`. When `CHECKS_EMPTY` is `false`, the
128    /// caller must invoke `EmptyState::is_empty` after the call if empty states are non-canonical.
129    const CHECKS_EMPTY: bool;
130
131    /// Decodes a field assuming the encoder's wire type directly from the buffer, also performing
132    /// any additional validation required to guarantee that the value would be re-encoded into the
133    /// exact same bytes.
134    fn decode_value_distinguished<const ALLOW_EMPTY: bool>(
135        value: &mut T,
136        buf: Capped<impl Buf + ?Sized>,
137        ctx: RestrictedDecodeContext,
138    ) -> Result<Canonicity, DecodeError>;
139}
140
141/// Value-decoding trait for decoding borrowed values.
142pub trait ValueBorrowDecoder<'a, E, T>: ValueEncoder<E, T> {
143    /// Decodes a field assuming the encoder's wire type directly from the buffer.
144    fn borrow_decode_value(
145        value: &mut T,
146        buf: Capped<&'a [u8]>,
147        ctx: DecodeContext,
148    ) -> Result<(), DecodeError>;
149}
150
151/// Value-decoding trait for distinguished decoding of borrowed values.
152pub trait DistinguishedValueBorrowDecoder<'a, E, T>: ValueEncoder<E, T> + Eq {
153    /// Indicates whether the `ALLOW_EMPTY` argument in `borrow_decode_value_distinguished` has any
154    /// effect. Some decoder implementations can more cheaply determine whether they were empty
155    /// during decoding, and will return `NotCanonical` if `ALLOW_EMPTY` was false; for these
156    /// implementations, `CHECKS_EMPTY` should be set to `true`. When `CHECKS_EMPTY` is `false`, the
157    /// caller must invoke `EmptyState::is_empty` after the call if empty states are non-canonical.
158    const CHECKS_EMPTY: bool;
159
160    /// Decodes a field assuming the encoder's wire type directly from the buffer, also performing
161    /// any additional validation required to guarantee that the value would be re-encoded into the
162    /// exact same bytes.
163    fn borrow_decode_value_distinguished<const ALLOW_EMPTY: bool>(
164        value: &mut T,
165        buf: Capped<&'a [u8]>,
166        ctx: RestrictedDecodeContext,
167    ) -> Result<Canonicity, DecodeError>;
168}
169
170/// Affiliated helper trait for ValueEncoder that provides obligate implementations for handling
171/// field keys and wire types.
172pub trait FieldEncoder<E, T: ?Sized>: ValueEncoder<E, T> {
173    /// Encodes exactly one field with the given tag and value into the buffer.
174    fn encode_field<B: BufMut + ?Sized>(tag: u32, value: &T, buf: &mut B, tw: &mut TagWriter);
175
176    /// Prepends exactly one field with the given tag and value into the buffer.
177    fn prepend_field<B: ReverseBuf + ?Sized>(
178        tag: u32,
179        value: &T,
180        buf: &mut B,
181        tw: &mut TagRevWriter,
182    );
183
184    /// Returns the encoded length of the field including its key.
185    fn field_encoded_len(tag: u32, value: &T, tm: &mut impl TagMeasurer) -> usize;
186}
187
188/// Affiliated helper trait for ValueDecoder that provides obligate implementations for handling
189/// field keys and wire types.
190pub trait FieldDecoder<E, T>: ValueDecoder<E, T> {
191    /// Decodes a field directly from the buffer, also checking the wire type.
192    fn decode_field<B: Buf + ?Sized>(
193        wire_type: WireType,
194        value: &mut T,
195        buf: Capped<B>,
196        ctx: DecodeContext,
197    ) -> Result<(), DecodeError>;
198}
199
200/// Affiliated helper trait for DistinguishedValueDecoder that provides obligate implementations for
201/// handling field keys and wire types.
202pub trait DistinguishedFieldDecoder<E, T>: DistinguishedValueDecoder<E, T> {
203    /// Decodes a field directly from the buffer, also checking the wire type.
204    fn decode_field_distinguished<const ALLOW_EMPTY: bool>(
205        wire_type: WireType,
206        value: &mut T,
207        buf: Capped<impl Buf + ?Sized>,
208        ctx: RestrictedDecodeContext,
209    ) -> Result<Canonicity, DecodeError>;
210}
211
212/// Affiliated helper trait for BorrowDecoder that provides obligate implementations for handling
213/// field keys and wire types.
214pub trait FieldBorrowDecoder<'a, E, T>: ValueBorrowDecoder<'a, E, T> {
215    /// Decodes a field directly from the buffer, also checking the wire type.
216    fn borrow_decode_field(
217        wire_type: WireType,
218        value: &mut T,
219        buf: Capped<&'a [u8]>,
220        ctx: DecodeContext,
221    ) -> Result<(), DecodeError>;
222}
223
224/// Affiliated helper trait for DistinguishedBorrowDecoder that provides obligate implementations
225/// for handling field keys and wire types.
226pub trait DistinguishedFieldBorrowDecoder<'a, E, T>:
227    DistinguishedValueBorrowDecoder<'a, E, T>
228{
229    /// Decodes a field directly from the buffer, also checking the wire type.
230    fn borrow_decode_field_distinguished<const ALLOW_EMPTY: bool>(
231        wire_type: WireType,
232        value: &mut T,
233        buf: Capped<&'a [u8]>,
234        ctx: RestrictedDecodeContext,
235    ) -> Result<Canonicity, DecodeError>;
236}
237
238impl<E, T: ?Sized> FieldEncoder<E, T> for ()
239where
240    (): ValueEncoder<E, T>,
241{
242    #[inline]
243    fn encode_field<B: BufMut + ?Sized>(tag: u32, value: &T, buf: &mut B, tw: &mut TagWriter) {
244        tw.encode_key(tag, <() as Wiretyped<E, T>>::WIRE_TYPE, buf);
245        <() as ValueEncoder<E, T>>::encode_value(value, buf);
246    }
247
248    #[inline]
249    fn prepend_field<B: ReverseBuf + ?Sized>(
250        tag: u32,
251        value: &T,
252        buf: &mut B,
253        tw: &mut TagRevWriter,
254    ) {
255        tw.begin_field(tag, <() as Wiretyped<E, T>>::WIRE_TYPE, buf);
256        <() as ValueEncoder<E, T>>::prepend_value(value, buf);
257    }
258
259    #[inline]
260    fn field_encoded_len(tag: u32, value: &T, tm: &mut impl TagMeasurer) -> usize {
261        tm.key_len(tag) + <() as ValueEncoder<E, T>>::value_encoded_len(value)
262    }
263}
264
265impl<T, E> FieldDecoder<E, T> for ()
266where
267    (): ValueDecoder<E, T>,
268{
269    #[inline]
270    fn decode_field<B: Buf + ?Sized>(
271        wire_type: WireType,
272        value: &mut T,
273        buf: Capped<B>,
274        ctx: DecodeContext,
275    ) -> Result<(), DecodeError> {
276        check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
277        <() as ValueDecoder<E, T>>::decode_value(value, buf, ctx)
278    }
279}
280
281impl<T, E> DistinguishedFieldDecoder<E, T> for ()
282where
283    (): DistinguishedValueDecoder<E, T>,
284{
285    #[inline(always)]
286    fn decode_field_distinguished<const ALLOW_EMPTY: bool>(
287        wire_type: WireType,
288        value: &mut T,
289        buf: Capped<impl Buf + ?Sized>,
290        ctx: RestrictedDecodeContext,
291    ) -> Result<Canonicity, DecodeError> {
292        check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
293        <() as DistinguishedValueDecoder<E, T>>::decode_value_distinguished::<ALLOW_EMPTY>(
294            value, buf, ctx,
295        )
296    }
297}
298
299impl<'a, T, E> FieldBorrowDecoder<'a, E, T> for ()
300where
301    (): ValueBorrowDecoder<'a, E, T>,
302{
303    #[inline]
304    fn borrow_decode_field(
305        wire_type: WireType,
306        value: &mut T,
307        buf: Capped<&'a [u8]>,
308        ctx: DecodeContext,
309    ) -> Result<(), DecodeError> {
310        check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
311        <() as ValueBorrowDecoder<E, T>>::borrow_decode_value(value, buf, ctx)
312    }
313}
314
315impl<'a, T, E> DistinguishedFieldBorrowDecoder<'a, E, T> for ()
316where
317    (): DistinguishedValueBorrowDecoder<'a, E, T>,
318{
319    #[inline(always)]
320    fn borrow_decode_field_distinguished<const ALLOW_EMPTY: bool>(
321        wire_type: WireType,
322        value: &mut T,
323        buf: Capped<&'a [u8]>,
324        ctx: RestrictedDecodeContext,
325    ) -> Result<Canonicity, DecodeError> {
326        check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
327        <() as DistinguishedValueBorrowDecoder<E, T>>::borrow_decode_value_distinguished::<
328            ALLOW_EMPTY,
329        >(value, buf, ctx)
330    }
331}
332
333/// Different value encoders may dispatch encoding their plain values slightly differently, but
334/// values wrapped in Option are always encoded & decoded the same.
335///
336/// This would perhaps, in theory, need to be broken up if a value type whose values may be encoded
337/// with different wire-types could be implemented. However, this can never happen: It is
338/// essentially forbidden for any type to value-encode with differing wire types, because *value*
339/// decoding does not get to know the wire type; when values are encoded packed end to end the wire
340/// type for each is not stored.
341mod generic_optional {
342    use super::*;
343
344    impl<T, E> Encoder<E, Option<T>> for ()
345    where
346        (): ValueEncoder<E, T> + ForOverwrite<E, T>,
347    {
348        #[inline]
349        fn encode<B: BufMut + ?Sized>(
350            tag: u32,
351            value: &Option<T>,
352            buf: &mut B,
353            tw: &mut TagWriter,
354        ) {
355            if let Some(value) = value {
356                <() as FieldEncoder<E, T>>::encode_field(tag, value, buf, tw);
357            }
358        }
359
360        #[inline]
361        fn prepend_encode<B: ReverseBuf + ?Sized>(
362            tag: u32,
363            value: &Option<T>,
364            buf: &mut B,
365            tw: &mut TagRevWriter,
366        ) {
367            if let Some(value) = value {
368                <() as FieldEncoder<E, T>>::prepend_field(tag, value, buf, tw)
369            }
370        }
371
372        #[inline]
373        fn encoded_len(tag: u32, value: &Option<T>, tm: &mut impl TagMeasurer) -> usize {
374            if let Some(value) = value {
375                <() as FieldEncoder<E, T>>::field_encoded_len(tag, value, tm)
376            } else {
377                0
378            }
379        }
380    }
381
382    impl<T, E> Decoder<E, Option<T>> for ()
383    where
384        (): ValueDecoder<E, T> + ForOverwrite<E, T>,
385    {
386        #[inline]
387        fn decode<B: Buf + ?Sized>(
388            wire_type: WireType,
389            value: &mut Option<T>,
390            buf: Capped<B>,
391            ctx: DecodeContext,
392        ) -> Result<(), DecodeError> {
393            <() as FieldDecoder<E, T>>::decode_field(
394                wire_type,
395                value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
396                buf,
397                ctx,
398            )
399        }
400    }
401
402    impl<T, E> DistinguishedDecoder<E, Option<T>> for ()
403    where
404        Option<T>: Eq,
405        (): DistinguishedValueDecoder<E, T> + ForOverwrite<E, T>,
406    {
407        #[inline]
408        fn decode_distinguished<B: Buf + ?Sized>(
409            wire_type: WireType,
410            value: &mut Option<T>,
411            buf: Capped<B>,
412            ctx: RestrictedDecodeContext,
413        ) -> Result<Canonicity, DecodeError> {
414            check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
415            <() as DistinguishedValueDecoder<E, T>>::decode_value_distinguished::<true>(
416                value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
417                buf,
418                ctx,
419            )
420        }
421    }
422
423    impl<'a, T, E> BorrowDecoder<'a, E, Option<T>> for ()
424    where
425        (): ValueBorrowDecoder<'a, E, T> + ForOverwrite<E, T>,
426    {
427        #[inline]
428        fn borrow_decode(
429            wire_type: WireType,
430            value: &mut Option<T>,
431            buf: Capped<&'a [u8]>,
432            ctx: DecodeContext,
433        ) -> Result<(), DecodeError> {
434            <() as FieldBorrowDecoder<E, T>>::borrow_decode_field(
435                wire_type,
436                value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
437                buf,
438                ctx,
439            )
440        }
441    }
442
443    impl<'a, T, E> DistinguishedBorrowDecoder<'a, E, Option<T>> for ()
444    where
445        Option<T>: Eq,
446        (): DistinguishedValueBorrowDecoder<'a, E, T> + ForOverwrite<E, T>,
447    {
448        #[inline]
449        fn borrow_decode_distinguished(
450            wire_type: WireType,
451            value: &mut Option<T>,
452            buf: Capped<&'a [u8]>,
453            ctx: RestrictedDecodeContext,
454        ) -> Result<Canonicity, DecodeError> {
455            check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
456            <() as DistinguishedValueBorrowDecoder<E, T>>::borrow_decode_value_distinguished::<true>(
457                value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
458                buf,
459                ctx,
460            )
461        }
462    }
463}