@@ -12,6 +12,96 @@ use alloc::vec::Vec;
1212use base64_ng:: { Alphabet , DecodeError , EncodeError , Engine } ;
1313use bytes:: { Buf , BufMut , Bytes } ;
1414
15+ /// Encoding error for bounded `bytes` integration helpers.
16+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
17+ pub enum BytesEncodeError {
18+ /// The input buffer reports more remaining bytes than the caller permits.
19+ InputTooLarge {
20+ /// Remaining input bytes reported by [`Buf::remaining`].
21+ input_len : usize ,
22+ /// Caller-provided maximum input bytes.
23+ max_input_len : usize ,
24+ } ,
25+ /// Base64 encoding failed after the input-size check passed.
26+ Encode ( EncodeError ) ,
27+ }
28+
29+ impl core:: fmt:: Display for BytesEncodeError {
30+ fn fmt ( & self , formatter : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
31+ match self {
32+ Self :: InputTooLarge {
33+ input_len,
34+ max_input_len,
35+ } => write ! (
36+ formatter,
37+ "bytes input length {input_len} exceeds limit {max_input_len}"
38+ ) ,
39+ Self :: Encode ( error) => core:: fmt:: Display :: fmt ( error, formatter) ,
40+ }
41+ }
42+ }
43+
44+ #[ cfg( feature = "std" ) ]
45+ impl std:: error:: Error for BytesEncodeError {
46+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
47+ match self {
48+ Self :: InputTooLarge { .. } => None ,
49+ Self :: Encode ( error) => Some ( error) ,
50+ }
51+ }
52+ }
53+
54+ impl From < EncodeError > for BytesEncodeError {
55+ fn from ( error : EncodeError ) -> Self {
56+ Self :: Encode ( error)
57+ }
58+ }
59+
60+ /// Decoding error for bounded `bytes` integration helpers.
61+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
62+ pub enum BytesDecodeError {
63+ /// The input buffer reports more remaining bytes than the caller permits.
64+ InputTooLarge {
65+ /// Remaining input bytes reported by [`Buf::remaining`].
66+ input_len : usize ,
67+ /// Caller-provided maximum input bytes.
68+ max_input_len : usize ,
69+ } ,
70+ /// Base64 decoding failed after the input-size check passed.
71+ Decode ( DecodeError ) ,
72+ }
73+
74+ impl core:: fmt:: Display for BytesDecodeError {
75+ fn fmt ( & self , formatter : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
76+ match self {
77+ Self :: InputTooLarge {
78+ input_len,
79+ max_input_len,
80+ } => write ! (
81+ formatter,
82+ "bytes input length {input_len} exceeds limit {max_input_len}"
83+ ) ,
84+ Self :: Decode ( error) => core:: fmt:: Display :: fmt ( error, formatter) ,
85+ }
86+ }
87+ }
88+
89+ #[ cfg( feature = "std" ) ]
90+ impl std:: error:: Error for BytesDecodeError {
91+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
92+ match self {
93+ Self :: InputTooLarge { .. } => None ,
94+ Self :: Decode ( error) => Some ( error) ,
95+ }
96+ }
97+ }
98+
99+ impl From < DecodeError > for BytesDecodeError {
100+ fn from ( error : DecodeError ) -> Self {
101+ Self :: Decode ( error)
102+ }
103+ }
104+
15105/// Extension helpers for [`base64_ng::Engine`] and `bytes` buffers.
16106pub trait EngineBytesExt < A , const PAD : bool >
17107where
@@ -43,6 +133,26 @@ where
43133 where
44134 B : Buf ;
45135
136+ /// Encodes at most `max_input_len` remaining bytes from `input` into a
137+ /// [`Bytes`] value.
138+ ///
139+ /// Use this variant for peer-controlled or metadata-declared frame sizes.
140+ /// The input buffer is not collected if [`Buf::remaining`] exceeds
141+ /// `max_input_len`.
142+ ///
143+ /// # Errors
144+ ///
145+ /// Returns [`BytesEncodeError::InputTooLarge`] if `input.remaining()`
146+ /// exceeds `max_input_len`, or [`BytesEncodeError::Encode`] if Base64
147+ /// encoding fails.
148+ fn encode_buf_limited < B > (
149+ & self ,
150+ input : B ,
151+ max_input_len : usize ,
152+ ) -> Result < Bytes , BytesEncodeError >
153+ where
154+ B : Buf ;
155+
46156 /// Decodes all remaining bytes from `input` into a [`Bytes`] value.
47157 ///
48158 /// # Errors
@@ -52,6 +162,26 @@ where
52162 where
53163 B : Buf ;
54164
165+ /// Decodes at most `max_input_len` remaining Base64 bytes from `input`
166+ /// into a [`Bytes`] value.
167+ ///
168+ /// Use this variant for peer-controlled or metadata-declared frame sizes.
169+ /// The input buffer is not collected if [`Buf::remaining`] exceeds
170+ /// `max_input_len`.
171+ ///
172+ /// # Errors
173+ ///
174+ /// Returns [`BytesDecodeError::InputTooLarge`] if `input.remaining()`
175+ /// exceeds `max_input_len`, or [`BytesDecodeError::Decode`] if Base64
176+ /// decoding fails.
177+ fn decode_buf_limited < B > (
178+ & self ,
179+ input : B ,
180+ max_input_len : usize ,
181+ ) -> Result < Bytes , BytesDecodeError >
182+ where
183+ B : Buf ;
184+
55185 /// Encodes all remaining bytes from `input` into `output`.
56186 ///
57187 /// # Errors
@@ -63,6 +193,25 @@ where
63193 B : Buf ,
64194 M : BufMut ;
65195
196+ /// Encodes at most `max_input_len` remaining bytes from `input` into
197+ /// `output`.
198+ ///
199+ /// # Errors
200+ ///
201+ /// Returns [`BytesEncodeError::InputTooLarge`] if `input.remaining()`
202+ /// exceeds `max_input_len`, [`BytesEncodeError::Encode`] with
203+ /// [`EncodeError::OutputTooSmall`] if `output` is too small, or another
204+ /// wrapped [`EncodeError`] if Base64 encoding fails.
205+ fn encode_buf_to_mut_limited < B , M > (
206+ & self ,
207+ input : B ,
208+ output : & mut M ,
209+ max_input_len : usize ,
210+ ) -> Result < usize , BytesEncodeError >
211+ where
212+ B : Buf ,
213+ M : BufMut ;
214+
66215 /// Decodes all remaining Base64 bytes from `input` into `output`.
67216 ///
68217 /// # Errors
@@ -74,6 +223,25 @@ where
74223 where
75224 B : Buf ,
76225 M : BufMut ;
226+
227+ /// Decodes at most `max_input_len` remaining Base64 bytes from `input`
228+ /// into `output`.
229+ ///
230+ /// # Errors
231+ ///
232+ /// Returns [`BytesDecodeError::InputTooLarge`] if `input.remaining()`
233+ /// exceeds `max_input_len`, [`BytesDecodeError::Decode`] with
234+ /// [`DecodeError::OutputTooSmall`] if `output` is too small, or another
235+ /// wrapped [`DecodeError`] if Base64 decoding fails.
236+ fn decode_buf_to_mut_limited < B , M > (
237+ & self ,
238+ input : B ,
239+ output : & mut M ,
240+ max_input_len : usize ,
241+ ) -> Result < usize , BytesDecodeError >
242+ where
243+ B : Buf ,
244+ M : BufMut ;
77245}
78246
79247impl < A , const PAD : bool > EngineBytesExt < A , PAD > for Engine < A , PAD >
@@ -95,13 +263,49 @@ where
95263 self . encode_bytes ( collect_buf ( input) )
96264 }
97265
266+ fn encode_buf_limited < B > (
267+ & self ,
268+ input : B ,
269+ max_input_len : usize ,
270+ ) -> Result < Bytes , BytesEncodeError >
271+ where
272+ B : Buf ,
273+ {
274+ let input =
275+ collect_buf_limited ( input, max_input_len) . map_err ( |( input_len, max_input_len) | {
276+ BytesEncodeError :: InputTooLarge {
277+ input_len,
278+ max_input_len,
279+ }
280+ } ) ?;
281+ self . encode_bytes ( input) . map_err ( BytesEncodeError :: Encode )
282+ }
283+
98284 fn decode_buf < B > ( & self , input : B ) -> Result < Bytes , DecodeError >
99285 where
100286 B : Buf ,
101287 {
102288 self . decode_bytes ( collect_buf ( input) )
103289 }
104290
291+ fn decode_buf_limited < B > (
292+ & self ,
293+ input : B ,
294+ max_input_len : usize ,
295+ ) -> Result < Bytes , BytesDecodeError >
296+ where
297+ B : Buf ,
298+ {
299+ let input =
300+ collect_buf_limited ( input, max_input_len) . map_err ( |( input_len, max_input_len) | {
301+ BytesDecodeError :: InputTooLarge {
302+ input_len,
303+ max_input_len,
304+ }
305+ } ) ?;
306+ self . decode_bytes ( input) . map_err ( BytesDecodeError :: Decode )
307+ }
308+
105309 fn encode_buf_to_mut < B , M > ( & self , input : B , output : & mut M ) -> Result < usize , EncodeError >
106310 where
107311 B : Buf ,
@@ -119,6 +323,28 @@ where
119323 Ok ( len)
120324 }
121325
326+ fn encode_buf_to_mut_limited < B , M > (
327+ & self ,
328+ input : B ,
329+ output : & mut M ,
330+ max_input_len : usize ,
331+ ) -> Result < usize , BytesEncodeError >
332+ where
333+ B : Buf ,
334+ M : BufMut ,
335+ {
336+ let encoded = self . encode_buf_limited ( input, max_input_len) ?;
337+ let len = encoded. len ( ) ;
338+ if output. remaining_mut ( ) < len {
339+ return Err ( BytesEncodeError :: Encode ( EncodeError :: OutputTooSmall {
340+ required : len,
341+ available : output. remaining_mut ( ) ,
342+ } ) ) ;
343+ }
344+ output. put_slice ( & encoded) ;
345+ Ok ( len)
346+ }
347+
122348 fn decode_buf_to_mut < B , M > ( & self , input : B , output : & mut M ) -> Result < usize , DecodeError >
123349 where
124350 B : Buf ,
@@ -135,6 +361,28 @@ where
135361 output. put_slice ( & decoded) ;
136362 Ok ( len)
137363 }
364+
365+ fn decode_buf_to_mut_limited < B , M > (
366+ & self ,
367+ input : B ,
368+ output : & mut M ,
369+ max_input_len : usize ,
370+ ) -> Result < usize , BytesDecodeError >
371+ where
372+ B : Buf ,
373+ M : BufMut ,
374+ {
375+ let decoded = self . decode_buf_limited ( input, max_input_len) ?;
376+ let len = decoded. len ( ) ;
377+ if output. remaining_mut ( ) < len {
378+ return Err ( BytesDecodeError :: Decode ( DecodeError :: OutputTooSmall {
379+ required : len,
380+ available : output. remaining_mut ( ) ,
381+ } ) ) ;
382+ }
383+ output. put_slice ( & decoded) ;
384+ Ok ( len)
385+ }
138386}
139387
140388fn collect_buf < B > ( mut input : B ) -> Vec < u8 >
@@ -150,3 +398,15 @@ where
150398 }
151399 output
152400}
401+
402+ fn collect_buf_limited < B > ( input : B , max_input_len : usize ) -> Result < Vec < u8 > , ( usize , usize ) >
403+ where
404+ B : Buf ,
405+ {
406+ let input_len = input. remaining ( ) ;
407+ if input_len > max_input_len {
408+ return Err ( ( input_len, max_input_len) ) ;
409+ }
410+
411+ Ok ( collect_buf ( input) )
412+ }
0 commit comments