11//! Core traits for encoding and decoding.
22
33use crate :: error:: Error ;
4+ #[ cfg( not( feature = "std" ) ) ]
5+ use alloc:: vec:: Vec ;
46use bytes:: { Buf , BufMut , Bytes , BytesMut } ;
7+ #[ cfg( feature = "std" ) ]
8+ use std:: vec:: Vec ;
59
610/// Trait for types with a known, fixed encoded size.
711///
@@ -23,20 +27,86 @@ pub trait EncodeSize {
2327 /// Returns the encoded size of this value (in bytes).
2428 fn encode_size ( & self ) -> usize ;
2529
30+ /// Returns the total encoded size of a sequence, excluding any container-specific length
31+ /// prefix.
32+ ///
33+ /// Container implementations call this hook so element types can provide a more efficient
34+ /// aggregate size calculation. The default preserves normal element-by-element sizing.
35+ /// Fixed-size implementations compute `SIZE * len`, which avoids an O(n) sizing prepass
36+ /// before containers such as `Vec<T>` allocate their output buffer.
37+ ///
38+ /// This hook exists because stable Rust cannot express the overlapping specialized
39+ /// container impls that would otherwise provide this aggregate path directly.
40+ ///
41+ /// This is hidden from generated documentation because it is an implementation hook for
42+ /// codec's container types, not part of the intended user-facing API. Most users should
43+ /// implement [EncodeSize::encode_size] or [FixedSize] instead.
44+ #[ doc( hidden) ]
45+ #[ inline]
46+ fn encode_size_slice ( values : & [ Self ] ) -> usize
47+ where
48+ Self : Sized ,
49+ {
50+ values. iter ( ) . map ( EncodeSize :: encode_size) . sum ( )
51+ }
52+
2653 /// Returns the encoded size excluding bytes passed to [`BufsMut::push`]
2754 /// during [`Write::write_bufs`]. Used to size the working buffer for inline
2855 /// writes. Override alongside [`Write::write_bufs`] for types where large
2956 /// [`Bytes`] fields go via push; failing to do so will over-allocate.
57+ #[ inline]
3058 fn encode_inline_size ( & self ) -> usize {
3159 self . encode_size ( )
3260 }
61+
62+ /// Returns the total inline encoded size of a sequence, excluding any container-specific
63+ /// length prefix.
64+ ///
65+ /// This hidden hook is the slice equivalent of [EncodeSize::encode_inline_size]. The
66+ /// default preserves normal element-by-element sizing. Fixed-size implementations override
67+ /// this to compute `SIZE * len`, matching [EncodeSize::encode_size_slice] for the
68+ /// [`Write::write_bufs`] path.
69+ ///
70+ /// This hook exists because stable Rust cannot express the overlapping specialized
71+ /// container impls that would otherwise provide this aggregate path directly.
72+ ///
73+ /// This is hidden from generated documentation for the same reason as
74+ /// [EncodeSize::encode_size_slice].
75+ #[ doc( hidden) ]
76+ #[ inline]
77+ fn encode_inline_size_slice ( values : & [ Self ] ) -> usize
78+ where
79+ Self : Sized ,
80+ {
81+ values
82+ . iter ( )
83+ . map ( EncodeSize :: encode_inline_size)
84+ . sum :: < usize > ( )
85+ }
3386}
3487
3588// Automatically implement `EncodeSize` for types that are `FixedSize`.
3689impl < T : FixedSize > EncodeSize for T {
90+ #[ inline]
3791 fn encode_size ( & self ) -> usize {
3892 Self :: SIZE
3993 }
94+
95+ #[ inline]
96+ fn encode_size_slice ( values : & [ Self ] ) -> usize
97+ where
98+ Self : Sized ,
99+ {
100+ Self :: SIZE * values. len ( )
101+ }
102+
103+ #[ inline]
104+ fn encode_inline_size_slice ( values : & [ Self ] ) -> usize
105+ where
106+ Self : Sized ,
107+ {
108+ Self :: encode_size_slice ( values)
109+ }
40110}
41111
42112/// Trait for types that can be written (encoded) to a byte buffer.
@@ -46,12 +116,57 @@ pub trait Write {
46116 /// Implementations should panic if the buffer doesn't have enough capacity.
47117 fn write ( & self , buf : & mut impl BufMut ) ;
48118
119+ /// Writes the encoded payload for a sequence, excluding any container-specific length
120+ /// prefix.
121+ ///
122+ /// Container implementations call this hook so element types can provide a more efficient
123+ /// aggregate write path. The default preserves normal element-by-element encoding.
124+ ///
125+ /// This hook exists because stable Rust cannot express the overlapping specialized
126+ /// container impls that would otherwise provide this aggregate path directly.
127+ ///
128+ /// This is hidden from generated documentation because it is an implementation hook for
129+ /// codec's container types, not part of the intended user-facing API. Most users should
130+ /// implement [Write::write] instead.
131+ #[ doc( hidden) ]
132+ #[ inline]
133+ fn write_slice ( values : & [ Self ] , buf : & mut impl BufMut )
134+ where
135+ Self : Sized ,
136+ {
137+ for item in values {
138+ item. write ( buf) ;
139+ }
140+ }
141+
49142 /// Writes to a [`BufsMut`], allowing existing [`Bytes`] chunks to be
50143 /// appended via [`BufsMut::push`] instead of written inline. Must encode
51144 /// to the same format as [`Write::write`]. Defaults to [`Write::write`].
145+ #[ inline]
52146 fn write_bufs ( & self , buf : & mut impl BufsMut ) {
53147 self . write ( buf) ;
54148 }
149+
150+ /// Writes the encoded payload for a sequence to a [`BufsMut`], excluding any
151+ /// container-specific length prefix.
152+ ///
153+ /// This hidden hook is the slice equivalent of [Write::write_bufs]. The default preserves
154+ /// normal element-by-element encoding.
155+ ///
156+ /// This hook exists because stable Rust cannot express the overlapping specialized
157+ /// container impls that would otherwise provide this aggregate path directly.
158+ ///
159+ /// This is hidden from generated documentation for the same reason as [Write::write_slice].
160+ #[ doc( hidden) ]
161+ #[ inline]
162+ fn write_slice_bufs ( values : & [ Self ] , buf : & mut impl BufsMut )
163+ where
164+ Self : Sized ,
165+ {
166+ for item in values {
167+ item. write_bufs ( buf) ;
168+ }
169+ }
55170}
56171
57172/// Trait for types that can be read (decoded) from a byte buffer.
@@ -71,6 +186,44 @@ pub trait Read: Sized {
71186 /// Returns [Error] if decoding fails due to invalid data, insufficient bytes in the buffer,
72187 /// or violation of constraints imposed by the `cfg`.
73188 fn read_cfg ( buf : & mut impl Buf , cfg : & Self :: Cfg ) -> Result < Self , Error > ;
189+
190+ /// Reads `len` values from the buffer into a vector.
191+ ///
192+ /// Container implementations call this hook so element types can provide a more efficient
193+ /// vector read path. The default preserves normal element-by-element decoding.
194+ ///
195+ /// This hook exists because stable Rust cannot express the overlapping specialized
196+ /// container impls that would otherwise provide this aggregate path directly.
197+ ///
198+ /// This is hidden from generated documentation because it is an implementation hook for
199+ /// codec's container types, not part of the intended user-facing API. Most users should
200+ /// implement [Read::read_cfg] instead.
201+ #[ doc( hidden) ]
202+ #[ inline]
203+ fn read_vec ( buf : & mut impl Buf , len : usize , cfg : & Self :: Cfg ) -> Result < Vec < Self > , Error > {
204+ let mut values = Vec :: with_capacity ( len) ;
205+ for _ in 0 ..len {
206+ values. push ( Self :: read_cfg ( buf, cfg) ?) ;
207+ }
208+ Ok ( values)
209+ }
210+
211+ /// Reads exactly `N` values from the buffer into an array.
212+ ///
213+ /// This hidden hook is the array equivalent of [Read::read_vec]. The default preserves
214+ /// normal element-by-element decoding.
215+ ///
216+ /// This hook exists because stable Rust cannot express the overlapping specialized array
217+ /// impls that would otherwise provide this aggregate path directly.
218+ ///
219+ /// This is hidden from generated documentation for the same reason as [Read::read_vec].
220+ #[ doc( hidden) ]
221+ #[ inline]
222+ fn read_array < const N : usize > ( buf : & mut impl Buf , cfg : & Self :: Cfg ) -> Result < [ Self ; N ] , Error > {
223+ Ok ( Self :: read_vec ( buf, N , cfg) ?
224+ . try_into ( )
225+ . unwrap_or_else ( |_| unreachable ! ( "array length should match capacity" ) ) )
226+ }
74227}
75228
76229/// Trait combining [Write] and [EncodeSize] for types that can be fully encoded.
0 commit comments