1- //! Const generic buffer types for optimal performance.
1+ //! Buffer types for optimal performance.
22//!
3- //! This module provides buffer types with compile-time size parameters
3+ //! This module provides buffer types with specific size parameters
44//! for better performance and reduced allocations.
55
66use smallvec:: SmallVec ;
7- use std:: marker:: PhantomData ;
87
9- /// A fixed-size buffer with const generic size parameter.
10- ///
11- /// This buffer type provides stack allocation for sizes up to N bytes,
12- /// falling back to heap allocation only when the size exceeds N.
8+ /// A field buffer optimized for small field values.
139#[ derive( Debug , Clone ) ]
14- pub struct ConstBuffer < const N : usize > {
15- inner : SmallVec < [ u8 ; N ] > ,
10+ pub struct FieldBuffer {
11+ inner : SmallVec < [ u8 ; 64 ] > ,
1612}
1713
18- impl < const N : usize > ConstBuffer < N > {
14+ impl FieldBuffer {
1915 /// Creates a new empty buffer.
2016 #[ inline]
2117 pub fn new ( ) -> Self {
@@ -71,62 +67,127 @@ impl<const N: usize> ConstBuffer<N> {
7167 /// Returns true if the buffer is currently using stack allocation.
7268 #[ inline]
7369 pub fn is_inline ( & self ) -> bool {
74- // Check if we're using inline storage using SmallVec's spilled() method
7570 !self . inner . spilled ( )
7671 }
7772}
7873
79- impl < const N : usize > Default for ConstBuffer < N > {
74+ impl Default for FieldBuffer {
8075 #[ inline]
8176 fn default ( ) -> Self {
8277 Self :: new ( )
8378 }
8479}
8580
86- impl < const N : usize > AsRef < [ u8 ] > for ConstBuffer < N > {
81+ impl AsRef < [ u8 ] > for FieldBuffer {
8782 #[ inline]
8883 fn as_ref ( & self ) -> & [ u8 ] {
8984 & self . inner
9085 }
9186}
9287
93- /// Type alias for field serialization buffers.
94- pub type FieldBuffer = ConstBuffer < { crate :: FIELD_BUFFER_SIZE } > ;
88+ /// A header buffer optimized for message headers.
89+ #[ derive( Debug , Clone ) ]
90+ pub struct HeaderBuffer {
91+ inner : SmallVec < [ u8 ; 128 ] > ,
92+ }
93+
94+ impl HeaderBuffer {
95+ /// Creates a new empty buffer.
96+ #[ inline]
97+ pub fn new ( ) -> Self {
98+ Self {
99+ inner : SmallVec :: new ( ) ,
100+ }
101+ }
102+
103+ /// Returns the length of the buffer.
104+ #[ inline]
105+ pub fn len ( & self ) -> usize {
106+ self . inner . len ( )
107+ }
95108
96- /// Type alias for message header buffers.
97- pub type HeaderBuffer = ConstBuffer < { crate :: MAX_HEADER_FIELDS * 16 } > ;
109+ /// Returns true if the buffer is empty.
110+ #[ inline]
111+ pub fn is_empty ( & self ) -> bool {
112+ self . inner . is_empty ( )
113+ }
98114
99- /// A const-sized message buffer pool for efficient allocation.
100- pub struct MessageBufferPool < const N : usize , const POOL_SIZE : usize > {
101- buffers : [ ConstBuffer < N > ; POOL_SIZE ] ,
102- next_idx : usize ,
103- _phantom : PhantomData < ( ) > ,
115+ /// Extends the buffer with the given slice.
116+ #[ inline]
117+ pub fn extend_from_slice ( & mut self , slice : & [ u8 ] ) {
118+ self . inner . extend_from_slice ( slice) ;
119+ }
120+
121+ /// Returns a slice of the buffer contents.
122+ #[ inline]
123+ pub fn as_slice ( & self ) -> & [ u8 ] {
124+ & self . inner
125+ }
126+
127+ /// Clears the buffer.
128+ #[ inline]
129+ pub fn clear ( & mut self ) {
130+ self . inner . clear ( ) ;
131+ }
104132}
105133
106- impl < const N : usize , const POOL_SIZE : usize > Default for MessageBufferPool < N , POOL_SIZE > {
134+ impl Default for HeaderBuffer {
135+ #[ inline]
107136 fn default ( ) -> Self {
108137 Self :: new ( )
109138 }
110139}
111140
112- impl < const N : usize , const POOL_SIZE : usize > MessageBufferPool < N , POOL_SIZE > {
113- /// Creates a new buffer pool.
141+ /// A message buffer for larger messages.
142+ #[ derive( Debug , Clone ) ]
143+ pub struct MessageBuffer {
144+ inner : SmallVec < [ u8 ; 256 ] > ,
145+ }
146+
147+ impl MessageBuffer {
148+ /// Creates a new empty buffer.
149+ #[ inline]
114150 pub fn new ( ) -> Self {
115- let buffers = core:: array:: from_fn ( |_| ConstBuffer :: new ( ) ) ;
116151 Self {
117- buffers,
118- next_idx : 0 ,
119- _phantom : PhantomData ,
152+ inner : SmallVec :: new ( ) ,
120153 }
121154 }
122155
123- /// Gets the next available buffer from the pool.
156+ /// Returns the length of the buffer.
157+ #[ inline]
158+ pub fn len ( & self ) -> usize {
159+ self . inner . len ( )
160+ }
161+
162+ /// Returns true if the buffer is empty.
163+ #[ inline]
164+ pub fn is_empty ( & self ) -> bool {
165+ self . inner . is_empty ( )
166+ }
167+
168+ /// Extends the buffer with the given slice.
124169 #[ inline]
125- pub fn get_buffer ( & mut self ) -> & mut ConstBuffer < N > {
126- let buffer = & mut self . buffers [ self . next_idx ] ;
127- buffer. clear ( ) ;
128- self . next_idx = ( self . next_idx + 1 ) % POOL_SIZE ;
129- buffer
170+ pub fn extend_from_slice ( & mut self , slice : & [ u8 ] ) {
171+ self . inner . extend_from_slice ( slice) ;
172+ }
173+
174+ /// Returns a slice of the buffer contents.
175+ #[ inline]
176+ pub fn as_slice ( & self ) -> & [ u8 ] {
177+ & self . inner
178+ }
179+
180+ /// Clears the buffer.
181+ #[ inline]
182+ pub fn clear ( & mut self ) {
183+ self . inner . clear ( ) ;
184+ }
185+ }
186+
187+ impl Default for MessageBuffer {
188+ #[ inline]
189+ fn default ( ) -> Self {
190+ Self :: new ( )
130191 }
131192}
132193
@@ -135,48 +196,31 @@ mod tests {
135196 use super :: * ;
136197
137198 #[ test]
138- fn test_const_buffer_inline ( ) {
139- let mut buffer: ConstBuffer < 64 > = ConstBuffer :: new ( ) ;
199+ fn test_field_buffer ( ) {
200+ let mut buffer = FieldBuffer :: new ( ) ;
140201 assert ! ( buffer. is_empty( ) ) ;
141202 assert ! ( buffer. is_inline( ) ) ;
142203
143- // Add data that fits in stack allocation
144204 buffer. extend_from_slice ( b"Hello, World!" ) ;
145205 assert_eq ! ( buffer. as_slice( ) , b"Hello, World!" ) ;
146206 assert ! ( buffer. is_inline( ) ) ;
147207 }
148208
149209 #[ test]
150- fn test_const_buffer_spill ( ) {
151- let mut buffer: ConstBuffer < 8 > = ConstBuffer :: new ( ) ;
152-
153- // Add data that exceeds stack allocation
154- buffer. extend_from_slice ( b"This is a longer string that will spill to heap" ) ;
155- assert_eq ! ( buffer. len( ) , 47 ) ;
156- assert ! ( !buffer. is_inline( ) ) ;
157- }
210+ fn test_header_buffer ( ) {
211+ let mut buffer = HeaderBuffer :: new ( ) ;
212+ assert ! ( buffer. is_empty( ) ) ;
158213
159- #[ test]
160- fn test_field_buffer_alias ( ) {
161- let mut buffer: FieldBuffer = FieldBuffer :: new ( ) ;
162- buffer. extend_from_slice ( b"EUR/USD" ) ;
163- assert_eq ! ( buffer. as_slice( ) , b"EUR/USD" ) ;
214+ buffer. extend_from_slice ( b"Header data" ) ;
215+ assert_eq ! ( buffer. as_slice( ) , b"Header data" ) ;
164216 }
165217
166218 #[ test]
167- fn test_buffer_pool ( ) {
168- let mut pool: MessageBufferPool < 64 , 4 > = MessageBufferPool :: new ( ) ;
169-
170- let buffer1 = pool. get_buffer ( ) ;
171- buffer1. extend_from_slice ( b"First" ) ;
172-
173- let buffer2 = pool. get_buffer ( ) ;
174- buffer2. extend_from_slice ( b"Second" ) ;
219+ fn test_message_buffer ( ) {
220+ let mut buffer = MessageBuffer :: new ( ) ;
221+ assert ! ( buffer. is_empty( ) ) ;
175222
176- // Should wrap around and reuse buffers
177- for _ in 0 ..4 {
178- let buffer = pool. get_buffer ( ) ;
179- assert ! ( buffer. is_empty( ) ) ; // Should be cleared
180- }
223+ buffer. extend_from_slice ( b"Message data" ) ;
224+ assert_eq ! ( buffer. as_slice( ) , b"Message data" ) ;
181225 }
182226}
0 commit comments