bufkit/chunk.rs
1use crate::must_non_zero;
2
3use super::error::{
4 OutOfBounds, TryAdvanceError, TryPeekAtError, TryPeekError, TryReadError, TrySegmentError,
5};
6
7#[cfg(feature = "varint")]
8use core::num::NonZeroUsize;
9use core::ops::{Bound, RangeBounds};
10
11#[cfg(feature = "varint")]
12use varing::Varint;
13
14#[cfg(feature = "varint")]
15use super::error::{DecodeVarintAtError, DecodeVarintError};
16
17use super::panic_advance;
18
19pub use peeker::Peeker;
20pub use ref_peeker::RefPeeker;
21
22mod peeker;
23mod ref_peeker;
24
25macro_rules! peek_fixed {
26 ($($ty:ident), +$(,)?) => {
27 paste::paste! {
28 $(
29 #[doc = "Peeks a `" $ty "` value from the buffer in little-endian byte order without advancing the cursor."]
30 ///
31 /// Returns the decoded value. The buffer position remains unchanged after this operation.
32 ///
33 /// # Panics
34 ///
35 #[doc = "Panics if the buffer has fewer than `size_of::<" $ty ">()` bytes available."]
36 /// Use the `*_checked` or `try_*` variants for non-panicking peeks.
37 ///
38 /// # Examples
39 ///
40 /// ```rust
41 /// use bufkit::Chunk;
42 ///
43 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
44 /// let buf = &data[..];
45 #[doc = "assert_eq!(buf.peek_" $ty "_le(), <" $ty ">::from_le_bytes((&data[..size_of::<" $ty ">()]).try_into().unwrap()));"]
46 /// assert_eq!(buf.remaining(), data.len()); // Cursor unchanged
47 /// ```
48 #[inline]
49 fn [<peek_ $ty _le>](&self) -> $ty {
50 <$ty>::from_le_bytes(peek_array::<_, { core::mem::size_of::<$ty>() }>(self))
51 }
52
53 #[doc = "Peeks a `" $ty "` value from the buffer in little-endian byte order without advancing the cursor."]
54 ///
55 #[doc = "This is the non-panicking version of [`peek_" $ty "_le`](Chunk::peek_" $ty "_le)."]
56 /// Returns `Some(value)` if sufficient data is available, otherwise returns `None`.
57 ///
58 /// # Examples
59 ///
60 /// ```rust
61 /// use bufkit::Chunk;
62 ///
63 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
64 /// let buf = &data[..];
65 #[doc = "assert!(buf.peek_" $ty "_le_checked().is_some());"]
66 ///
67 /// let small_buf = &[0x34][..];
68 #[doc = "assert!(small_buf.peek_" $ty "_le_checked().is_none()); // Not enough bytes"]
69 /// ```
70 #[inline]
71 fn [<peek_ $ty _le_checked>](&self) -> Option<$ty> {
72 peek_array_checked::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_le_bytes)
73 }
74
75 #[doc = "Peeks a `" $ty "` value from the buffer in little-endian byte order without advancing the cursor."]
76 ///
77 #[doc = "This is the non-panicking version of [`peek_" $ty "_le`](Chunk::peek_" $ty "_le)."]
78 /// Returns `Ok(value)` on success, or `Err(TryPeekError)` with details about
79 /// requested vs available bytes.
80 ///
81 /// # Examples
82 ///
83 /// ```rust
84 /// use bufkit::Chunk;
85 ///
86 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
87 /// let buf = &data[..];
88 #[doc = "assert!(buf.try_peek_" $ty "_le().is_ok());"]
89 ///
90 /// let small_buf = &[0x34][..];
91 #[doc = "let err = small_buf.try_peek_" $ty "_le().unwrap_err();"]
92 /// // err contains details about requested vs available bytes
93 /// ```
94 #[inline]
95 fn [<try_peek_ $ty _le>](&self) -> Result<$ty, TryPeekError> {
96 try_peek_array::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_le_bytes)
97 }
98
99 #[doc = "Peeks a `" $ty "` value from the buffer in big-endian byte order without advancing the cursor."]
100 ///
101 /// Returns the decoded value. The buffer position remains unchanged after this operation.
102 ///
103 /// # Panics
104 ///
105 #[doc = "Panics if the buffer has fewer than `size_of::<" $ty ">()` bytes available."]
106 /// Use the `*_checked` or `try_*` variants for non-panicking peeks.
107 ///
108 /// # Examples
109 ///
110 /// ```rust
111 /// use bufkit::Chunk;
112 ///
113 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
114 /// let buf = &data[..];
115 #[doc = "assert_eq!(buf.peek_" $ty "_be(), <" $ty ">::from_be_bytes((&data[..size_of::<" $ty ">()]).try_into().unwrap()));"]
116 /// assert_eq!(buf.remaining(), data.len()); // Cursor unchanged
117 /// ```
118 #[inline]
119 fn [<peek_ $ty _be>](&self) -> $ty {
120 <$ty>::from_be_bytes(peek_array::<_, { core::mem::size_of::<$ty>() }>(self))
121 }
122
123 #[doc = "Peeks a `" $ty "` value from the buffer in big-endian byte order without advancing the cursor."]
124 ///
125 #[doc = "This is the non-panicking version of [`peek_" $ty "_be`](Chunk::peek_" $ty "_be)."]
126 /// Returns `Some(value)` if sufficient data is available, otherwise returns `None`.
127 ///
128 /// # Examples
129 ///
130 /// ```rust
131 /// use bufkit::Chunk;
132 ///
133 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
134 /// let buf = &data[..];
135 #[doc = "assert!(buf.peek_" $ty "_be_checked().is_some());"]
136 ///
137 /// let small_buf = &[0x12][..];
138 #[doc = "assert!(small_buf.peek_" $ty "_be_checked().is_none()); // Not enough bytes"]
139 /// ```
140 #[inline]
141 fn [<peek_ $ty _be_checked>](&self) -> Option<$ty> {
142 peek_array_checked::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_be_bytes)
143 }
144
145 #[doc = "Peeks a `" $ty "` value from the buffer in big-endian byte order without advancing the cursor."]
146 ///
147 #[doc = "This is the non-panicking version of [`peek_" $ty "_be`](Chunk::peek_" $ty "_be)."]
148 /// Returns `Ok(value)` on success, or `Err(TryPeekError)` with details about
149 /// requested vs available bytes.
150 ///
151 /// # Examples
152 ///
153 /// ```rust
154 /// use bufkit::Chunk;
155 ///
156 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
157 /// let buf = &data[..];
158 #[doc = "assert!(buf.try_peek_" $ty "_be().is_ok());"]
159 ///
160 /// let small_buf = &[0x12][..];
161 #[doc = "let err = small_buf.try_peek_" $ty "_be().unwrap_err();"]
162 /// // err contains details about requested vs available bytes
163 /// ```
164 #[inline]
165 fn [<try_peek_ $ty _be>](&self) -> Result<$ty, TryPeekError> {
166 try_peek_array::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_be_bytes)
167 }
168
169 #[doc = "Peeks a `" $ty "` value from the buffer in native-endian byte order without advancing the cursor."]
170 ///
171 /// The byte order depends on the target platform's endianness (little-endian on x86/x64,
172 /// big-endian on some embedded platforms).
173 ///
174 /// Returns the decoded value. The buffer position remains unchanged after this operation.
175 ///
176 /// # Panics
177 ///
178 #[doc = "Panics if the buffer has fewer than `size_of::<" $ty ">()` bytes available."]
179 /// Use the `*_checked` or `try_*` variants for non-panicking peeks.
180 ///
181 /// # Examples
182 ///
183 /// ```rust
184 /// use bufkit::Chunk;
185 ///
186 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
187 /// let buf = &data[..];
188 #[doc = "let value = buf.peek_" $ty "_ne();"]
189 /// assert_eq!(buf.remaining(), data.len()); // Cursor unchanged
190 /// ```
191 #[inline]
192 fn [<peek_ $ty _ne>](&self) -> $ty {
193 <$ty>::from_ne_bytes(peek_array::<_, { core::mem::size_of::<$ty>() }>(self))
194 }
195
196 #[doc = "Peeks a `" $ty "` value from the buffer in native-endian byte order without advancing the cursor."]
197 ///
198 /// The byte order depends on the target platform's endianness.
199 #[doc = "This is the non-panicking version of [`peek_" $ty "_ne`](Chunk::peek_" $ty "_ne)."]
200 /// Returns `Some(value)` if sufficient data is available, otherwise returns `None`.
201 ///
202 /// # Examples
203 ///
204 /// ```rust
205 /// use bufkit::Chunk;
206 ///
207 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
208 /// let buf = &data[..];
209 #[doc = "assert!(buf.peek_" $ty "_ne_checked().is_some());"]
210 ///
211 /// let small_buf = &[0x34][..];
212 #[doc = "assert!(small_buf.peek_" $ty "_ne_checked().is_none()); // Not enough bytes"]
213 /// ```
214 #[inline]
215 fn [<peek_ $ty _ne_checked>](&self) -> Option<$ty> {
216 peek_array_checked::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_ne_bytes)
217 }
218
219 #[doc = "Peeks a `" $ty "` value from the buffer in native-endian byte order without advancing the cursor."]
220 ///
221 /// The byte order depends on the target platform's endianness.
222 #[doc = "This is the non-panicking version of [`peek_" $ty "_ne`](Chunk::peek_" $ty "_ne)."]
223 /// Returns `Ok(value)` on success, or `Err(TryPeekError)` with details about
224 /// requested vs available bytes.
225 ///
226 /// # Examples
227 ///
228 /// ```rust
229 /// use bufkit::Chunk;
230 ///
231 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
232 /// let buf = &data[..];
233 #[doc = "assert!(buf.try_peek_" $ty "_ne().is_ok());"]
234 ///
235 /// let small_buf = &[0x34][..];
236 #[doc = "let err = small_buf.try_peek_" $ty "_ne().unwrap_err();"]
237 /// // err contains details about requested vs available bytes
238 /// ```
239 #[inline]
240 fn [<try_peek_ $ty _ne>](&self) -> Result<$ty, TryPeekError> {
241 try_peek_array::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_ne_bytes)
242 }
243
244 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in little-endian byte order."]
245 ///
246 /// Returns the decoded value without modifying the buffer position.
247 /// The offset is relative to the current buffer position.
248 ///
249 /// # Panics
250 ///
251 #[doc = "Panics if `offset + size_of::<" $ty ">() > self.remaining()`."]
252 /// Use the `*_checked` or `try_*` variants for non-panicking peeks.
253 ///
254 /// # Examples
255 ///
256 /// ```rust
257 /// use bufkit::Chunk;
258 ///
259 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
260 /// let buf = &data[..];
261 #[doc = "let value = buf.peek_" $ty "_le_at(2); // Peek at offset 2"]
262 /// assert_eq!(buf.remaining(), data.len()); // Chunkfer unchanged
263 /// ```
264 #[inline]
265 fn [<peek_ $ty _le_at>](&self, offset: usize) -> $ty {
266 <$ty>::from_le_bytes(peek_array_at::<_, { core::mem::size_of::<$ty>() }>(self, offset))
267 }
268
269 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in little-endian byte order."]
270 ///
271 #[doc = "This is the non-panicking version of [`peek_" $ty "_le_at`](Chunk::peek_" $ty "_le_at)."]
272 /// Returns `Some(value)` if sufficient data is available at the offset, otherwise returns `None`.
273 ///
274 /// # Examples
275 ///
276 /// ```rust
277 /// use bufkit::Chunk;
278 ///
279 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
280 /// let buf = &data[..];
281 #[doc = "assert!(buf.peek_" $ty "_le_at_checked(2).is_some());"]
282 #[doc = "assert!(buf.peek_" $ty "_le_at_checked(100).is_none()); // Out of bounds"]
283 /// ```
284 #[inline]
285 fn [<peek_ $ty _le_at_checked>](&self, offset: usize) -> Option<$ty> {
286 peek_array_at_checked::<_, { core::mem::size_of::<$ty>() }>(self, offset).map(<$ty>::from_le_bytes)
287 }
288
289 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in little-endian byte order."]
290 ///
291 #[doc = "This is the non-panicking version of [`peek_" $ty "_le_at`](Chunk::peek_" $ty "_le_at)."]
292 /// Returns `Ok(value)` on success, or `Err(TryPeekAtError)` with details about
293 /// the error condition (out of bounds or insufficient data).
294 ///
295 /// # Examples
296 ///
297 /// ```rust
298 /// use bufkit::Chunk;
299 ///
300 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
301 /// let buf = &data[..];
302 #[doc = "assert!(buf.try_peek_" $ty "_le_at(2).is_ok());"]
303 #[doc = "let err = buf.try_peek_" $ty "_le_at(100).unwrap_err();"]
304 /// // err contains details about the error
305 /// ```
306 #[inline]
307 fn [<try_peek_ $ty _le_at>](&self, offset: usize) -> Result<$ty, TryPeekAtError> {
308 try_peek_array_at::<_, { core::mem::size_of::<$ty>() }>(self, offset).map(<$ty>::from_le_bytes)
309 }
310
311 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in big-endian byte order."]
312 ///
313 /// Returns the decoded value without modifying the buffer position.
314 /// The offset is relative to the current buffer position.
315 ///
316 /// # Panics
317 ///
318 #[doc = "Panics if `offset + size_of::<" $ty ">() > self.remaining()`."]
319 /// Use the `*_checked` or `try_*` variants for non-panicking peeks.
320 ///
321 /// # Examples
322 ///
323 /// ```rust
324 /// use bufkit::Chunk;
325 ///
326 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
327 /// let buf = &data[..];
328 #[doc = "let value = buf.peek_" $ty "_be_at(2); // Peek at offset 2"]
329 /// assert_eq!(buf.remaining(), data.len()); // Chunkfer unchanged
330 /// ```
331 #[inline]
332 fn [<peek_ $ty _be_at>](&self, offset: usize) -> $ty {
333 <$ty>::from_be_bytes(peek_array_at::<_, { core::mem::size_of::<$ty>() }>(self, offset))
334 }
335
336 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in big-endian byte order."]
337 ///
338 #[doc = "This is the non-panicking version of [`peek_" $ty "_be_at`](Chunk::peek_" $ty "_be_at)."]
339 /// Returns `Some(value)` if sufficient data is available at the offset, otherwise returns `None`.
340 ///
341 /// # Examples
342 ///
343 /// ```rust
344 /// use bufkit::Chunk;
345 ///
346 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
347 /// let buf = &data[..];
348 #[doc = "assert!(buf.peek_" $ty "_be_at_checked(2).is_some());"]
349 #[doc = "assert!(buf.peek_" $ty "_be_at_checked(100).is_none()); // Out of bounds"]
350 /// ```
351 #[inline]
352 fn [<peek_ $ty _be_at_checked>](&self, offset: usize) -> Option<$ty> {
353 peek_array_at_checked::<_, { core::mem::size_of::<$ty>() }>(self, offset).map(<$ty>::from_be_bytes)
354 }
355
356 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in big-endian byte order."]
357 ///
358 #[doc = "This is the non-panicking version of [`peek_" $ty "_be_at`](Chunk::peek_" $ty "_be_at)."]
359 /// Returns `Ok(value)` on success, or `Err(TryPeekAtError)` with details about
360 /// the error condition (out of bounds or insufficient data).
361 ///
362 /// # Examples
363 ///
364 /// ```rust
365 /// use bufkit::Chunk;
366 ///
367 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
368 /// let buf = &data[..];
369 #[doc = "assert!(buf.try_peek_" $ty "_be_at(2).is_ok());"]
370 #[doc = "let err = buf.try_peek_" $ty "_be_at(100).unwrap_err();"]
371 /// // err contains details about the error
372 /// ```
373 #[inline]
374 fn [<try_peek_ $ty _be_at>](&self, offset: usize) -> Result<$ty, TryPeekAtError> {
375 try_peek_array_at::<_, { core::mem::size_of::<$ty>() }>(self, offset).map(<$ty>::from_be_bytes)
376 }
377
378 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in native-endian byte order."]
379 ///
380 /// The byte order depends on the target platform's endianness.
381 /// Returns the decoded value without modifying the buffer position.
382 /// The offset is relative to the current buffer position.
383 ///
384 /// # Panics
385 ///
386 #[doc = "Panics if `offset + size_of::<" $ty ">() > self.remaining()`."]
387 /// Use the `*_checked` or `try_*` variants for non-panicking peeks.
388 ///
389 /// # Examples
390 ///
391 /// ```rust
392 /// use bufkit::Chunk;
393 ///
394 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
395 /// let buf = &data[..];
396 #[doc = "let value = buf.peek_" $ty "_ne_at(2); // Peek at offset 2"]
397 /// assert_eq!(buf.remaining(), data.len()); // Chunkfer unchanged
398 /// ```
399 #[inline]
400 fn [<peek_ $ty _ne_at>](&self, offset: usize) -> $ty {
401 <$ty>::from_ne_bytes(peek_array_at::<_, { core::mem::size_of::<$ty>() }>(self, offset))
402 }
403
404 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in native-endian byte order."]
405 ///
406 /// The byte order depends on the target platform's endianness.
407 #[doc = "This is the non-panicking version of [`peek_" $ty "_ne_at`](Chunk::peek_" $ty "_ne_at)."]
408 /// Returns `Some(value)` if sufficient data is available at the offset, otherwise returns `None`.
409 ///
410 /// # Examples
411 ///
412 /// ```rust
413 /// use bufkit::Chunk;
414 ///
415 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
416 /// let buf = &data[..];
417 #[doc = "assert!(buf.peek_" $ty "_ne_at_checked(2).is_some());"]
418 #[doc = "assert!(buf.peek_" $ty "_ne_at_checked(100).is_none()); // Out of bounds"]
419 /// ```
420 #[inline]
421 fn [<peek_ $ty _ne_at_checked>](&self, offset: usize) -> Option<$ty> {
422 peek_array_at_checked::<_, { core::mem::size_of::<$ty>() }>(self, offset).map(<$ty>::from_ne_bytes)
423 }
424
425 #[doc = "Peeks a `" $ty "` value from the buffer at the specified offset in native-endian byte order."]
426 ///
427 /// The byte order depends on the target platform's endianness.
428 #[doc = "This is the non-panicking version of [`peek_" $ty "_ne_at`](Chunk::peek_" $ty "_ne_at)."]
429 /// Returns `Ok(value)` on success, or `Err(TryPeekAtError)` with details about
430 /// the error condition (out of bounds or insufficient data).
431 ///
432 /// # Examples
433 ///
434 /// ```rust
435 /// use bufkit::Chunk;
436 ///
437 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
438 /// let buf = &data[..];
439 #[doc = "assert!(buf.try_peek_" $ty "_ne_at(0).is_ok());"]
440 #[doc = "let err = buf.try_peek_" $ty "_ne_at(100).unwrap_err();"]
441 /// // err contains details about the error
442 /// ```
443 #[inline]
444 fn [<try_peek_ $ty _ne_at>](&self, offset: usize) -> Result<$ty, TryPeekAtError> {
445 try_peek_array_at::<_, { core::mem::size_of::<$ty>() }>(self, offset).map(<$ty>::from_ne_bytes)
446 }
447 )*
448 }
449 };
450 (@forward $($ty:ident), +$(,)?) => {
451 paste::paste! {
452 $(
453 #[inline]
454 fn [<peek_ $ty _le>](&self) -> $ty {
455 (**self).[<peek_ $ty _le>]()
456 }
457
458 #[inline]
459 fn [<peek_ $ty _le_checked>](&self) -> Option<$ty> {
460 (**self).[<peek_ $ty _le_checked>]()
461 }
462
463 #[inline]
464 fn [<try_peek_ $ty _le>](&self) -> Result<$ty, TryPeekError> {
465 (**self).[<try_peek_ $ty _le>]()
466 }
467
468 #[inline]
469 fn [<peek_ $ty _be>](&self) -> $ty {
470 (**self).[<peek_ $ty _be>]()
471 }
472
473 #[inline]
474 fn [<peek_ $ty _be_checked>](&self) -> Option<$ty> {
475 (**self).[<peek_ $ty _be_checked>]()
476 }
477
478 #[inline]
479 fn [<try_peek_ $ty _be>](&self) -> Result<$ty, TryPeekError> {
480 (**self).[<try_peek_ $ty _be>]()
481 }
482
483 #[inline]
484 fn [<peek_ $ty _ne>](&self) -> $ty {
485 (**self).[<peek_ $ty _ne>]()
486 }
487
488 #[inline]
489 fn [<peek_ $ty _ne_checked>](&self) -> Option<$ty> {
490 (**self).[<peek_ $ty _ne_checked>]()
491 }
492
493 #[inline]
494 fn [<try_peek_ $ty _ne>](&self) -> Result<$ty, TryPeekError> {
495 (**self).[<try_peek_ $ty _ne>]()
496 }
497
498 #[inline]
499 fn [<peek_ $ty _le_at>](&self, offset: usize) -> $ty {
500 (**self).[<peek_ $ty _le_at>](offset)
501 }
502
503 #[inline]
504 fn [<peek_ $ty _le_at_checked>](&self, offset: usize) -> Option<$ty> {
505 (**self).[<peek_ $ty _le_at_checked>](offset)
506 }
507
508 #[inline]
509 fn [<try_peek_ $ty _le_at>](&self, offset: usize) -> Result<$ty, TryPeekAtError> {
510 (**self).[<try_peek_ $ty _le_at>](offset)
511 }
512
513 #[inline]
514 fn [<peek_ $ty _be_at>](&self, offset: usize) -> $ty {
515 (**self).[<peek_ $ty _be_at>](offset)
516 }
517
518 #[inline]
519 fn [<peek_ $ty _be_at_checked>](&self, offset: usize) -> Option<$ty> {
520 (**self).[<peek_ $ty _be_at_checked>](offset)
521 }
522
523 #[inline]
524 fn [<try_peek_ $ty _be_at>](&self, offset: usize) -> Result<$ty, TryPeekAtError> {
525 (**self).[<try_peek_ $ty _be_at>](offset)
526 }
527
528 #[inline]
529 fn [<peek_ $ty _ne_at>](&self, offset: usize) -> $ty {
530 (**self).[<peek_ $ty _ne_at>](offset)
531 }
532
533 #[inline]
534 fn [<peek_ $ty _ne_at_checked>](&self, offset: usize) -> Option<$ty> {
535 (**self).[<peek_ $ty _ne_at_checked>](offset)
536 }
537
538 #[inline]
539 fn [<try_peek_ $ty _ne_at>](&self, offset: usize) -> Result<$ty, TryPeekAtError> {
540 (**self).[<try_peek_ $ty _ne_at>](offset)
541 }
542 )*
543 }
544 };
545}
546
547macro_rules! read_fixed {
548 ($($ty:ident), +$(,)?) => {
549 paste::paste! {
550 $(
551 #[doc = "Reads a `" $ty "` value from the buffer in little-endian byte order and advances the cursor."]
552 ///
553 #[doc = "Returns the decoded value and advances the cursor by `size_of::<" $ty ">()` bytes."]
554 ///
555 /// # Panics
556 ///
557 #[doc = "Panics if the buffer has fewer than `size_of::<" $ty ">()` bytes available."]
558 /// Use the `*_checked` or `try_*` variants for non-panicking reads.
559 ///
560 /// # Examples
561 ///
562 /// ```rust
563 /// use bufkit::Chunk;
564 ///
565 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
566 /// let mut buf = &data[..];
567 #[doc = "let value = buf.read_" $ty "_le();"]
568 #[doc = "assert_eq!(buf.remaining(), data.len() - size_of::<" $ty ">()); // Cursor advanced"]
569 /// ```
570 #[inline]
571 fn [<read_ $ty _le>](&mut self) -> $ty {
572 <$ty>::from_le_bytes(read_array::<_, { core::mem::size_of::<$ty>() }>(self))
573 }
574
575 #[doc = "Reads a `" $ty "` value from the buffer in little-endian byte order and advances the cursor."]
576 ///
577 #[doc = "This is the non-panicking version of [`read_" $ty "_le`](Chunk::read_" $ty "_le)."]
578 /// Returns `Some(value)` and advances the cursor on success, or `None` if insufficient data.
579 ///
580 /// # Examples
581 ///
582 /// ```rust
583 /// use bufkit::Chunk;
584 ///
585 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
586 /// let mut buf = &data[..];
587 #[doc = "if let Some(value) = buf.read_" $ty "_le_checked() {"]
588 #[doc = " // Cursor advanced by size_of::<" $ty ">()"]
589 /// } else {
590 /// // Not enough data, cursor unchanged
591 /// }
592 /// ```
593 #[inline]
594 fn [<read_ $ty _le_checked>](&mut self) -> Option<$ty> {
595 read_array_checked::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_le_bytes)
596 }
597
598 #[doc = "Reads a `" $ty "` value from the buffer in little-endian byte order and advances the cursor."]
599 ///
600 #[doc = "This is the non-panicking version of [`read_" $ty "_le`](Chunk::read_" $ty "_le)."]
601 /// Returns `Ok(value)` and advances the cursor on success, or `Err(TryReadError)`
602 /// with details about requested vs available bytes.
603 ///
604 /// # Examples
605 ///
606 /// ```rust
607 /// use bufkit::Chunk;
608 ///
609 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
610 /// let mut buf = &data[..];
611 #[doc = "match buf.try_read_" $ty "_le() {"]
612 /// Ok(value) => {
613 #[doc = " // Cursor advanced by size_of::<" $ty ">()"]
614 /// },
615 /// Err(e) => {
616 /// // e contains details about requested vs available bytes
617 /// }
618 /// }
619 /// ```
620 #[inline]
621 fn [<try_read_ $ty _le>](&mut self) -> Result<$ty, TryReadError> {
622 try_read_array::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_le_bytes)
623 }
624
625 #[doc = "Reads a `" $ty "` value from the buffer in big-endian byte order and advances the cursor."]
626 ///
627 #[doc = "Returns the decoded value and advances the cursor by `size_of::<" $ty ">()` bytes."]
628 ///
629 /// # Panics
630 ///
631 #[doc = "Panics if the buffer has fewer than `size_of::<" $ty ">()` bytes available."]
632 /// Use the `*_checked` or `try_*` variants for non-panicking reads.
633 ///
634 /// # Examples
635 ///
636 /// ```rust
637 /// use bufkit::Chunk;
638 ///
639 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
640 /// let mut buf = &data[..];
641 #[doc = "let value = buf.read_" $ty "_be();"]
642 #[doc = "assert_eq!(buf.remaining(), data.len() - size_of::<" $ty ">()); // Cursor advanced"]
643 /// ```
644 #[inline]
645 fn [<read_ $ty _be>](&mut self) -> $ty {
646 <$ty>::from_be_bytes(read_array::<_, { core::mem::size_of::<$ty>() }>(self))
647 }
648
649 #[doc = "Reads a `" $ty "` value from the buffer in big-endian byte order and advances the cursor."]
650 ///
651 #[doc = "This is the non-panicking version of [`read_" $ty "_be`](Chunk::read_" $ty "_be)."]
652 /// Returns `Some(value)` and advances the cursor on success, or `None` if insufficient data.
653 ///
654 /// # Examples
655 ///
656 /// ```rust
657 /// use bufkit::Chunk;
658 ///
659 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
660 /// let mut buf = &data[..];
661 #[doc = "if let Some(value) = buf.read_" $ty "_be_checked() {"]
662 #[doc = " // Cursor advanced by size_of::<" $ty ">()"]
663 /// } else {
664 /// // Not enough data, cursor unchanged
665 /// }
666 /// ```
667 #[inline]
668 fn [<read_ $ty _be_checked>](&mut self) -> Option<$ty> {
669 read_array_checked::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_be_bytes)
670 }
671
672 #[doc = "Reads a `" $ty "` value from the buffer in big-endian byte order and advances the cursor."]
673 ///
674 #[doc = "This is the non-panicking version of [`read_" $ty "_be`](Chunk::read_" $ty "_be)."]
675 /// Returns `Ok(value)` and advances the cursor on success, or `Err(TryReadError)`
676 /// with details about requested vs available bytes.
677 ///
678 /// # Examples
679 ///
680 /// ```rust
681 /// use bufkit::Chunk;
682 ///
683 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
684 /// let mut buf = &data[..];
685 #[doc = "match buf.try_read_" $ty "_be() {"]
686 /// Ok(value) => {
687 #[doc = " // Cursor advanced by size_of::<" $ty ">()"]
688 /// },
689 /// Err(e) => {
690 /// // e contains details about requested vs available bytes
691 /// }
692 /// }
693 /// ```
694 #[inline]
695 fn [<try_read_ $ty _be>](&mut self) -> Result<$ty, TryReadError> {
696 try_read_array::<_, { core::mem::size_of::<$ty>() }>(self).map(|val| { <$ty>::from_be_bytes(val) })
697 }
698
699 #[doc = "Reads a `" $ty "` value from the buffer in native-endian byte order and advances the cursor."]
700 ///
701 /// The byte order depends on the target platform's endianness (little-endian on x86/x64,
702 /// big-endian on some embedded platforms).
703 ///
704 #[doc = "Returns the decoded value and advances the cursor by `size_of::<" $ty ">()` bytes."]
705 ///
706 /// # Panics
707 ///
708 #[doc = "Panics if the buffer has fewer than `size_of::<" $ty ">()` bytes available."]
709 /// Use the `*_checked` or `try_*` variants for non-panicking reads.
710 ///
711 /// # Examples
712 ///
713 /// ```rust
714 /// use bufkit::Chunk;
715 ///
716 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
717 /// let mut buf = &data[..];
718 #[doc = "let value = buf.read_" $ty "_ne();"]
719 #[doc = "assert_eq!(buf.remaining(), data.len() - size_of::<" $ty ">()); // Cursor advanced"]
720 /// ```
721 #[inline]
722 fn [<read_ $ty _ne>](&mut self) -> $ty {
723 <$ty>::from_ne_bytes(read_array::<_, { core::mem::size_of::<$ty>() }>(self))
724 }
725
726 #[doc = "Reads a `" $ty "` value from the buffer in native-endian byte order and advances the cursor."]
727 ///
728 /// The byte order depends on the target platform's endianness.
729 #[doc = "This is the non-panicking version of [`read_" $ty "_ne`](Chunk::read_" $ty "_ne)."]
730 /// Returns `Some(value)` and advances the cursor on success, or `None` if insufficient data.
731 ///
732 /// # Examples
733 ///
734 /// ```rust
735 /// use bufkit::Chunk;
736 ///
737 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
738 /// let mut buf = &data[..];
739 #[doc = "if let Some(value) = buf.read_" $ty "_ne_checked() {"]
740 #[doc = " // Cursor advanced by size_of::<" $ty ">()"]
741 /// } else {
742 /// // Not enough data, cursor unchanged
743 /// }
744 /// ```
745 #[inline]
746 fn [<read_ $ty _ne_checked>](&mut self) -> Option<$ty> {
747 read_array_checked::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_ne_bytes)
748 }
749
750 #[doc = "Reads a `" $ty "` value from the buffer in native-endian byte order and advances the cursor."]
751 ///
752 /// The byte order depends on the target platform's endianness.
753 #[doc = "This is the non-panicking version of [`read_" $ty "_ne`](Chunk::read_" $ty "_ne)."]
754 /// Returns `Ok(value)` and advances the cursor on success, or `Err(TryReadError)`
755 /// with details about requested vs available bytes.
756 ///
757 /// # Examples
758 ///
759 /// ```rust
760 /// use bufkit::Chunk;
761 ///
762 /// let data = [147, 23, 89, 201, 156, 74, 33, 198, 67, 142, 91, 205, 38, 177, 124, 59, 183, 96, 241, 167, 82, 135, 49, 213];
763 /// let mut buf = &data[..];
764 #[doc = "match buf.try_read_" $ty "_ne() {"]
765 /// Ok(value) => {
766 #[doc = " // Cursor advanced by size_of::<" $ty ">()"]
767 /// },
768 /// Err(e) => {
769 /// // e contains details about requested vs available bytes
770 /// }
771 /// }
772 /// ```
773 #[inline]
774 fn [<try_read_ $ty _ne>](&mut self) -> Result<$ty, TryReadError> {
775 try_read_array::<_, { core::mem::size_of::<$ty>() }>(self).map(<$ty>::from_ne_bytes)
776 }
777 )*
778 }
779 };
780 (@forward $($ty:ident), +$(,)?) => {
781 paste::paste! {
782 $(
783 #[inline]
784 fn [<read_ $ty _le>](&mut self) -> $ty {
785 (**self).[<read_ $ty _le>]()
786 }
787
788 #[inline]
789 fn [<read_ $ty _le_checked>](&mut self) -> Option<$ty> {
790 (**self).[<read_ $ty _le_checked>]()
791 }
792
793 #[inline]
794 fn [<try_read_ $ty _le>](&mut self) -> Result<$ty, TryReadError> {
795 (**self).[<try_read_ $ty _le>]()
796 }
797
798 #[inline]
799 fn [<read_ $ty _be>](&mut self) -> $ty {
800 (**self).[<read_ $ty _be>]()
801 }
802
803 #[inline]
804 fn [<read_ $ty _be_checked>](&mut self) -> Option<$ty> {
805 (**self).[<read_ $ty _be_checked>]()
806 }
807
808 #[inline]
809 fn [<try_read_ $ty _be>](&mut self) -> Result<$ty, TryReadError> {
810 (**self).[<try_read_ $ty _be>]()
811 }
812
813 #[inline]
814 fn [<read_ $ty _ne>](&mut self) -> $ty {
815 (**self).[<read_ $ty _ne>]()
816 }
817
818 #[inline]
819 fn [<read_ $ty _ne_checked>](&mut self) -> Option<$ty> {
820 (**self).[<read_ $ty _ne_checked>]()
821 }
822
823 #[inline]
824 fn [<try_read_ $ty _ne>](&mut self) -> Result<$ty, TryReadError> {
825 (**self).[<try_read_ $ty _ne>]()
826 }
827 )*
828 }
829 };
830}
831
832/// A trait for implementing custom buffers that can read and navigate through byte sequences.
833///
834/// This trait provides a comprehensive set of methods for reading data from buffers with different
835/// error handling strategies:
836/// - **Panicking methods** (e.g., `read_*`): Fast operations that panic on insufficient data
837/// - **Checked methods** (e.g., `*_checked`): Return `Option` - `None` on failure, `Some(value)` on success
838/// - **Fallible methods** (e.g., `try_*`): Return `Result` with detailed error information
839///
840/// # Method Categories
841///
842/// - **Chunkfer inspection**: `remaining()`, `has_remaining()`, `buffer()`
843/// - **Navigation**: `advance()`, `try_advance()`
844/// - **Chunkfer manipulation**: `truncate()`, `split_to()`, `split_off()`, `segment()`
845/// - **Peeking data**: `peek_u8()`, `peek_u16_le()`, etc. (read without advancing)
846/// - **Reading data**: `read_u8()`, `read_u16_le()`, etc. (read and advance cursor)
847pub trait Chunk {
848 /// Returns the number of bytes available for reading in the buffer.
849 ///
850 /// This represents how many bytes can be read from the current cursor position
851 /// to the end of the buffer.
852 ///
853 /// # Examples
854 ///
855 /// ```rust
856 /// use bufkit::Chunk;
857 ///
858 /// let data = [1, 2, 3, 4, 5];
859 /// let mut buf = &data[..];
860 /// assert_eq!(buf.remaining(), 5);
861 ///
862 /// buf.advance(2);
863 /// assert_eq!(buf.remaining(), 3);
864 /// ```
865 fn remaining(&self) -> usize;
866
867 /// Returns the remaining bytes of the buffer as a slice.
868 ///
869 /// This provides direct access to all bytes from the current cursor position
870 /// to the end of the buffer.
871 ///
872 /// # Examples
873 ///
874 /// ```rust
875 /// use bufkit::Chunk;
876 ///
877 /// let data = [1, 2, 3, 4, 5];
878 /// let mut buf = &data[..];
879 /// assert_eq!(buf.buffer(), &[1, 2, 3, 4, 5]);
880 ///
881 /// buf.advance(2);
882 /// assert_eq!(buf.buffer(), &[3, 4, 5]);
883 /// ```
884 fn buffer(&self) -> &[u8];
885
886 /// Returns a slice of the buffer starting from the specified offset.
887 ///
888 /// This is similar to [`buffer`](Chunk::buffer) but starts from the given offset
889 /// rather than the current cursor position.
890 ///
891 /// # Panics
892 ///
893 /// Panics if `offset > self.remaining()`.
894 /// Use [`buffer_from_checked`](Chunk::buffer_from_checked) for non-panicking access.
895 ///
896 /// # Examples
897 ///
898 /// ```rust
899 /// use bufkit::Chunk;
900 ///
901 /// let data = [1u8, 2, 3, 4, 5];
902 /// let buf = &data[..];
903 ///
904 /// assert_eq!(buf.buffer(), &[1, 2, 3, 4, 5]);
905 /// assert_eq!(buf.buffer_from(2), &[3, 4, 5]);
906 /// ```
907 #[inline]
908 fn buffer_from(&self, offset: usize) -> &[u8] {
909 &self.buffer()[offset..]
910 }
911
912 /// Returns a slice of the buffer starting from the specified offset.
913 ///
914 /// This is the non-panicking version of [`buffer_from`](Chunk::buffer_from).
915 /// Returns `Some(slice)` if `offset <= self.remaining()`, otherwise returns `None`.
916 ///
917 /// # Examples
918 ///
919 /// ```rust
920 /// use bufkit::Chunk;
921 ///
922 /// let data = [1u8, 2, 3, 4, 5];
923 /// let buf = &data[..];
924 ///
925 /// assert_eq!(buf.buffer_from_checked(2), Some(&[3, 4, 5][..]));
926 /// assert!(buf.buffer_from_checked(5).unwrap().is_empty()); // empty buffer
927 /// assert_eq!(buf.buffer_from_checked(10), None); // Out of bounds
928 /// ```
929 #[inline]
930 fn buffer_from_checked(&self, offset: usize) -> Option<&[u8]> {
931 if offset > self.remaining() {
932 None
933 } else {
934 Some(&self.buffer()[offset..])
935 }
936 }
937
938 /// Advances the internal cursor by the specified number of bytes.
939 ///
940 /// This moves the read position forward, making the advanced bytes no longer
941 /// available for reading. The operation consumes the bytes without returning them.
942 ///
943 /// # Panics
944 ///
945 /// Panics if `cnt > self.remaining()`.
946 /// Use [`try_advance`](Chunk::try_advance) for non-panicking advancement.
947 ///
948 /// # Examples
949 ///
950 /// ```rust
951 /// use bufkit::Chunk;
952 ///
953 /// let data = [1, 2, 3, 4, 5];
954 /// let mut buf = &data[..];
955 ///
956 /// buf.advance(2);
957 /// assert_eq!(buf.remaining(), 3);
958 /// assert_eq!(buf.buffer(), &[3, 4, 5]);
959 /// ```
960 fn advance(&mut self, cnt: usize);
961
962 /// Returns a slice containing the first `len` bytes of the buffer.
963 ///
964 /// This provides access to a prefix of the buffer for efficient manipulation
965 /// of a specific portion without affecting the rest of the buffer.
966 ///
967 /// # Panics
968 ///
969 /// Panics if `len > self.remaining()`.
970 /// Use [`prefix_checked`](Chunk::prefix_checked) for non-panicking access.
971 ///
972 /// # Examples
973 ///
974 /// ```rust
975 /// use bufkit::Chunk;
976 ///
977 /// let mut buf = [1u8, 2, 3, 4, 5];
978 /// let slice = &buf[..];
979 /// let prefix = Chunk::prefix(&slice, 3);
980 /// assert_eq!(prefix, [1u8, 2, 3].as_slice());
981 /// ```
982 #[inline]
983 fn prefix(&self, len: usize) -> &[u8] {
984 &self.buffer()[..len]
985 }
986
987 /// Returns a slice containing the first `len` bytes of the buffer.
988 ///
989 /// This is the non-panicking version of [`prefix`](Chunk::prefix).
990 /// Returns `Some(slice)` if `len <= self.remaining()`, otherwise returns `None`.
991 ///
992 /// # Examples
993 ///
994 /// ```rust
995 /// use bufkit::Chunk;
996 ///
997 /// let mut buf = [1u8, 2, 3, 4, 5];
998 ///
999 /// assert_eq!(Chunk::prefix_checked(&&buf[..], 3).unwrap(), &[1, 2, 3]);
1000 /// assert_eq!(Chunk::prefix_checked(&&buf[..], 5).unwrap(), &[1, 2, 3, 4, 5]);
1001 /// assert!(Chunk::prefix_checked(&&buf[..], 10).is_none());
1002 /// ```
1003 #[inline]
1004 fn prefix_checked(&self, len: usize) -> Option<&[u8]> {
1005 if self.remaining() < len {
1006 None
1007 } else {
1008 Some(&self.buffer()[..len])
1009 }
1010 }
1011
1012 /// Returns a slice containing the last `len` bytes of the buffer.
1013 ///
1014 /// This provides access to a suffix of the buffer for efficient manipulation
1015 /// of the trailing portion without affecting the rest of the buffer.
1016 ///
1017 /// # Panics
1018 ///
1019 /// Panics if `len > self.remaining()`.
1020 /// Use [`suffix_checked`](Chunk::suffix_checked) for non-panicking access.
1021 ///
1022 /// # Examples
1023 ///
1024 /// ```rust
1025 /// use bufkit::Chunk;
1026 ///
1027 /// let mut buf = [1u8, 2, 3, 4, 5];
1028 ///
1029 /// let slice = &buf[..];
1030 /// let suffix = Chunk::suffix(&slice, 2);
1031 /// assert_eq!(suffix, &[4, 5]);
1032 /// ```
1033 #[inline]
1034 fn suffix(&self, len: usize) -> &[u8] {
1035 let total_len = self.remaining();
1036 &self.buffer()[total_len - len..]
1037 }
1038
1039 /// Returns a slice containing the last `len` bytes of the buffer.
1040 ///
1041 /// This is the non-panicking version of [`suffix`](Chunk::suffix).
1042 /// Returns `Some(slice)` if `len <= self.remaining()`, otherwise returns `None`.
1043 ///
1044 /// # Examples
1045 ///
1046 /// ```rust
1047 /// use bufkit::Chunk;
1048 ///
1049 /// let mut buf = [1u8, 2, 3, 4, 5];
1050 /// let slice = &buf[..];
1051 /// assert_eq!(Chunk::suffix_checked(&slice, 2).unwrap(), &[4, 5]);
1052 /// assert_eq!(Chunk::suffix_checked(&slice, 5).unwrap(), &[1, 2, 3, 4, 5]);
1053 /// assert!(Chunk::suffix_checked(&slice, 10).is_none());
1054 /// ```
1055 #[inline]
1056 fn suffix_checked(&self, len: usize) -> Option<&[u8]> {
1057 self
1058 .remaining()
1059 .checked_sub(len)
1060 .map(|start| &self.buffer()[start..])
1061 }
1062
1063 /// Creates an independent buffer containing a segment of the current buffer's data.
1064 ///
1065 /// This method returns a new buffer instance that represents a portion of the current
1066 /// buffer defined by the given range. The original buffer remains unchanged,
1067 /// and the new buffer has its own independent cursor starting at the beginning of the segment.
1068 ///
1069 /// # Panics
1070 ///
1071 /// Panics if the range is out of bounds relative to the current buffer's available data.
1072 /// Use [`try_segment`](Chunk::try_segment) for non-panicking segmentation.
1073 ///
1074 /// # Examples
1075 ///
1076 /// ```rust
1077 /// use bufkit::Chunk;
1078 ///
1079 /// let data = b"Hello, World!";
1080 /// let buf = &data[..];
1081 ///
1082 /// let hello = buf.segment(0..5);
1083 /// let world = buf.segment(7..12);
1084 ///
1085 /// assert_eq!(hello.buffer(), b"Hello");
1086 /// assert_eq!(world.buffer(), b"World");
1087 /// // Original buffer unchanged
1088 /// assert_eq!(buf.remaining(), 13);
1089 /// ```
1090 fn segment(&self, range: impl RangeBounds<usize>) -> Self
1091 where
1092 Self: Sized;
1093
1094 /// Shortens the buffer to the specified length, keeping the first `len` bytes.
1095 ///
1096 /// If `len` is greater than the buffer's current available bytes, this has no effect.
1097 /// This operation cannot fail and will never panic.
1098 ///
1099 /// # Examples
1100 ///
1101 /// ```rust
1102 /// use bufkit::Chunk;
1103 ///
1104 /// let data = [1, 2, 3, 4, 5];
1105 /// let mut buf = &data[..];
1106 ///
1107 /// buf.truncate(3);
1108 /// assert_eq!(buf.remaining(), 3);
1109 /// assert_eq!(buf.buffer(), &[1, 2, 3]);
1110 ///
1111 /// // Truncating to a length >= available has no effect
1112 /// buf.truncate(10);
1113 /// assert_eq!(buf.remaining(), 3);
1114 /// ```
1115 fn truncate(&mut self, len: usize);
1116
1117 /// Splits the buffer into two at the given index.
1118 ///
1119 /// Afterwards `self` contains elements `[0, at)`, and the returned buffer
1120 /// contains elements `[at, remaining())`. The memory layout remains unchanged.
1121 ///
1122 /// **Implementor Notes:** This should be an `O(1)` operation.
1123 ///
1124 /// # Panics
1125 ///
1126 /// Panics if `at > self.remaining()`.
1127 /// Use [`split_off_checked`](Chunk::split_off_checked) or
1128 /// [`try_split_off`](Chunk::try_split_off) for non-panicking splits.
1129 ///
1130 /// # Examples
1131 ///
1132 /// ```rust
1133 /// use bufkit::Chunk;
1134 ///
1135 /// let data = [1, 2, 3, 4, 5];
1136 /// let mut buf = &data[..];
1137 ///
1138 /// let tail = Chunk::split_off(&mut buf, 2);
1139 /// assert_eq!(buf.buffer(), &[1, 2]);
1140 /// assert_eq!(tail.buffer(), &[3, 4, 5]);
1141 /// ```
1142 #[must_use = "consider Chunk::truncate if you don't need the other half"]
1143 fn split_off(&mut self, at: usize) -> Self
1144 where
1145 Self: Sized;
1146
1147 /// Splits the buffer into two at the given index.
1148 ///
1149 /// This is the non-panicking version of [`split_off`](Chunk::split_off).
1150 /// Returns `Some((left, right))` if `at <= self.remaining()`, otherwise returns `None`.
1151 ///
1152 /// # Examples
1153 ///
1154 /// ```rust
1155 /// use bufkit::Chunk;
1156 ///
1157 /// let data = [1, 2, 3, 4, 5];
1158 /// let mut buf = &data[..];
1159 ///
1160 /// assert!(Chunk::split_off_checked(&mut buf, 2).is_some());
1161 ///
1162 /// let mut small_buf = &[1u8][..];
1163 /// assert!(Chunk::split_off_checked(&mut small_buf, 5).is_none());
1164 /// ```
1165 #[must_use = "consider Chunk::truncate if you don't need the other half"]
1166 fn split_off_checked(&mut self, at: usize) -> Option<Self>
1167 where
1168 Self: Sized,
1169 {
1170 if at > self.remaining() {
1171 None
1172 } else {
1173 Some(self.split_off(at))
1174 }
1175 }
1176
1177 /// Splits the buffer into two at the given index.
1178 ///
1179 /// This is the non-panicking version of [`split_off`](Chunk::split_off) that
1180 /// returns detailed error information on failure.
1181 /// Returns `Ok(right_half)` on success, or `Err(OutOfBounds)` with details about
1182 /// the attempted split position and available bytes.
1183 ///
1184 /// # Examples
1185 ///
1186 /// ```rust
1187 /// use bufkit::Chunk;
1188 ///
1189 /// let data = [1, 2, 3, 4, 5];
1190 /// let mut buf = &data[..];
1191 ///
1192 /// assert!(Chunk::try_split_off(&mut buf, 2).is_ok());
1193 ///
1194 /// let mut small_buf = &[1u8][..];
1195 /// let err = Chunk::try_split_off(&mut small_buf, 5).unwrap_err();
1196 /// // err contains details about requested vs available
1197 /// ```
1198 #[must_use = "consider Chunk::try_split_off if you don't need the other half"]
1199 fn try_split_off(&mut self, at: usize) -> Result<Self, OutOfBounds>
1200 where
1201 Self: Sized,
1202 {
1203 if at > self.remaining() {
1204 Err(OutOfBounds::new(at, self.remaining()))
1205 } else {
1206 Ok(self.split_off(at))
1207 }
1208 }
1209
1210 /// Splits the buffer into two at the given index.
1211 ///
1212 /// Afterwards `self` contains elements `[at, remaining())`, and the returned
1213 /// buffer contains elements `[0, at)`.
1214 ///
1215 /// **Implementor Notes:** This should be an `O(1)` operation.
1216 ///
1217 /// # Panics
1218 ///
1219 /// Panics if `at > self.remaining()`.
1220 /// Use [`split_to_checked`](Chunk::split_to_checked) or
1221 /// [`try_split_to`](Chunk::try_split_to) for non-panicking splits.
1222 ///
1223 /// # Examples
1224 ///
1225 /// ```rust
1226 /// use bufkit::Chunk;
1227 ///
1228 /// let data = b"hello world";
1229 /// let mut buf = &data[..];
1230 ///
1231 /// let hello = buf.split_to(5);
1232 /// assert_eq!(hello.buffer(), b"hello");
1233 /// assert_eq!(buf.buffer(), b" world");
1234 /// ```
1235 #[must_use = "consider Chunk::advance if you don't need the other half"]
1236 fn split_to(&mut self, at: usize) -> Self
1237 where
1238 Self: Sized;
1239
1240 /// Splits the buffer into two at the given index.
1241 ///
1242 /// This is the non-panicking version of [`split_to`](Chunk::split_to).
1243 /// Returns `Some(left_half)` if `at <= self.remaining()`, otherwise returns `None`.
1244 ///
1245 /// # Examples
1246 ///
1247 /// ```rust
1248 /// use bufkit::Chunk;
1249 ///
1250 /// let data = [1, 2, 3, 4, 5];
1251 /// let mut buf = &data[..];
1252 ///
1253 /// assert!(Chunk::split_to_checked(&mut buf, 3).is_some());
1254 /// assert!(Chunk::split_to_checked(&mut buf, 10).is_none());
1255 /// ```
1256 #[must_use = "consider Chunk::advance if you don't need the other half"]
1257 fn split_to_checked(&mut self, at: usize) -> Option<Self>
1258 where
1259 Self: Sized,
1260 {
1261 if at > self.remaining() {
1262 None
1263 } else {
1264 Some(self.split_to(at))
1265 }
1266 }
1267
1268 /// Splits the buffer into two at the given index.
1269 ///
1270 /// This is the non-panicking version of [`split_to`](Chunk::split_to) that
1271 /// returns detailed error information on failure.
1272 /// Returns `Ok(left_half)` on success, or `Err(OutOfBounds)` with details about
1273 /// the attempted split position and available bytes.
1274 ///
1275 /// # Examples
1276 ///
1277 /// ```rust
1278 /// use bufkit::Chunk;
1279 ///
1280 /// let data = [1, 2, 3, 4, 5];
1281 /// let mut buf = &data[..];
1282 ///
1283 /// assert!(Chunk::try_split_to(&mut buf, 3).is_ok());
1284 ///
1285 /// let err = Chunk::try_split_to(&mut buf, 10).unwrap_err();
1286 /// // err contains detailed information about the failure
1287 /// ```
1288 #[must_use = "consider Chunk::try_split_to if you don't need the other half"]
1289 fn try_split_to(&mut self, at: usize) -> Result<Self, OutOfBounds>
1290 where
1291 Self: Sized,
1292 {
1293 if at > self.remaining() {
1294 Err(OutOfBounds::new(at, self.remaining()))
1295 } else {
1296 Ok(self.split_to(at))
1297 }
1298 }
1299
1300 /// Returns `true` if there are bytes available for reading in the buffer.
1301 ///
1302 /// This is equivalent to `self.remaining() > 0`.
1303 ///
1304 /// # Examples
1305 ///
1306 /// ```rust
1307 /// use bufkit::Chunk;
1308 ///
1309 /// let data = [1, 2, 3];
1310 /// let mut buf = &data[..];
1311 /// assert!(Chunk::has_remaining(&buf));
1312 ///
1313 /// buf.advance(3);
1314 /// assert!(!Chunk::has_remaining(&buf));
1315 /// ```
1316 fn has_remaining(&self) -> bool {
1317 self.remaining() > 0
1318 }
1319
1320 /// Attempts to advance the internal cursor by the specified number of bytes.
1321 ///
1322 /// This is the non-panicking version of [`advance`](Chunk::advance).
1323 /// Returns `Ok(())` if the advancement was successful, or `Err(TryAdvanceError)`
1324 /// with details about requested vs available bytes.
1325 ///
1326 /// # Examples
1327 ///
1328 /// ```rust
1329 /// use bufkit::Chunk;
1330 ///
1331 /// let data = [1, 2, 3, 4, 5];
1332 /// let mut buf = &data[..];
1333 ///
1334 /// assert!(buf.try_advance(3).is_ok());
1335 /// assert_eq!(buf.remaining(), 2);
1336 ///
1337 /// let err = buf.try_advance(5).unwrap_err();
1338 /// // err contains details about requested vs available
1339 /// ```
1340 fn try_advance(&mut self, cnt: usize) -> Result<(), TryAdvanceError> {
1341 if cnt == 0 {
1342 return Ok(());
1343 }
1344
1345 let remaining = self.remaining();
1346 if remaining < cnt {
1347 return Err(TryAdvanceError::new(must_non_zero(cnt), remaining));
1348 }
1349
1350 self.advance(cnt);
1351 Ok(())
1352 }
1353
1354 /// Attempts to create a new buffer containing a segment of the current buffer's data.
1355 ///
1356 /// The returned buffer is independent with its own cursor starting at the beginning of the segment.
1357 /// The original buffer remains unchanged. This is the non-panicking version of
1358 /// [`segment`](Chunk::segment).
1359 ///
1360 /// Returns `Ok(segment)` if the range is valid, or `Err(TrySegmentError)` if the range
1361 /// extends beyond the current buffer's available data.
1362 ///
1363 /// # Examples
1364 ///
1365 /// ```rust
1366 /// use bufkit::Chunk;
1367 ///
1368 /// let data = b"Hello, World!";
1369 /// let buf = &data[..];
1370 ///
1371 /// assert!(buf.try_segment(0..5).is_ok());
1372 /// assert!(buf.try_segment(0..20).is_err()); // Out of bounds
1373 /// ```
1374 #[inline]
1375 fn try_segment(&self, range: impl RangeBounds<usize>) -> Result<Self, TrySegmentError>
1376 where
1377 Self: Sized,
1378 {
1379 check_segment(range, self.remaining()).map(|(start, end)| self.segment(start..end))
1380 }
1381
1382 // Macro generates peek methods for primitive types
1383 peek_fixed!(u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
1384
1385 // Macro generates read methods for primitive types
1386 read_fixed!(u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
1387
1388 /// Peeks a `u8` value from the buffer without advancing the internal cursor.
1389 ///
1390 /// Returns the first byte from the buffer without consuming it.
1391 /// The buffer position remains unchanged after this operation.
1392 ///
1393 /// # Panics
1394 ///
1395 /// Panics if the buffer is empty.
1396 /// Use [`peek_u8_checked`](Chunk::peek_u8_checked) for non-panicking peeks.
1397 ///
1398 /// # Examples
1399 ///
1400 /// ```rust
1401 /// use bufkit::Chunk;
1402 ///
1403 /// let data = [42, 1, 2, 3];
1404 /// let buf = &data[..];
1405 ///
1406 /// assert_eq!(buf.peek_u8(), 42);
1407 /// assert_eq!(buf.remaining(), 4); // Unchanged
1408 /// ```
1409 #[inline]
1410 fn peek_u8(&self) -> u8 {
1411 self.buffer()[0]
1412 }
1413
1414 /// Peeks a `u8` value from the buffer without advancing the internal cursor.
1415 ///
1416 /// This is the non-panicking version of [`peek_u8`](Chunk::peek_u8).
1417 /// Returns `Some(byte)` if data is available, otherwise returns `None`.
1418 ///
1419 /// # Examples
1420 ///
1421 /// ```rust
1422 /// use bufkit::Chunk;
1423 ///
1424 /// let data = [42];
1425 /// let buf = &data[..];
1426 /// assert_eq!(buf.peek_u8_checked(), Some(42));
1427 ///
1428 /// let empty_buf = &[][..];
1429 /// assert_eq!(empty_buf.peek_u8_checked(), None);
1430 /// ```
1431 #[inline]
1432 fn peek_u8_checked(&self) -> Option<u8> {
1433 self.buffer().first().copied()
1434 }
1435
1436 /// Peeks a `u8` value from the buffer without advancing the internal cursor.
1437 ///
1438 /// This is the non-panicking version of [`peek_u8`](Chunk::peek_u8).
1439 /// Returns `Ok(byte)` if data is available, otherwise returns `Err`.
1440 ///
1441 /// # Examples
1442 ///
1443 /// ```rust
1444 /// use bufkit::Chunk;
1445 ///
1446 /// let data = [42];
1447 /// let buf = &data[..];
1448 /// assert_eq!(buf.peek_u8_checked(), Some(42));
1449 ///
1450 /// let empty_buf = &[][..];
1451 /// assert!(empty_buf.try_peek_u8().is_err());
1452 /// ```
1453 #[inline]
1454 fn try_peek_u8(&self) -> Result<u8, TryPeekError> {
1455 self
1456 .buffer()
1457 .first()
1458 .copied()
1459 .ok_or_else(|| TryPeekError::new(super::NON_ZERO_1, self.remaining()))
1460 }
1461
1462 /// Peeks a `u8` value from the buffer at the specified offset without advancing the cursor.
1463 ///
1464 /// Returns the byte at the given offset without consuming it.
1465 /// The buffer position remains unchanged after this operation.
1466 ///
1467 /// # Panics
1468 ///
1469 /// Panics if `offset >= self.remaining()`.
1470 /// Use [`peek_u8_at_checked`](Chunk::peek_u8_at_checked) for non-panicking peeks.
1471 ///
1472 /// # Examples
1473 ///
1474 /// ```rust
1475 /// use bufkit::Chunk;
1476 ///
1477 /// let data = [42, 1, 2, 3];
1478 /// let buf = &data[..];
1479 ///
1480 /// assert_eq!(buf.peek_u8_at(0), 42);
1481 /// assert_eq!(buf.peek_u8_at(2), 2);
1482 /// assert_eq!(buf.remaining(), 4); // Unchanged
1483 /// ```
1484 #[inline]
1485 fn peek_u8_at(&self, offset: usize) -> u8 {
1486 self.buffer_from(offset)[0]
1487 }
1488
1489 /// Peeks a `u8` value from the buffer at the specified offset without advancing the cursor.
1490 ///
1491 /// This is the non-panicking version of [`peek_u8_at`](Chunk::peek_u8_at).
1492 /// Returns `Some(byte)` if the offset is valid, otherwise returns `None`.
1493 ///
1494 /// # Examples
1495 ///
1496 /// ```rust
1497 /// use bufkit::Chunk;
1498 ///
1499 /// let data = [42, 1, 2];
1500 /// let buf = &data[..];
1501 /// assert_eq!(buf.peek_u8_at_checked(1), Some(1));
1502 /// assert_eq!(buf.peek_u8_at_checked(10), None);
1503 /// ```
1504 #[inline]
1505 fn peek_u8_at_checked(&self, offset: usize) -> Option<u8> {
1506 self.buffer().get(offset).copied()
1507 }
1508
1509 /// Peeks a `u8` value from the buffer at the specified offset without advancing the cursor.
1510 ///
1511 /// This is the non-panicking version of [`peek_u8_at`](Chunk::peek_u8_at).
1512 /// Returns `Ok(byte)` if the offset is valid, otherwise returns `Err(TryPeekAtError)`.
1513 ///
1514 /// # Examples
1515 ///
1516 /// ```rust
1517 /// use bufkit::Chunk;
1518 ///
1519 /// let data = [42, 1, 2];
1520 /// let buf = &data[..];
1521 /// assert_eq!(buf.try_peek_u8_at(1), Ok(1));
1522 ///
1523 /// let err = buf.try_peek_u8_at(10).unwrap_err();
1524 /// // err contains details about the error
1525 /// ```
1526 #[inline]
1527 fn try_peek_u8_at(&self, offset: usize) -> Result<u8, TryPeekAtError> {
1528 let buffer = self.buffer();
1529
1530 if offset >= buffer.len() {
1531 return Err(TryPeekAtError::out_of_bounds(offset, buffer.len()));
1532 }
1533
1534 Ok(buffer[offset])
1535 }
1536
1537 /// Peeks an `i8` value from the buffer at the specified offset without advancing the cursor.
1538 ///
1539 /// Returns the byte at the given offset as a signed integer without consuming it.
1540 /// The buffer position remains unchanged after this operation.
1541 ///
1542 /// # Panics
1543 ///
1544 /// Panics if `offset >= self.remaining()`.
1545 /// Use [`peek_i8_at_checked`](Chunk::peek_i8_at_checked) for non-panicking peeks.
1546 ///
1547 /// # Examples
1548 ///
1549 /// ```rust
1550 /// use bufkit::Chunk;
1551 ///
1552 /// let data = [255u8, 1, 2, 3]; // 255 as i8 is -1
1553 /// let buf = &data[..];
1554 ///
1555 /// assert_eq!(buf.peek_i8_at(0), -1);
1556 /// assert_eq!(buf.remaining(), 4); // Unchanged
1557 /// ```
1558 #[inline]
1559 fn peek_i8_at(&self, offset: usize) -> i8 {
1560 self.peek_u8_at(offset) as i8
1561 }
1562
1563 /// Peeks an `i8` value from the buffer at the specified offset without advancing the cursor.
1564 ///
1565 /// This is the non-panicking version of [`peek_i8_at`](Chunk::peek_i8_at).
1566 /// Returns `Some(byte)` if the offset is valid, otherwise returns `None`.
1567 ///
1568 /// # Examples
1569 ///
1570 /// ```rust
1571 /// use bufkit::Chunk;
1572 ///
1573 /// let data = [255u8, 1, 2]; // 255 as i8 is -1
1574 /// let buf = &data[..];
1575 /// assert_eq!(buf.peek_i8_at_checked(0), Some(-1));
1576 /// assert_eq!(buf.peek_i8_at_checked(10), None);
1577 /// ```
1578 #[inline]
1579 fn peek_i8_at_checked(&self, offset: usize) -> Option<i8> {
1580 self.peek_u8_at_checked(offset).map(|v| v as i8)
1581 }
1582
1583 /// Peeks an `i8` value from the buffer at the specified offset without advancing the cursor.
1584 ///
1585 /// This is the non-panicking version of [`peek_i8_at`](Chunk::peek_i8_at).
1586 /// Returns `Ok(byte)` if the offset is valid, otherwise returns `Err(TryPeekAtError)`.
1587 ///
1588 /// # Examples
1589 ///
1590 /// ```rust
1591 /// use bufkit::Chunk;
1592 ///
1593 /// let data = [255u8, 1, 2]; // 255 as i8 is -1
1594 /// let buf = &data[..];
1595 /// assert_eq!(buf.try_peek_i8_at(0), Ok(-1));
1596 ///
1597 /// let err = buf.try_peek_i8_at(10).unwrap_err();
1598 /// // err contains details about the error
1599 /// ```
1600 #[inline]
1601 fn try_peek_i8_at(&self, offset: usize) -> Result<i8, TryPeekAtError> {
1602 self.try_peek_u8_at(offset).map(|v| v as i8)
1603 }
1604
1605 /// Reads a `u8` value from the buffer and advances the internal cursor.
1606 ///
1607 /// Returns the first byte from the buffer and advances the cursor by 1 byte.
1608 ///
1609 /// # Panics
1610 ///
1611 /// Panics if the buffer is empty.
1612 /// Use [`read_u8_checked`](Chunk::read_u8_checked) for non-panicking reads.
1613 ///
1614 /// # Examples
1615 ///
1616 /// ```rust
1617 /// use bufkit::Chunk;
1618 ///
1619 /// let data = [42, 1, 2, 3];
1620 /// let mut buf = &data[..];
1621 ///
1622 /// assert_eq!(buf.read_u8(), 42);
1623 /// assert_eq!(buf.remaining(), 3); // Cursor advanced
1624 /// ```
1625 #[inline]
1626 fn read_u8(&mut self) -> u8 {
1627 let val = self.peek_u8();
1628 self.advance(1);
1629 val
1630 }
1631
1632 /// Reads a `u8` value from the buffer and advances the internal cursor.
1633 ///
1634 /// This is the non-panicking version of [`read_u8`](Chunk::read_u8).
1635 /// Returns `Some(byte)` and advances the cursor on success, or `None` if the buffer is empty.
1636 ///
1637 /// # Examples
1638 ///
1639 /// ```rust
1640 /// use bufkit::Chunk;
1641 ///
1642 /// let data = [42];
1643 /// let mut buf = &data[..];
1644 ///
1645 /// assert_eq!(buf.read_u8_checked(), Some(42));
1646 /// assert_eq!(buf.remaining(), 0);
1647 ///
1648 /// assert_eq!(buf.read_u8_checked(), None); // Empty now
1649 /// ```
1650 #[inline]
1651 fn read_u8_checked(&mut self) -> Option<u8> {
1652 self.peek_u8_checked().inspect(|_| {
1653 self.advance(1);
1654 })
1655 }
1656
1657 /// Reads a `u8` value from the buffer and advances the internal cursor.
1658 ///
1659 /// This is the non-panicking version of [`read_u8`](Chunk::read_u8).
1660 /// Returns `Ok(byte)` and advances the cursor on success, or `Err` if the buffer is empty.
1661 ///
1662 /// # Examples
1663 ///
1664 /// ```rust
1665 /// use bufkit::Chunk;
1666 ///
1667 /// let data = [42];
1668 /// let mut buf = &data[..];
1669 ///
1670 /// assert_eq!(buf.read_u8_checked(), Some(42));
1671 /// assert_eq!(buf.remaining(), 0);
1672 ///
1673 /// assert!(buf.try_read_u8().is_err()); // Empty now
1674 /// ```
1675 #[inline]
1676 fn try_read_u8(&mut self) -> Result<u8, TryReadError> {
1677 self
1678 .read_u8_checked()
1679 .ok_or_else(|| TryReadError::new(super::NON_ZERO_1, self.remaining()))
1680 }
1681
1682 /// Peeks an `i8` value from the buffer without advancing the internal cursor.
1683 ///
1684 /// Returns the first byte from the buffer as a signed integer without consuming it.
1685 /// The buffer position remains unchanged after this operation.
1686 ///
1687 /// # Panics
1688 ///
1689 /// Panics if the buffer is empty.
1690 /// Use [`peek_i8_checked`](Chunk::peek_i8_checked) for non-panicking peeks.
1691 ///
1692 /// # Examples
1693 ///
1694 /// ```rust
1695 /// use bufkit::Chunk;
1696 ///
1697 /// let data = [255u8, 1, 2, 3]; // 255 as i8 is -1
1698 /// let buf = &data[..];
1699 ///
1700 /// assert_eq!(buf.peek_i8(), -1);
1701 /// assert_eq!(buf.remaining(), 4); // Unchanged
1702 /// ```
1703 #[inline]
1704 fn peek_i8(&self) -> i8 {
1705 self.peek_u8() as i8
1706 }
1707
1708 /// Peeks an `i8` value from the buffer without advancing the internal cursor.
1709 ///
1710 /// This is the non-panicking version of [`peek_i8`](Chunk::peek_i8).
1711 /// Returns `Some(byte)` if data is available, otherwise returns `None`.
1712 ///
1713 /// # Examples
1714 ///
1715 /// ```rust
1716 /// use bufkit::Chunk;
1717 ///
1718 /// let data = [255u8]; // -1 as i8
1719 /// let buf = &data[..];
1720 /// assert_eq!(buf.peek_i8_checked(), Some(-1));
1721 ///
1722 /// let empty_buf = &[][..];
1723 /// assert_eq!(empty_buf.peek_i8_checked(), None);
1724 /// ```
1725 #[inline]
1726 fn peek_i8_checked(&self) -> Option<i8> {
1727 self.peek_u8_checked().map(|v| v as i8)
1728 }
1729
1730 /// Peeks an `i8` value from the buffer without advancing the internal cursor.
1731 ///
1732 /// This is the non-panicking version of [`peek_i8`](Chunk::peek_i8).
1733 /// Returns `Ok(byte)` if data is available, otherwise returns `Err`.
1734 ///
1735 /// # Examples
1736 ///
1737 /// ```rust
1738 /// use bufkit::Chunk;
1739 ///
1740 /// let data = [255u8]; // -1 as i8
1741 /// let buf = &data[..];
1742 /// assert_eq!(buf.try_peek_i8(), Ok(-1));
1743 ///
1744 /// let empty_buf = &[][..];
1745 /// assert!(empty_buf.try_peek_i8().is_err());
1746 /// ```
1747 #[inline]
1748 fn try_peek_i8(&self) -> Result<i8, TryPeekError> {
1749 self.try_peek_u8().map(|v| v as i8)
1750 }
1751
1752 /// Reads an `i8` value from the buffer and advances the internal cursor.
1753 ///
1754 /// Returns the first byte from the buffer as a signed integer and advances the cursor by 1 byte.
1755 ///
1756 /// # Panics
1757 ///
1758 /// Panics if the buffer is empty.
1759 /// Use [`read_i8_checked`](Chunk::read_i8_checked) for non-panicking reads.
1760 ///
1761 /// # Examples
1762 ///
1763 /// ```rust
1764 /// use bufkit::Chunk;
1765 ///
1766 /// let data = [255u8, 1, 2, 3]; // 255 as i8 is -1
1767 /// let mut buf = &data[..];
1768 ///
1769 /// assert_eq!(buf.read_i8(), -1);
1770 /// assert_eq!(buf.remaining(), 3); // Cursor advanced
1771 /// ```
1772 #[inline]
1773 fn read_i8(&mut self) -> i8 {
1774 self.read_u8() as i8
1775 }
1776
1777 /// Reads an `i8` value from the buffer and advances the internal cursor.
1778 ///
1779 /// This is the non-panicking version of [`read_i8`](Chunk::read_i8).
1780 /// Returns `Some(byte)` and advances the cursor on success, or `None` if the buffer is empty.
1781 ///
1782 /// # Examples
1783 ///
1784 /// ```rust
1785 /// use bufkit::Chunk;
1786 ///
1787 /// let data = [255u8]; // -1 as i8
1788 /// let mut buf = &data[..];
1789 ///
1790 /// assert_eq!(buf.read_i8_checked(), Some(-1));
1791 /// assert_eq!(buf.remaining(), 0);
1792 ///
1793 /// assert_eq!(buf.read_i8_checked(), None); // Empty now
1794 /// ```
1795 #[inline]
1796 fn read_i8_checked(&mut self) -> Option<i8> {
1797 self.read_u8_checked().map(|v| v as i8)
1798 }
1799
1800 /// Reads an `i8` value from the buffer and advances the internal cursor.
1801 ///
1802 /// This is the non-panicking version of [`read_i8`](Chunk::read_i8).
1803 /// Returns `Ok(byte)` and advances the cursor on success, or `Err(Try
1804 /// ReadError)` if the buffer is empty.
1805 ///
1806 /// # Examples
1807 /// ```rust
1808 /// use bufkit::Chunk;
1809 ///
1810 /// let data = [255u8]; // -1 as i8
1811 /// let mut buf = &data[..];
1812 /// assert_eq!(buf.try_read_i8(), Ok(-1));
1813 /// assert_eq!(buf.remaining(), 0);
1814 /// assert!(buf.try_read_i8().is_err()); // Empty now
1815 /// ```
1816 #[inline]
1817 fn try_read_i8(&mut self) -> Result<i8, TryReadError> {
1818 self.try_read_u8().map(|v| v as i8)
1819 }
1820
1821 /// Converts the read buffer to a `Vec<u8>` instance.
1822 ///
1823 /// Creates a new vector containing a copy of all available bytes in the buffer.
1824 /// The original buffer remains unchanged.
1825 ///
1826 /// # Examples
1827 ///
1828 /// ```rust
1829 /// use bufkit::Chunk;
1830 ///
1831 /// let data = [1, 2, 3, 4, 5];
1832 /// let buf = &data[..];
1833 ///
1834 /// let vec = buf.to_vec();
1835 /// assert_eq!(vec, vec![1, 2, 3, 4, 5]);
1836 /// ```
1837 #[cfg(any(feature = "std", feature = "alloc"))]
1838 #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
1839 fn to_vec(&self) -> ::std::vec::Vec<u8> {
1840 self.buffer().to_vec()
1841 }
1842
1843 /// Converts the read buffer to a `Bytes` instance.
1844 ///
1845 /// Creates a new `Bytes` instance containing a copy of all available bytes in the buffer.
1846 /// The original buffer remains unchanged.
1847 #[cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc")))]
1848 #[cfg_attr(
1849 docsrs,
1850 doc(cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc"))))
1851 )]
1852 fn to_bytes(&self) -> ::bytes_1::Bytes {
1853 ::bytes_1::Bytes::copy_from_slice(self.buffer())
1854 }
1855
1856 /// Converts the read buffer to a `BytesMut` instance.
1857 ///
1858 /// Creates a new `BytesMut` instance containing a copy of all available bytes in the buffer.
1859 /// The original buffer remains unchanged.
1860 #[cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc")))]
1861 #[cfg_attr(
1862 docsrs,
1863 doc(cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc"))))
1864 )]
1865 #[allow(clippy::wrong_self_convention)]
1866 fn to_bytes_mut(&self) -> ::bytes_1::BytesMut {
1867 ::bytes_1::BytesMut::from(self.to_bytes())
1868 }
1869}
1870
1871/// Extension trait for `Chunk` that provides additional methods
1872pub trait ChunkExt: Chunk {
1873 /// Peeks a fixed-size array from the beginning of the buffer without advancing the cursor.
1874 ///
1875 /// This method creates a copy of the first `N` bytes from the buffer without
1876 /// consuming them. The buffer position remains unchanged after this operation.
1877 ///
1878 /// # Panics
1879 ///
1880 /// Panics if the buffer contains fewer than `N` bytes.
1881 /// Use [`peek_array_checked`](Chunk::peek_array_checked) or
1882 /// [`try_peek_array`](Chunk::try_peek_array) for non-panicking peeks.
1883 ///
1884 /// # Examples
1885 ///
1886 /// ```rust
1887 /// use bufkit::{Chunk, ChunkExt};
1888 ///
1889 /// let data = [1, 2, 3, 4, 5];
1890 /// let buf = &data[..];
1891 ///
1892 /// let first_three: [u8; 3] = buf.peek_array();
1893 /// assert_eq!(first_three, [1, 2, 3]);
1894 /// // Chunkfer unchanged
1895 /// assert_eq!(buf.remaining(), 5);
1896 /// ```
1897 #[inline]
1898 fn peek_array<const N: usize>(&self) -> [u8; N] {
1899 peek_array::<_, N>(self)
1900 }
1901
1902 /// Peeks a fixed-size array from the beginning of the buffer without advancing the cursor.
1903 ///
1904 /// This is the non-panicking version of [`peek_array`](Chunk::peek_array).
1905 /// Returns `Some(array)` if sufficient data is available, otherwise returns `None`.
1906 ///
1907 /// # Examples
1908 ///
1909 /// ```rust
1910 /// use bufkit::{Chunk, ChunkExt};
1911 ///
1912 /// let data = [1, 2, 3];
1913 /// let buf = &data[..];
1914 ///
1915 /// assert!(buf.peek_array_checked::<2>().is_some());
1916 /// assert!(buf.peek_array_checked::<5>().is_none());
1917 /// ```
1918 #[inline]
1919 fn peek_array_checked<const N: usize>(&self) -> Option<[u8; N]> {
1920 peek_array_checked::<_, N>(self)
1921 }
1922
1923 /// Peeks a fixed-size array from the beginning of the buffer without advancing the cursor.
1924 ///
1925 /// This is the non-panicking version of [`peek_array`](Chunk::peek_array) that
1926 /// returns detailed error information on failure.
1927 /// Returns `Ok(array)` on success, or `Err(TryPeekError)` with details about
1928 /// requested vs available bytes.
1929 ///
1930 /// # Examples
1931 ///
1932 /// ```rust
1933 /// use bufkit::{Chunk, ChunkExt};
1934 ///
1935 /// let data = [1, 2, 3];
1936 /// let buf = &data[..];
1937 ///
1938 /// assert!(buf.try_peek_array::<2>().is_ok());
1939 ///
1940 /// let err = buf.try_peek_array::<5>().unwrap_err();
1941 /// // err contains details about requested vs available
1942 /// ```
1943 #[inline]
1944 fn try_peek_array<const N: usize>(&self) -> Result<[u8; N], TryPeekError> {
1945 try_peek_array::<_, N>(self)
1946 }
1947
1948 /// Peeks a fixed-size array from the buffer at the specified offset without advancing the cursor.
1949 ///
1950 /// This method creates a copy of `N` bytes from the buffer starting at the given offset
1951 /// without consuming them. The buffer position remains unchanged after this operation.
1952 ///
1953 /// # Panics
1954 ///
1955 /// Panics if `offset + N > self.remaining()`.
1956 /// Use [`peek_array_at_checked`](ChunkExt::peek_array_at_checked) or
1957 /// [`try_peek_array_at`](ChunkExt::try_peek_array_at) for non-panicking peeks.
1958 ///
1959 /// # Examples
1960 ///
1961 /// ```rust
1962 /// use bufkit::{Chunk, ChunkExt};
1963 ///
1964 /// let data = [1, 2, 3, 4, 5, 6, 7, 8];
1965 /// let buf = &data[..];
1966 ///
1967 /// let array_at_2: [u8; 3] = buf.peek_array_at(2);
1968 /// assert_eq!(array_at_2, [3, 4, 5]);
1969 /// // Chunkfer unchanged
1970 /// assert_eq!(buf.remaining(), 8);
1971 /// ```
1972 #[inline]
1973 fn peek_array_at<const N: usize>(&self, offset: usize) -> [u8; N] {
1974 peek_array_at::<_, N>(self, offset)
1975 }
1976
1977 /// Peeks a fixed-size array from the buffer at the specified offset without advancing the cursor.
1978 ///
1979 /// This is the non-panicking version of [`peek_array_at`](ChunkExt::peek_array_at).
1980 /// Returns `Some(array)` if sufficient data is available at the offset, otherwise returns `None`.
1981 ///
1982 /// # Examples
1983 ///
1984 /// ```rust
1985 /// use bufkit::{Chunk, ChunkExt};
1986 ///
1987 /// let data = [1, 2, 3, 4, 5];
1988 /// let buf = &data[..];
1989 ///
1990 /// assert!(buf.peek_array_at_checked::<3>(1).is_some());
1991 /// assert!(buf.peek_array_at_checked::<3>(4).is_none()); // Not enough bytes
1992 /// ```
1993 #[inline]
1994 fn peek_array_at_checked<const N: usize>(&self, offset: usize) -> Option<[u8; N]> {
1995 peek_array_at_checked::<_, N>(self, offset)
1996 }
1997
1998 /// Peeks a fixed-size array from the buffer at the specified offset without advancing the cursor.
1999 ///
2000 /// This is the non-panicking version of [`peek_array_at`](ChunkExt::peek_array_at) that
2001 /// returns detailed error information on failure.
2002 /// Returns `Ok(array)` on success, or `Err(TryPeekAtError)` with details about
2003 /// the error condition.
2004 ///
2005 /// # Examples
2006 ///
2007 /// ```rust
2008 /// use bufkit::{Chunk, ChunkExt};
2009 ///
2010 /// let data = [1, 2, 3, 4, 5];
2011 /// let buf = &data[..];
2012 ///
2013 /// assert!(buf.try_peek_array_at::<3>(1).is_ok());
2014 ///
2015 /// let err = buf.try_peek_array_at::<3>(4).unwrap_err();
2016 /// let err = buf.try_peek_array_at::<3>(6).unwrap_err();
2017 /// // err contains details about the error
2018 /// ```
2019 #[inline]
2020 fn try_peek_array_at<const N: usize>(&self, offset: usize) -> Result<[u8; N], TryPeekAtError> {
2021 try_peek_array_at::<_, N>(self, offset)
2022 }
2023
2024 /// Reads a fixed-size array from the buffer and advances the internal cursor.
2025 ///
2026 /// This method creates a copy of the first `N` bytes from the buffer and
2027 /// advances the cursor by `N` bytes, consuming the data.
2028 ///
2029 /// # Panics
2030 ///
2031 /// Panics if the buffer contains fewer than `N` bytes.
2032 /// Use [`read_array_checked`](Chunk::read_array_checked) or
2033 /// [`try_read_array`](Chunk::try_read_array) for non-panicking reads.
2034 ///
2035 /// # Examples
2036 ///
2037 /// ```rust
2038 /// use bufkit::{Chunk, ChunkExt};
2039 ///
2040 /// let data = [1, 2, 3, 4, 5];
2041 /// let mut buf = &data[..];
2042 ///
2043 /// let first_three: [u8; 3] = buf.read_array();
2044 /// assert_eq!(first_three, [1, 2, 3]);
2045 /// assert_eq!(buf.remaining(), 2); // Cursor advanced
2046 /// ```
2047 #[inline]
2048 fn read_array<const N: usize>(&mut self) -> [u8; N] {
2049 let output = self.peek_array::<N>();
2050 self.advance(N);
2051 output
2052 }
2053
2054 /// Reads a fixed-size array from the buffer and advances the internal cursor.
2055 ///
2056 /// This is the non-panicking version of [`read_array`](Chunk::read_array).
2057 /// Returns `Some(array)` and advances the cursor on success, or `None` if insufficient data.
2058 ///
2059 /// # Examples
2060 ///
2061 /// ```rust
2062 /// use bufkit::{Chunk, ChunkExt};
2063 ///
2064 /// let data = [1, 2, 3];
2065 /// let mut buf = &data[..];
2066 ///
2067 /// assert!(buf.read_array_checked::<2>().is_some());
2068 /// assert_eq!(buf.remaining(), 1);
2069 ///
2070 /// assert!(buf.read_array_checked::<2>().is_none());
2071 /// assert_eq!(buf.remaining(), 1); // Cursor not advanced on failure
2072 /// ```
2073 #[inline]
2074 fn read_array_checked<const N: usize>(&mut self) -> Option<[u8; N]> {
2075 self.peek_array_checked::<N>().inspect(|_| {
2076 self.advance(N);
2077 })
2078 }
2079
2080 /// Reads a fixed-size array from the buffer and advances the internal cursor.
2081 ///
2082 /// This is the non-panicking version of [`read_array`](Chunk::read_array) that
2083 /// returns detailed error information on failure.
2084 /// Returns `Ok(array)` and advances the cursor on success, or `Err(TryReadError)`
2085 /// with details about requested vs available bytes.
2086 ///
2087 /// # Examples
2088 ///
2089 /// ```rust
2090 /// use bufkit::{Chunk, ChunkExt};
2091 ///
2092 /// let data = [1, 2, 3];
2093 /// let mut buf = &data[..];
2094 ///
2095 /// assert!(buf.try_read_array::<2>().is_ok());
2096 /// assert_eq!(buf.remaining(), 1);
2097 ///
2098 /// let err = buf.try_read_array::<2>().unwrap_err();
2099 /// // err contains details about requested vs available
2100 /// ```
2101 #[inline]
2102 fn try_read_array<const N: usize>(&mut self) -> Result<[u8; N], TryReadError> {
2103 self
2104 .try_peek_array::<N>()
2105 .inspect(|_| {
2106 self.advance(N);
2107 })
2108 .map_err(Into::into)
2109 }
2110
2111 /// Peeks a variable-length encoded type from the buffer without advancing the internal cursor.
2112 ///
2113 /// Returns the length of the value and the value itself.
2114 #[cfg(feature = "varint")]
2115 #[cfg_attr(docsrs, doc(cfg(feature = "varint")))]
2116 #[inline]
2117 fn peek_varint<V: Varint>(&self) -> Result<(NonZeroUsize, V), DecodeVarintError> {
2118 V::decode(self.buffer())
2119 }
2120
2121 /// Reads a variable-length encoded type from the buffer and advances the internal cursor.
2122 ///
2123 /// Returns the length of the value read and the value itself.
2124 #[cfg(feature = "varint")]
2125 #[cfg_attr(docsrs, doc(cfg(feature = "varint")))]
2126 #[inline]
2127 fn read_varint<V: Varint>(&mut self) -> Result<(NonZeroUsize, V), DecodeVarintError> {
2128 V::decode(self.buffer()).inspect(|(len, _)| {
2129 self.advance(len.get());
2130 })
2131 }
2132
2133 /// Skips a variable-length encoded type in the buffer without advancing the internal cursor.
2134 ///
2135 /// In varint encoding, each byte uses 7 bits for the value and the highest bit (MSB)
2136 /// as a continuation flag. A set MSB (1) indicates more bytes follow, while an unset MSB (0)
2137 /// marks the last byte of the varint.
2138 ///
2139 /// ## Examples
2140 ///
2141 /// ```rust
2142 /// use bufkit::{ChunkExt, Chunk};
2143 ///
2144 /// let buf = [0x96, 0x01]; // Varint encoding of 150
2145 /// let mut chunk = &buf[..];
2146 /// assert_eq!(chunk.try_scan_varint().map(|val| val.get()), Ok(2));
2147 /// assert_eq!(chunk.remaining(), 2); // Cursor not advanced
2148 ///
2149 /// let buf = [0x7F]; // Varint encoding of 127
2150 /// let mut chunk = &buf[..];
2151 /// assert_eq!(chunk.try_scan_varint().map(|val| val.get()), Ok(1));
2152 /// assert_eq!(chunk.remaining(), 1); // Cursor not advanced
2153 /// ```
2154 #[cfg(feature = "varint")]
2155 #[cfg_attr(docsrs, doc(cfg(feature = "varint")))]
2156 fn try_scan_varint(&mut self) -> Result<NonZeroUsize, DecodeVarintError> {
2157 varing::try_consume_varint(self.buffer()).map_err(Into::into)
2158 }
2159
2160 /// Skips a variable-length encoded type in the buffer at the specified offset without advancing the cursor.
2161 ///
2162 /// In varint encoding, each byte uses 7 bits for the value and the highest bit (MSB)
2163 /// as a continuation flag. A set MSB (1) indicates more bytes follow, while an unset MSB (0)
2164 /// marks the last byte of the varint.
2165 ///
2166 /// ## Examples
2167 ///
2168 /// ```rust
2169 /// use bufkit::{ChunkExt, Chunk};
2170 ///
2171 /// let buf = [0, 0x96, 0x01]; // Varint encoding of 150
2172 /// let mut chunk = &buf[..];
2173 /// assert_eq!(chunk.try_scan_varint_at(1).map(|val| val.get()), Ok(2));
2174 /// assert_eq!(chunk.remaining(), 3); // Cursor not advanced
2175 ///
2176 /// let buf = [0, 0x7F]; // Varint encoding of 127
2177 /// let mut chunk = &buf[..];
2178 /// assert_eq!(chunk.try_scan_varint_at(1).map(|val| val.get()), Ok(1));
2179 /// assert_eq!(chunk.remaining(), 2); // Cursor not advanced
2180 ///
2181 /// // Out of bounds example
2182 /// let err = chunk.try_scan_varint_at(10).unwrap_err();
2183 /// ```
2184 #[cfg(feature = "varint")]
2185 #[cfg_attr(docsrs, doc(cfg(feature = "varint")))]
2186 fn try_scan_varint_at(&mut self, offset: usize) -> Result<NonZeroUsize, DecodeVarintAtError> {
2187 self
2188 .buffer_from_checked(offset)
2189 .ok_or_else(|| DecodeVarintAtError::out_of_bounds(offset, self.remaining()))
2190 .and_then(|buf| {
2191 varing::try_consume_varint(buf)
2192 .map_err(|e| DecodeVarintAtError::from_const_varint_error(e, offset))
2193 })
2194 }
2195
2196 /// Skips a variable-length encoded type in the buffer and advances the internal cursor.
2197 ///
2198 /// In varint encoding, each byte uses 7 bits for the value and the highest bit (MSB)
2199 /// as a continuation flag. A set MSB (1) indicates more bytes follow, while an unset MSB (0)
2200 /// marks the last byte of the varint.
2201 ///
2202 /// ## Examples
2203 ///
2204 /// ```rust
2205 /// use bufkit::{ChunkExt, Chunk};
2206 ///
2207 /// let buf = [0x96, 0x01]; // Varint encoding of 150
2208 /// let mut chunk = &buf[..];
2209 /// assert_eq!(chunk.try_consume_varint().map(|val| val.get()), Ok(2));
2210 /// assert_eq!(chunk.remaining(), 0); // Cursor advanced
2211 ///
2212 /// let buf = [0x7F]; // Varint encoding of 127
2213 /// let mut chunk = &buf[..];
2214 /// assert_eq!(chunk.try_consume_varint().map(|val| val.get()), Ok(1));
2215 /// assert_eq!(chunk.remaining(), 0); // Cursor advanced
2216 /// ```
2217 #[cfg(feature = "varint")]
2218 #[cfg_attr(docsrs, doc(cfg(feature = "varint")))]
2219 fn try_consume_varint(&mut self) -> Result<NonZeroUsize, DecodeVarintError> {
2220 varing::try_consume_varint(self.buffer())
2221 .inspect(|len| {
2222 self.advance(len.get());
2223 })
2224 .map_err(Into::into)
2225 }
2226}
2227
2228impl<T: Chunk> ChunkExt for T {}
2229
2230#[allow(unused)]
2231macro_rules! deref_forward_buf {
2232 () => {
2233 #[inline]
2234 fn remaining(&self) -> usize {
2235 (**self).remaining()
2236 }
2237
2238 #[inline]
2239 fn has_remaining(&self) -> bool {
2240 (**self).has_remaining()
2241 }
2242
2243 #[inline]
2244 fn buffer(&self) -> &[u8] {
2245 (**self).buffer()
2246 }
2247
2248 #[inline]
2249 fn buffer_from(&self, offset: usize) -> &[u8] {
2250 (**self).buffer_from(offset)
2251 }
2252
2253 #[inline]
2254 fn buffer_from_checked(&self, offset: usize) -> Option<&[u8]> {
2255 (**self).buffer_from_checked(offset)
2256 }
2257
2258 #[inline]
2259 fn advance(&mut self, cnt: usize) {
2260 (**self).advance(cnt);
2261 }
2262
2263 #[inline]
2264 fn try_advance(&mut self, cnt: usize) -> Result<(), TryAdvanceError> {
2265 (**self).try_advance(cnt)
2266 }
2267
2268 #[inline]
2269 fn prefix(&self, len: usize) -> &[u8] {
2270 (**self).prefix(len)
2271 }
2272
2273 #[inline]
2274 fn prefix_checked(&self, len: usize) -> Option<&[u8]> {
2275 (**self).prefix_checked(len)
2276 }
2277
2278 #[inline]
2279 fn suffix(&self, len: usize) -> &[u8] {
2280 (**self).suffix(len)
2281 }
2282
2283 #[inline]
2284 fn suffix_checked(&self, len: usize) -> Option<&[u8]> {
2285 (**self).suffix_checked(len)
2286 }
2287
2288 #[inline]
2289 fn segment(&self, range: impl RangeBounds<usize>) -> Self
2290 where
2291 Self: Sized,
2292 {
2293 (**self).segment(range)
2294 }
2295
2296 #[inline]
2297 fn try_segment(&self, range: impl RangeBounds<usize>) -> Result<Self, TrySegmentError>
2298 where
2299 Self: Sized,
2300 {
2301 (**self).try_segment(range)
2302 }
2303
2304 #[inline]
2305 fn truncate(&mut self, len: usize) {
2306 (**self).truncate(len);
2307 }
2308
2309 #[inline]
2310 fn split_off(&mut self, at: usize) -> Self
2311 where
2312 Self: Sized,
2313 {
2314 (**self).split_off(at)
2315 }
2316
2317 #[inline]
2318 fn split_off_checked(&mut self, at: usize) -> Option<Self>
2319 where
2320 Self: Sized,
2321 {
2322 (**self).split_off_checked(at)
2323 }
2324
2325 #[inline]
2326 fn try_split_off(&mut self, at: usize) -> Result<Self, OutOfBounds>
2327 where
2328 Self: Sized,
2329 {
2330 (**self).try_split_off(at)
2331 }
2332
2333 #[inline]
2334 fn split_to(&mut self, at: usize) -> Self
2335 where
2336 Self: Sized,
2337 {
2338 (**self).split_to(at)
2339 }
2340
2341 #[inline]
2342 fn split_to_checked(&mut self, at: usize) -> Option<Self>
2343 where
2344 Self: Sized,
2345 {
2346 (**self).split_to_checked(at)
2347 }
2348
2349 #[inline]
2350 fn try_split_to(&mut self, at: usize) -> Result<Self, OutOfBounds>
2351 where
2352 Self: Sized,
2353 {
2354 (**self).try_split_to(at)
2355 }
2356
2357 peek_fixed!(@forward u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
2358 read_fixed!(@forward u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
2359
2360 #[inline]
2361 fn peek_u8(&self) -> u8 {
2362 (**self).peek_u8()
2363 }
2364
2365 #[inline]
2366 fn peek_u8_checked(&self) -> Option<u8> {
2367 (**self).peek_u8_checked()
2368 }
2369
2370 #[inline]
2371 fn try_peek_u8(&self) -> Result<u8, TryPeekError> {
2372 (**self).try_peek_u8()
2373 }
2374
2375 #[inline]
2376 fn read_u8(&mut self) -> u8 {
2377 (**self).read_u8()
2378 }
2379
2380 #[inline]
2381 fn read_u8_checked(&mut self) -> Option<u8> {
2382 (**self).read_u8_checked()
2383 }
2384
2385 #[inline]
2386 fn try_read_u8(&mut self) -> Result<u8, TryReadError>
2387 {
2388 (**self).try_read_u8()
2389 }
2390
2391 #[inline]
2392 fn peek_i8(&self) -> i8 {
2393 (**self).peek_i8()
2394 }
2395
2396 #[inline]
2397 fn peek_i8_checked(&self) -> Option<i8> {
2398 (**self).peek_i8_checked()
2399 }
2400
2401 #[inline]
2402 fn try_peek_i8(&self) -> Result<i8, TryPeekError>
2403 {
2404 (**self).try_peek_i8()
2405 }
2406
2407 #[inline]
2408 fn read_i8(&mut self) -> i8 {
2409 (**self).read_i8()
2410 }
2411
2412 #[inline]
2413 fn read_i8_checked(&mut self) -> Option<i8> {
2414 (**self).read_i8_checked()
2415 }
2416
2417 #[inline]
2418 fn try_read_i8(&mut self) -> Result<i8, TryReadError> {
2419 (**self).try_read_i8()
2420 }
2421 }
2422}
2423
2424impl Chunk for &[u8] {
2425 #[inline]
2426 fn remaining(&self) -> usize {
2427 <[u8]>::len(self)
2428 }
2429
2430 #[inline]
2431 fn has_remaining(&self) -> bool {
2432 !<[u8]>::is_empty(self)
2433 }
2434
2435 #[inline]
2436 fn advance(&mut self, cnt: usize) {
2437 if self.len() < cnt {
2438 panic_advance(&TryAdvanceError::new(must_non_zero(cnt), self.len()));
2439 }
2440
2441 *self = &self[cnt..];
2442 }
2443
2444 #[inline]
2445 fn try_advance(&mut self, cnt: usize) -> Result<(), TryAdvanceError> {
2446 if self.len() < cnt {
2447 return Err(TryAdvanceError::new(must_non_zero(cnt), self.len()));
2448 }
2449
2450 *self = &self[cnt..];
2451 Ok(())
2452 }
2453
2454 #[inline]
2455 fn truncate(&mut self, len: usize) {
2456 if len > self.len() {
2457 return;
2458 }
2459
2460 *self = &self[..len];
2461 }
2462
2463 #[inline]
2464 fn segment(&self, range: impl RangeBounds<usize>) -> Self {
2465 let len = self.len();
2466
2467 let begin = match range.start_bound() {
2468 Bound::Included(&n) => n,
2469 Bound::Excluded(&n) => n.checked_add(1).expect("out of range"),
2470 Bound::Unbounded => 0,
2471 };
2472
2473 let end = match range.end_bound() {
2474 Bound::Included(&n) => n.checked_add(1).expect("out of range"),
2475 Bound::Excluded(&n) => n,
2476 Bound::Unbounded => len,
2477 };
2478
2479 &self[begin..end]
2480 }
2481
2482 #[inline]
2483 fn try_segment(&self, range: impl RangeBounds<usize>) -> Result<Self, TrySegmentError> {
2484 check_segment(range, self.len()).map(|(begin, end)| &self[begin..end])
2485 }
2486
2487 #[inline]
2488 fn split_off(&mut self, at: usize) -> Self {
2489 let (left, right) = self.split_at(at);
2490 *self = left;
2491 right
2492 }
2493
2494 #[inline]
2495 fn split_off_checked(&mut self, at: usize) -> Option<Self> {
2496 let (left, right) = self.split_at_checked(at)?;
2497 *self = left;
2498 Some(right)
2499 }
2500
2501 #[inline]
2502 fn split_to(&mut self, at: usize) -> Self {
2503 let (left, right) = self.split_at(at);
2504 *self = right;
2505 left
2506 }
2507
2508 #[inline]
2509 fn split_to_checked(&mut self, at: usize) -> Option<Self> {
2510 let (left, right) = self.split_at_checked(at)?;
2511 *self = right;
2512 Some(left)
2513 }
2514
2515 #[inline]
2516 fn try_split_off(&mut self, at: usize) -> Result<Self, OutOfBounds> {
2517 self
2518 .split_at_checked(at)
2519 .ok_or_else(|| OutOfBounds::new(at, self.len()))
2520 .map(|(left, right)| {
2521 *self = left;
2522 right
2523 })
2524 }
2525
2526 #[inline]
2527 fn try_split_to(&mut self, at: usize) -> Result<Self, OutOfBounds> {
2528 self
2529 .split_at_checked(at)
2530 .ok_or_else(|| OutOfBounds::new(at, self.len()))
2531 .map(|(left, right)| {
2532 *self = right;
2533 left
2534 })
2535 }
2536
2537 #[inline]
2538 fn buffer(&self) -> &[u8] {
2539 self
2540 }
2541
2542 #[inline]
2543 fn buffer_from(&self, offset: usize) -> &[u8] {
2544 &self[offset..]
2545 }
2546
2547 #[inline]
2548 fn buffer_from_checked(&self, offset: usize) -> Option<&[u8]> {
2549 self.split_at_checked(offset).map(|(_, right)| right)
2550 }
2551}
2552
2553#[cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc")))]
2554const _: () = {
2555 use bytes_1::{Buf as _, Bytes};
2556
2557 macro_rules! read_fixed_specification {
2558 ($($ty:ident), +$(,)?) => {
2559 paste::paste! {
2560 $(
2561 fn [<read_ $ty _le>](&mut self) -> $ty {
2562 self.[<get_ $ty _le>]()
2563 }
2564
2565 fn [<read_ $ty _le_checked>](&mut self) -> Option<$ty> {
2566 self.[<try_get_ $ty _le>]().ok()
2567 }
2568
2569 fn [<try_read_ $ty _le>](&mut self) -> Result<$ty, TryReadError> {
2570 self.[<try_get_ $ty _le>]().map_err(Into::into)
2571 }
2572
2573 fn [<read_ $ty _be>](&mut self) -> $ty {
2574 self.[<get_ $ty>]()
2575 }
2576
2577 fn [<read_ $ty _be_checked>](&mut self) -> Option<$ty> {
2578 self.[<try_get_ $ty>]().ok()
2579 }
2580
2581 fn [<try_read_ $ty _be>](&mut self) -> Result<$ty, TryReadError> {
2582 self.[<try_get_ $ty>]().map_err(Into::into)
2583 }
2584
2585 fn [<read_ $ty _ne>](&mut self) -> $ty {
2586 self.[<get_ $ty _ne>]()
2587 }
2588
2589 fn [<read_ $ty _ne_checked>](&mut self) -> Option<$ty> {
2590 self.[<try_get_ $ty _ne>]().ok()
2591 }
2592
2593 fn [<try_read_ $ty _ne>](&mut self) -> Result<$ty, TryReadError> {
2594 self.[<try_get_ $ty _ne>]().map_err(Into::into)
2595 }
2596 )*
2597 }
2598 };
2599 }
2600
2601 #[cfg_attr(
2602 docsrs,
2603 doc(cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc"))))
2604 )]
2605 impl Chunk for Bytes {
2606 #[inline]
2607 fn remaining(&self) -> usize {
2608 self.len()
2609 }
2610
2611 #[inline]
2612 fn has_remaining(&self) -> bool {
2613 !self.is_empty()
2614 }
2615
2616 #[inline]
2617 fn buffer(&self) -> &[u8] {
2618 self.as_ref()
2619 }
2620
2621 #[inline]
2622 fn buffer_from(&self, offset: usize) -> &[u8] {
2623 &self.as_ref()[offset..]
2624 }
2625
2626 #[inline]
2627 fn buffer_from_checked(&self, offset: usize) -> Option<&[u8]> {
2628 self
2629 .as_ref()
2630 .split_at_checked(offset)
2631 .map(|(_, right)| right)
2632 }
2633
2634 #[inline]
2635 fn advance(&mut self, cnt: usize) {
2636 bytes_1::Buf::advance(self, cnt);
2637 }
2638
2639 #[inline]
2640 fn truncate(&mut self, len: usize) {
2641 Bytes::truncate(self, len);
2642 }
2643
2644 #[inline]
2645 fn segment(&self, range: impl RangeBounds<usize>) -> Self {
2646 Bytes::slice(self, range)
2647 }
2648
2649 #[inline]
2650 fn split_off(&mut self, at: usize) -> Self {
2651 Bytes::split_off(self, at)
2652 }
2653
2654 #[inline]
2655 fn split_to(&mut self, at: usize) -> Self {
2656 Bytes::split_to(self, at)
2657 }
2658
2659 #[inline]
2660 fn read_u8(&mut self) -> u8 {
2661 self.get_u8()
2662 }
2663
2664 #[inline]
2665 fn read_u8_checked(&mut self) -> Option<u8> {
2666 self.try_get_u8().ok()
2667 }
2668
2669 #[inline]
2670 fn try_read_u8(&mut self) -> Result<u8, TryReadError> {
2671 self.try_get_u8().map_err(Into::into)
2672 }
2673
2674 #[inline]
2675 fn read_i8(&mut self) -> i8 {
2676 self.get_i8()
2677 }
2678
2679 #[inline]
2680 fn read_i8_checked(&mut self) -> Option<i8> {
2681 self.try_get_i8().ok()
2682 }
2683
2684 #[inline]
2685 fn try_read_i8(&mut self) -> Result<i8, TryReadError> {
2686 self.try_get_i8().map_err(Into::into)
2687 }
2688
2689 #[cfg(all(feature = "bytes_1", any(feature = "std", feature = "alloc")))]
2690 fn to_bytes(&self) -> ::bytes_1::Bytes {
2691 self.clone()
2692 }
2693
2694 read_fixed_specification!(u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
2695 }
2696};
2697
2698#[inline]
2699fn check_segment<R: RangeBounds<usize>>(
2700 range: R,
2701 len: usize,
2702) -> Result<(usize, usize), TrySegmentError> {
2703 let begin = match range.start_bound() {
2704 Bound::Included(&n) => n,
2705 Bound::Excluded(&n) => match n.checked_add(1) {
2706 Some(val) => val,
2707 None => usize::MAX,
2708 },
2709 Bound::Unbounded => 0,
2710 };
2711
2712 let end = match range.end_bound() {
2713 Bound::Included(&n) => match n.checked_add(1) {
2714 Some(val) => val,
2715 None => usize::MAX,
2716 },
2717 Bound::Excluded(&n) => n,
2718 Bound::Unbounded => len,
2719 };
2720
2721 if begin > len || end > len || begin > end {
2722 return Err(TrySegmentError::new(begin, end, len));
2723 }
2724
2725 Ok((begin, end))
2726}
2727
2728#[inline]
2729fn read_array<B: Chunk + ?Sized, const N: usize>(buf: &mut B) -> [u8; N] {
2730 let output = peek_array::<B, N>(buf);
2731 buf.advance(N);
2732 output
2733}
2734
2735#[inline]
2736fn read_array_checked<B: Chunk + ?Sized, const N: usize>(buf: &mut B) -> Option<[u8; N]> {
2737 peek_array_checked::<B, N>(buf).inspect(|_| {
2738 buf.advance(N);
2739 })
2740}
2741
2742#[inline]
2743fn try_read_array<B: Chunk + ?Sized, const N: usize>(buf: &mut B) -> Result<[u8; N], TryReadError> {
2744 try_peek_array::<B, N>(buf)
2745 .inspect(|_| {
2746 buf.advance(N);
2747 })
2748 .map_err(Into::into)
2749}
2750
2751#[inline]
2752fn peek_array<B: Chunk + ?Sized, const N: usize>(buf: &B) -> [u8; N] {
2753 <[u8; N]>::try_from(&buf.buffer()[..N]).expect("Already checked there are enough bytes")
2754}
2755
2756#[inline]
2757fn peek_array_checked<B: Chunk + ?Sized, const N: usize>(buf: &B) -> Option<[u8; N]> {
2758 if N == 0 {
2759 return Some([0u8; N]);
2760 }
2761
2762 if buf.remaining() < N {
2763 None
2764 } else {
2765 Some(<[u8; N]>::try_from(&buf.buffer()[..N]).expect("Already checked there are enough bytes"))
2766 }
2767}
2768
2769#[inline]
2770fn try_peek_array<B: Chunk + ?Sized, const N: usize>(buf: &B) -> Result<[u8; N], TryPeekError> {
2771 if N == 0 {
2772 return Ok([0u8; N]);
2773 }
2774
2775 if buf.remaining() < N {
2776 Err(TryPeekError::new(must_non_zero(N), buf.remaining()))
2777 } else {
2778 Ok(<[u8; N]>::try_from(&buf.buffer()[..N]).expect("Already checked there are enough bytes"))
2779 }
2780}
2781
2782#[inline]
2783fn peek_array_at<B: Chunk + ?Sized, const N: usize>(buf: &B, offset: usize) -> [u8; N] {
2784 buf.buffer_from(offset)[..N].try_into().unwrap()
2785}
2786
2787#[inline]
2788fn peek_array_at_checked<B: Chunk + ?Sized, const N: usize>(
2789 buf: &B,
2790 offset: usize,
2791) -> Option<[u8; N]> {
2792 match buf.buffer_from_checked(offset) {
2793 Some(slice) if slice.len() >= N => Some(slice[..N].try_into().unwrap()),
2794 _ => None,
2795 }
2796}
2797
2798#[inline]
2799fn try_peek_array_at<B: Chunk + ?Sized, const N: usize>(
2800 buf: &B,
2801 offset: usize,
2802) -> Result<[u8; N], TryPeekAtError> {
2803 let buffer = buf.buffer();
2804 let buf_len = buffer.len();
2805
2806 match buf_len.checked_sub(offset) {
2807 None => Err(TryPeekAtError::out_of_bounds(offset, buf_len)),
2808 Some(_) if N == 0 => Ok([0u8; N]),
2809 Some(remaining) if remaining >= N => Ok(
2810 buffer[offset..offset + N]
2811 .try_into()
2812 .expect("Already checked there are enough bytes"),
2813 ),
2814 Some(remaining) => {
2815 let n = must_non_zero(N);
2816 let err = TryPeekAtError::insufficient_data_with_requested(remaining, offset, n);
2817 Err(err)
2818 }
2819 }
2820}
2821
2822#[inline]
2823fn check_out_of_bounds(method_name: &'static str, at: usize, remaining: usize) {
2824 assert!(
2825 at <= remaining,
2826 "{method_name} out of bounds: {at} <= {remaining}",
2827 );
2828}
2829
2830#[inline]
2831fn check_segment_range_bounds(begin: usize, end: usize, current_remaining: usize) {
2832 assert!(
2833 begin <= end,
2834 "range start must not be greater than end: {begin} <= {end}",
2835 );
2836 assert!(
2837 end <= current_remaining,
2838 "range end out of bounds: {end} <= {current_remaining}",
2839 );
2840}
2841
2842#[cfg(test)]
2843mod tests {
2844 use super::*;
2845
2846 struct Wrapper<'a>(&'a [u8]);
2847
2848 impl Chunk for Wrapper<'_> {
2849 fn remaining(&self) -> usize {
2850 self.0.len()
2851 }
2852
2853 fn buffer(&self) -> &[u8] {
2854 self.0
2855 }
2856
2857 fn advance(&mut self, cnt: usize) {
2858 if self.0.len() < cnt {
2859 panic_advance(&TryAdvanceError::new(must_non_zero(cnt), self.0.len()));
2860 }
2861
2862 self.0 = &self.0[cnt..];
2863 }
2864
2865 fn segment(&self, range: impl RangeBounds<usize>) -> Self
2866 where
2867 Self: Sized,
2868 {
2869 let len = self.0.len();
2870 let (begin, end) = check_segment(range, len).expect("out of range");
2871 Wrapper(&self.0[begin..end])
2872 }
2873
2874 fn truncate(&mut self, len: usize) {
2875 if len > self.0.len() {
2876 return;
2877 }
2878
2879 self.0 = &self.0[..len];
2880 }
2881
2882 fn split_off(&mut self, at: usize) -> Self
2883 where
2884 Self: Sized,
2885 {
2886 let (left, right) = self.0.split_at(at);
2887 self.0 = left;
2888 Wrapper(right)
2889 }
2890
2891 fn split_to(&mut self, at: usize) -> Self
2892 where
2893 Self: Sized,
2894 {
2895 let (left, right) = self.0.split_at(at);
2896 self.0 = right;
2897 Wrapper(left)
2898 }
2899 }
2900
2901 #[test]
2902 #[should_panic]
2903 fn test_advance_panic() {
2904 let buf = [0u8; 5];
2905 let mut slice = &buf[..];
2906 slice.advance(10);
2907 }
2908
2909 #[test]
2910 fn test_segment_edge() {
2911 let buf = [1, 2, 3, 4, 5];
2912 let slice = Wrapper(&buf[..]);
2913 let output = slice
2914 .try_segment((Bound::Excluded(1), Bound::Included(3)))
2915 .unwrap();
2916 assert_eq!(output.0, &[3, 4]);
2917
2918 assert!(slice
2919 .try_segment((Bound::Excluded(usize::MAX), Bound::Included(usize::MAX)))
2920 .is_err());
2921 }
2922
2923 #[test]
2924 #[should_panic]
2925 fn test_segment_panic() {
2926 let buf = [1, 2, 3, 4, 5];
2927 let slice = Wrapper(&buf[..]);
2928 let output = slice.segment((Bound::Excluded(1), Bound::Included(3)));
2929 assert_eq!(output.0, &[3, 4]);
2930
2931 slice.segment((Bound::Excluded(usize::MAX), Bound::Included(usize::MAX)));
2932 }
2933
2934 #[test]
2935 fn test_blanket_has_remaining() {
2936 let buf = [0u8; 5];
2937 let slice = Wrapper(&buf[..]);
2938 assert!(slice.has_remaining());
2939
2940 let empty = Wrapper(&[]);
2941 assert!(!empty.has_remaining());
2942 }
2943
2944 #[test]
2945 fn test_blanket_split_off() {
2946 let buf = [1, 2, 3, 4, 5];
2947 let mut slice = Wrapper(&buf[..]);
2948 let right = slice.split_off(2);
2949 assert_eq!(slice.0, &[1, 2]);
2950 assert_eq!(right.0, &[3, 4, 5]);
2951 }
2952
2953 #[test]
2954 fn test_blanket_split_off_checked() {
2955 let buf = [1, 2, 3, 4, 5];
2956 let mut slice = Wrapper(&buf[..]);
2957 let right = slice.split_off_checked(2).unwrap();
2958 assert_eq!(slice.0, &[1, 2]);
2959 assert_eq!(right.0, &[3, 4, 5]);
2960
2961 assert!(slice.split_off_checked(10).is_none());
2962 }
2963
2964 #[test]
2965 fn test_blanket_try_split_off() {
2966 let buf = [1, 2, 3, 4, 5];
2967 let mut slice = Wrapper(&buf[..]);
2968 let right = slice.try_split_off(2).unwrap();
2969 assert_eq!(slice.0, &[1, 2]);
2970 assert_eq!(right.0, &[3, 4, 5]);
2971
2972 assert!(slice.try_split_off(10).is_err());
2973 }
2974
2975 #[test]
2976 fn test_blanket_split_to() {
2977 let buf = [1, 2, 3, 4, 5];
2978 let mut slice = Wrapper(&buf[..]);
2979 let right = slice.split_to(2);
2980 assert_eq!(slice.0, &[3, 4, 5]);
2981 assert_eq!(right.0, &[1, 2]);
2982 }
2983
2984 #[test]
2985 fn test_blanket_split_to_checked() {
2986 let buf = [1, 2, 3, 4, 5];
2987 let mut slice = Wrapper(&buf[..]);
2988 let right = slice.split_to_checked(2).unwrap();
2989 assert_eq!(slice.0, &[3, 4, 5]);
2990 assert_eq!(right.0, &[1, 2]);
2991
2992 assert!(slice.split_to_checked(10).is_none());
2993 }
2994
2995 #[test]
2996 fn test_blanket_try_split_to() {
2997 let buf = [1, 2, 3, 4, 5];
2998 let mut slice = Wrapper(&buf[..]);
2999 let right = slice.try_split_to(2).unwrap();
3000 assert_eq!(slice.0, &[3, 4, 5]);
3001 assert_eq!(right.0, &[1, 2]);
3002
3003 assert!(slice.try_split_to(10).is_err());
3004 }
3005
3006 #[test]
3007 fn test_blanket_buffer_from() {
3008 let buf = [1, 2, 3, 4, 5];
3009 let slice = Wrapper(&buf[..]);
3010 assert_eq!(slice.buffer_from(2), &[3, 4, 5]);
3011 }
3012
3013 #[test]
3014 fn test_blanket_buffer_from_checked() {
3015 let buf = [1, 2, 3, 4, 5];
3016 let slice = Wrapper(&buf[..]);
3017 assert_eq!(slice.buffer_from_checked(2), Some(&[3, 4, 5][..]));
3018 assert_eq!(slice.buffer_from_checked(10), None);
3019 }
3020
3021 #[test]
3022 fn test_blanket_peek_array_0() {
3023 let buf = [1, 2, 3, 4, 5];
3024 let slice = Wrapper(&buf[..]);
3025 let arr: [u8; 0] = slice.peek_array();
3026 assert_eq!(arr, []);
3027
3028 let buf = [];
3029 let slice = Wrapper(&buf[..]);
3030 let arr: [u8; 0] = slice.peek_array();
3031 assert_eq!(arr, []);
3032 }
3033
3034 #[test]
3035 fn test_blanket_peek_checked_array_0() {
3036 let buf = [1, 2, 3, 4, 5];
3037 let slice = Wrapper(&buf[..]);
3038 let arr: Option<[u8; 0]> = slice.peek_array_checked();
3039 assert_eq!(arr, Some([]));
3040 }
3041
3042 #[test]
3043 fn test_blanket_try_peek_array_0() {
3044 let buf = [1, 2, 3, 4, 5];
3045 let slice = Wrapper(&buf[..]);
3046 let arr: Result<[u8; 0], TryPeekError> = slice.try_peek_array();
3047 assert_eq!(arr, Ok([]));
3048 }
3049
3050 #[test]
3051 fn test_blanket_peek_at_array_0() {
3052 let buf = [1, 2, 3, 4, 5];
3053 let slice = Wrapper(&buf[..]);
3054 let arr: [u8; 0] = slice.peek_array_at(2);
3055 assert_eq!(arr, []);
3056
3057 let buf = [1, 2, 3, 4, 5];
3058 let slice = Wrapper(&buf[..]);
3059 let arr: [u8; 0] = slice.peek_array_at(5);
3060 assert_eq!(arr, []);
3061
3062 let buf = [];
3063 let slice = Wrapper(&buf[..]);
3064 let arr: [u8; 0] = slice.peek_array_at(0);
3065 assert_eq!(arr, []);
3066 }
3067
3068 #[test]
3069 fn test_blanket_peek_at_checked_array_0() {
3070 let buf = [1, 2, 3, 4, 5];
3071 let slice = Wrapper(&buf[..]);
3072 let arr: Option<[u8; 0]> = slice.peek_array_at_checked(2);
3073 assert_eq!(arr, Some([]));
3074
3075 let buf = [1, 2, 3, 4, 5];
3076 let slice = Wrapper(&buf[..]);
3077 let arr: Option<[u8; 0]> = slice.peek_array_at_checked(5);
3078 assert_eq!(arr, Some([]));
3079
3080 let buf = [];
3081 let slice = Wrapper(&buf[..]);
3082 let arr: Option<[u8; 0]> = slice.peek_array_at_checked(0);
3083 assert_eq!(arr, Some([]));
3084
3085 let buf = [1, 2, 3, 4, 5];
3086 let slice = Wrapper(&buf[..]);
3087 let arr: Option<[u8; 0]> = slice.peek_array_at_checked(10);
3088 assert_eq!(arr, None);
3089 }
3090
3091 #[test]
3092 fn test_blanket_try_peek_at_array_0() {
3093 let buf = [1, 2, 3, 4, 5];
3094 let slice = Wrapper(&buf[..]);
3095 let arr: Result<[u8; 0], TryPeekAtError> = slice.try_peek_array_at(2);
3096 assert_eq!(arr, Ok([]));
3097
3098 let buf = [1, 2, 3, 4, 5];
3099 let slice = Wrapper(&buf[..]);
3100 let arr: Result<[u8; 0], TryPeekAtError> = slice.try_peek_array_at(5);
3101 assert_eq!(arr, Ok([]));
3102
3103 let buf = [];
3104 let slice = Wrapper(&buf[..]);
3105 let arr: Result<[u8; 0], TryPeekAtError> = slice.try_peek_array_at(0);
3106 assert_eq!(arr, Ok([]));
3107
3108 let buf = [1, 2, 3, 4, 5];
3109 let slice = Wrapper(&buf[..]);
3110 let arr: Result<[u8; 0], TryPeekAtError> = slice.try_peek_array_at(10);
3111 assert!(arr.is_err());
3112 }
3113
3114 #[test]
3115 #[cfg(feature = "bytes_1")]
3116 fn test_to_bytes() {
3117 let slice = Wrapper(&[1, 2, 3, 4, 5]);
3118 let bytes = slice.to_bytes();
3119 assert_eq!(bytes, bytes_1::Bytes::from(&[1, 2, 3, 4, 5][..]));
3120 }
3121}