Skip to main content

smol_bytes/buffer/
io.rs

1//! Const I/O methods for Buffer matching bytes::Buf and bytes::BufMut trait signatures.
2//!
3//! These methods allow Buffer to be used in no_std/no_alloc environments while providing
4//! the same API as the bytes crate.
5
6use crate::{InvalidIntegerLength, TryPutIntegerError};
7
8use super::{Buffer, InlineSize, TryGetError, TryPutError, panic_advance, panic_does_not_fit};
9
10/// Validates the byte width accepted by the variable-width integer readers.
11///
12/// This is deliberately performed before checking available input so an invalid
13/// width cannot be masked by a short buffer (or reach the copy below).
14#[inline]
15pub(crate) fn assert_uint_width(nbytes: usize) {
16  if nbytes > 8 {
17    panic_does_not_fit(8, nbytes);
18  }
19}
20
21// https://en.wikipedia.org/wiki/Sign_extension
22pub(crate) const fn sign_extend(val: u64, nbytes: usize) -> i64 {
23  if nbytes == 0 {
24    return 0;
25  }
26
27  let shift = (8 - nbytes) * 8;
28  (val << shift) as i64 >> shift
29}
30
31macro_rules! impl_try_get {
32  ($this:ident, $typ:tt::$conv:tt) => {{
33    const SIZE: usize = core::mem::size_of::<$typ>();
34
35    let remaining = $this.remaining();
36
37    if remaining < SIZE {
38      return Err(TryGetError {
39        requested: SIZE,
40        available: remaining,
41      });
42    }
43
44    unsafe {
45      let ptr = $this.buf.as_ptr().add($this.cur.to_usize());
46      let val = $typ::$conv(*(ptr as *const _ as *const [_; SIZE]));
47
48      $this.cur = InlineSize::from_u8($this.cur.to_u8() + SIZE as u8);
49      Ok(val)
50    }
51  }};
52  (le($this:ident, $typ:tt, $len_to_read:expr)) => {{
53    const SIZE: usize = core::mem::size_of::<$typ>();
54
55    assert_uint_width($len_to_read);
56
57    let remaining = $this.remaining();
58    if remaining < $len_to_read {
59      return Err(TryGetError {
60        requested: $len_to_read,
61        available: remaining,
62      });
63    }
64
65    let mut buf = [0u8; SIZE];
66
67    unsafe {
68      // SAFETY: checked above that there is enough remaining data
69      // For LE: copy to the START of the buffer [data..., 0, 0, 0]
70      core::ptr::copy_nonoverlapping(
71        $this.buf.as_ptr().add($this.cur.to_usize()).cast::<u8>(),
72        buf.as_mut_ptr(),
73        $len_to_read,
74      );
75      let val = $typ::from_le_bytes(buf);
76
77      $this.cur = InlineSize::from_u8($this.cur.to_u8() + $len_to_read as u8);
78      Ok(val)
79    }
80  }};
81  (be($this:ident, $typ:tt, $len_to_read:expr)) => {{
82    const SIZE: usize = core::mem::size_of::<$typ>();
83
84    assert_uint_width($len_to_read);
85
86    let remaining = $this.remaining();
87    if remaining < $len_to_read {
88      return Err(TryGetError {
89        requested: $len_to_read,
90        available: remaining,
91      });
92    }
93
94    let slice_at = SIZE - $len_to_read;
95    let mut buf = [0u8; SIZE];
96
97    unsafe {
98      // SAFETY: checked above that there is enough remaining data
99      // For BE: copy to the END of the buffer [0, 0, 0, ..., data...]
100      core::ptr::copy_nonoverlapping(
101        $this.buf.as_ptr().add($this.cur.to_usize()).cast::<u8>(),
102        buf.as_mut_ptr().add(slice_at),
103        $len_to_read,
104      );
105      let val = $typ::from_be_bytes(buf);
106
107      $this.cur = InlineSize::from_u8($this.cur.to_u8() + $len_to_read as u8);
108      Ok(val)
109    }
110  }};
111}
112
113macro_rules! try_get_and_get {
114  ($long:literal: { $($typ:ident::$conv:ident$(::$order:ident)?),+$(,)? }) => {
115    paste::paste! {
116      $(
117        #[doc = "Gets a `" $typ "` from `self` in " $long " byte order."]
118        ///
119        /// The current position is advanced by the size of the type.
120        ///
121        /// ## Panics
122        ///
123        /// This function panics if there is not enough remaining data in `self`.
124        #[inline]
125        pub fn [<get_ $typ:lower $(_ $order)?>](&mut self) -> $typ {
126          self.[<try_get_ $typ:lower $(_ $order)?>]().unwrap_or_else(|e| panic_advance(e.available, e.requested))
127        }
128
129        #[doc = "Tries to get a `" $typ "` from `self` in " $long " byte order."]
130        ///
131        /// The current position is advanced by the size of the type.
132        ///
133        /// ## Errors
134        ///
135        /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
136        #[inline]
137        pub const fn [<try_get_ $typ:lower $(_ $order)?>](&mut self) -> Result<$typ, TryGetError> {
138          impl_try_get!(self, $typ::$conv)
139        }
140      )*
141    }
142  };
143}
144
145macro_rules! try_put_and_put {
146  ($long:literal: { $($typ:ident::$conv:ident$(::$order:ident)?),+$(,)? }) => {
147    paste::paste! {
148      $(
149        #[doc = "Puts a `" $typ "` to `self` in " $long " byte order."]
150        ///
151        /// The current length is advanced by the size of the type.
152        ///
153        /// ## Panics
154        ///
155        /// This function panics if there is not enough remaining capacity in `self`.
156        #[inline]
157        pub fn [<put_ $typ:lower $(_ $order)?>](&mut self, val: $typ) {
158          self.[<try_put_ $typ:lower $(_ $order)?>](val)
159            .unwrap_or_else(|e| panic_advance(e.available, e.requested))
160        }
161
162        #[doc = "Tries to put a `" $typ "` to `self` in " $long " byte order."]
163        ///
164        /// The current length is advanced by the size of the type.
165        ///
166        /// ## Errors
167        ///
168        /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
169        #[inline]
170        pub const fn [<try_put_ $typ:lower $(_ $order)?>](&mut self, val: $typ) -> Result<(), TryPutError> {
171          self.try_put_slice(val.$conv().as_slice())
172        }
173      )*
174    }
175  };
176}
177
178impl Buffer {
179  try_get_and_get!(
180    "little-endian": {
181      u16::from_le_bytes::le,
182      i16::from_le_bytes::le,
183      u32::from_le_bytes::le,
184      i32::from_le_bytes::le,
185      u64::from_le_bytes::le,
186      i64::from_le_bytes::le,
187      u128::from_le_bytes::le,
188      i128::from_le_bytes::le,
189    }
190  );
191
192  try_get_and_get!(
193    "big-endian": {
194      u16::from_be_bytes,
195      i16::from_be_bytes,
196      u32::from_be_bytes,
197      i32::from_be_bytes,
198      u64::from_be_bytes,
199      i64::from_be_bytes,
200      u128::from_be_bytes,
201      i128::from_be_bytes,
202    }
203  );
204
205  try_get_and_get!(
206    "native-endian": {
207      u16::from_ne_bytes::ne,
208      i16::from_ne_bytes::ne,
209      u32::from_ne_bytes::ne,
210      i32::from_ne_bytes::ne,
211      u64::from_ne_bytes::ne,
212      i64::from_ne_bytes::ne,
213      u128::from_ne_bytes::ne,
214      i128::from_ne_bytes::ne,
215    }
216  );
217
218  /// Gets an unsigned 8 bit integer from `self`.
219  ///
220  /// The current position is advanced by 1.
221  ///
222  /// ## Examples
223  ///
224  /// ```
225  /// use smol_bytes::Buffer;
226  ///
227  /// let mut buf = Buffer::try_from(&b"\x08 hello"[..]).unwrap();
228  /// assert_eq!(8, buf.get_u8());
229  /// assert_eq!(6, buf.remaining());
230  /// ```
231  ///
232  /// ## Panics
233  ///
234  /// This function panics if there is no more remaining data in `self`.
235  #[inline]
236  pub fn get_u8(&mut self) -> u8 {
237    match self.try_get_u8() {
238      Ok(v) => v,
239      Err(e) => panic_advance(e.available, e.requested),
240    }
241  }
242
243  /// Tries to get an unsigned 8 bit integer from `self`.
244  ///
245  /// The current position is advanced by 1.
246  ///
247  /// ## Examples
248  ///
249  /// ```
250  /// use smol_bytes::Buffer;
251  ///
252  /// let mut buf = Buffer::try_from(&b"\x08 hello"[..]).unwrap();
253  /// assert_eq!(8, buf.try_get_u8().unwrap());
254  /// assert_eq!(6, buf.remaining());
255  /// ```
256  ///
257  /// ## Errors
258  ///
259  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
260  #[inline]
261  pub const fn try_get_u8(&mut self) -> Result<u8, TryGetError> {
262    if self.remaining() < 1 {
263      return Err(TryGetError {
264        requested: 1,
265        available: self.remaining(),
266      });
267    }
268
269    // SAFETY: checked above that there is at least 1 byte remaining
270    let ret = unsafe { self.buf[self.cur.to_usize()].assume_init_read() };
271    self.cur = unsafe { InlineSize::from_u8(self.cur.to_u8() + 1) };
272    Ok(ret)
273  }
274
275  /// Gets a signed 8 bit integer from `self`.
276  ///
277  /// The current position is advanced by 1.
278  ///
279  /// ## Panics
280  ///
281  /// This function panics if there is no more remaining data in `self`.
282  #[inline]
283  pub fn get_i8(&mut self) -> i8 {
284    Self::get_u8(self) as i8
285  }
286
287  /// Tries to get a signed 8 bit integer from `self`.
288  ///
289  /// The current position is advanced by 1.
290  ///
291  /// ## Errors
292  ///
293  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
294  #[inline]
295  pub const fn try_get_i8(&mut self) -> Result<i8, TryGetError> {
296    match Self::try_get_u8(self) {
297      Ok(v) => Ok(v as i8),
298      Err(e) => Err(e),
299    }
300  }
301
302  /// Gets an IEEE754 single-precision (4 bytes) floating point number from
303  /// `self` in big-endian byte order.
304  ///
305  /// The current position is advanced by 4.
306  ///
307  /// ## Examples
308  ///
309  /// ```
310  /// use smol_bytes::Buffer;
311  ///
312  /// let mut buf = Buffer::try_from(&[0x41, 0x48, 0x00, 0x00][..]).unwrap();
313  /// assert_eq!(12.5, buf.get_f32());
314  /// ```
315  ///
316  /// ## Panics
317  ///
318  /// This function panics if there is not enough remaining data in `self`.
319  #[inline]
320  pub fn get_f32(&mut self) -> f32 {
321    f32::from_bits(self.get_u32())
322  }
323
324  /// Tries to get an IEEE754 single-precision (4 bytes) floating point number from
325  /// `self` in big-endian byte order.
326  ///
327  /// The current position is advanced by 4.
328  ///
329  /// ## Errors
330  ///
331  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
332  #[inline]
333  pub const fn try_get_f32(&mut self) -> Result<f32, TryGetError> {
334    match self.try_get_u32() {
335      Ok(bits) => Ok(f32::from_bits(bits)),
336      Err(e) => Err(e),
337    }
338  }
339
340  /// Gets an IEEE754 single-precision (4 bytes) floating point number from
341  /// `self` in little-endian byte order.
342  ///
343  /// The current position is advanced by 4.
344  ///
345  /// ## Panics
346  ///
347  /// This function panics if there is not enough remaining data in `self`.
348  #[inline]
349  pub fn get_f32_le(&mut self) -> f32 {
350    f32::from_bits(self.get_u32_le())
351  }
352
353  /// Tries to get an IEEE754 single-precision (4 bytes) floating point number from
354  /// `self` in little-endian byte order.
355  ///
356  /// The current position is advanced by 4.
357  ///
358  /// ## Errors
359  ///
360  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
361  #[inline]
362  pub const fn try_get_f32_le(&mut self) -> Result<f32, TryGetError> {
363    match self.try_get_u32_le() {
364      Ok(bits) => Ok(f32::from_bits(bits)),
365      Err(e) => Err(e),
366    }
367  }
368
369  /// Gets an IEEE754 single-precision (4 bytes) floating point number from
370  /// `self` in native-endian byte order.
371  ///
372  /// The current position is advanced by 4.
373  ///
374  /// ## Panics
375  ///
376  /// This function panics if there is not enough remaining data in `self`.
377  #[inline]
378  pub fn get_f32_ne(&mut self) -> f32 {
379    f32::from_bits(self.get_u32_ne())
380  }
381
382  /// Tries to get an IEEE754 single-precision (4 bytes) floating point number from
383  /// `self` in native-endian byte order.
384  ///
385  /// The current position is advanced by 4.
386  ///
387  /// ## Errors
388  ///
389  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
390  #[inline]
391  pub const fn try_get_f32_ne(&mut self) -> Result<f32, TryGetError> {
392    match self.try_get_u32_ne() {
393      Ok(bits) => Ok(f32::from_bits(bits)),
394      Err(e) => Err(e),
395    }
396  }
397
398  /// Gets an IEEE754 double-precision (8 bytes) floating point number from
399  /// `self` in big-endian byte order.
400  ///
401  /// The current position is advanced by 8.
402  ///
403  /// ## Panics
404  ///
405  /// This function panics if there is not enough remaining data in `self`.
406  #[inline]
407  pub fn get_f64(&mut self) -> f64 {
408    f64::from_bits(self.get_u64())
409  }
410
411  /// Tries to get an IEEE754 double-precision (8 bytes) floating point number from
412  /// `self` in big-endian byte order.
413  ///
414  /// The current position is advanced by 8.
415  ///
416  /// ## Errors
417  ///
418  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
419  #[inline]
420  pub const fn try_get_f64(&mut self) -> Result<f64, TryGetError> {
421    match self.try_get_u64() {
422      Ok(bits) => Ok(f64::from_bits(bits)),
423      Err(e) => Err(e),
424    }
425  }
426
427  /// Gets an IEEE754 double-precision (8 bytes) floating point number from
428  /// `self` in little-endian byte order.
429  ///
430  /// The current position is advanced by 8.
431  ///
432  /// ## Panics
433  ///
434  /// This function panics if there is not enough remaining data in `self`.
435  #[inline]
436  pub fn get_f64_le(&mut self) -> f64 {
437    f64::from_bits(self.get_u64_le())
438  }
439
440  /// Tries to get an IEEE754 double-precision (8 bytes) floating point number from
441  /// `self` in little-endian byte order.
442  ///
443  /// The current position is advanced by 8.
444  ///
445  /// ## Errors
446  ///
447  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
448  #[inline]
449  pub const fn try_get_f64_le(&mut self) -> Result<f64, TryGetError> {
450    match self.try_get_u64_le() {
451      Ok(bits) => Ok(f64::from_bits(bits)),
452      Err(e) => Err(e),
453    }
454  }
455
456  /// Gets an IEEE754 double-precision (8 bytes) floating point number from
457  /// `self` in native-endian byte order.
458  ///
459  /// The current position is advanced by 8.
460  ///
461  /// ## Panics
462  ///
463  /// This function panics if there is not enough remaining data in `self`.
464  #[inline]
465  pub fn get_f64_ne(&mut self) -> f64 {
466    f64::from_bits(self.get_u64_ne())
467  }
468
469  /// Tries to get an IEEE754 double-precision (8 bytes) floating point number from
470  /// `self` in native-endian byte order.
471  ///
472  /// The current position is advanced by 8.
473  ///
474  /// ## Errors
475  ///
476  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
477  #[inline]
478  pub const fn try_get_f64_ne(&mut self) -> Result<f64, TryGetError> {
479    match self.try_get_u64_ne() {
480      Ok(bits) => Ok(f64::from_bits(bits)),
481      Err(e) => Err(e),
482    }
483  }
484
485  /// Gets an unsigned n-byte integer from `self` in big-endian byte order.
486  ///
487  /// The current position is advanced by `nbytes`.
488  ///
489  /// ## Examples
490  ///
491  /// ```
492  /// use smol_bytes::Buffer;
493  ///
494  /// let mut buf = Buffer::try_from(&b"\x01\x02\x03"[..]).unwrap();
495  /// assert_eq!(0x010203, buf.get_uint(3));
496  /// ```
497  ///
498  /// ## Panics
499  ///
500  /// This function panics if there is not enough remaining data in `self`,
501  /// or if `nbytes` is greater than 8.
502  #[inline]
503  pub fn get_uint(&mut self, nbytes: usize) -> u64 {
504    self
505      .try_get_uint(nbytes)
506      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
507  }
508
509  /// Tries to get an unsigned n-byte integer from `self` in big-endian byte order.
510  ///
511  /// The current position is advanced by `nbytes`.
512  ///
513  /// ## Errors
514  ///
515  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
516  ///
517  /// ## Panics
518  ///
519  /// This function panics if `nbytes` is greater than 8.
520  #[inline]
521  pub fn try_get_uint(&mut self, nbytes: usize) -> Result<u64, TryGetError> {
522    impl_try_get!(be(self, u64, nbytes))
523  }
524
525  /// Gets an unsigned n-byte integer from `self` in little-endian byte order.
526  ///
527  /// The current position is advanced by `nbytes`.
528  ///
529  /// ## Panics
530  ///
531  /// This function panics if there is not enough remaining data in `self`,
532  /// or if `nbytes` is greater than 8.
533  #[inline]
534  pub fn get_uint_le(&mut self, nbytes: usize) -> u64 {
535    self
536      .try_get_uint_le(nbytes)
537      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
538  }
539
540  /// Tries to get an unsigned n-byte integer from `self` in little-endian byte order.
541  ///
542  /// The current position is advanced by `nbytes`.
543  ///
544  /// ## Errors
545  ///
546  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
547  ///
548  /// ## Panics
549  ///
550  /// This function panics if `nbytes` is greater than 8.
551  #[inline]
552  pub fn try_get_uint_le(&mut self, nbytes: usize) -> Result<u64, TryGetError> {
553    impl_try_get!(le(self, u64, nbytes))
554  }
555
556  /// Gets an unsigned n-byte integer from `self` in native-endian byte order.
557  ///
558  /// The current position is advanced by `nbytes`.
559  ///
560  /// ## Panics
561  ///
562  /// This function panics if there is not enough remaining data in `self`,
563  /// or if `nbytes` is greater than 8.
564  #[inline]
565  pub fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
566    self
567      .try_get_uint_ne(nbytes)
568      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
569  }
570
571  /// Tries to get an unsigned n-byte integer from `self` in native-endian byte order.
572  ///
573  /// The current position is advanced by `nbytes`.
574  ///
575  /// ## Errors
576  ///
577  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
578  ///
579  /// ## Panics
580  ///
581  /// This function panics if `nbytes` is greater than 8.
582  #[inline]
583  pub fn try_get_uint_ne(&mut self, nbytes: usize) -> Result<u64, TryGetError> {
584    if cfg!(target_endian = "big") {
585      self.try_get_uint(nbytes)
586    } else {
587      self.try_get_uint_le(nbytes)
588    }
589  }
590
591  /// Gets a signed n-byte integer from `self` in big-endian byte order.
592  ///
593  /// The current position is advanced by `nbytes`.
594  ///
595  /// ## Panics
596  ///
597  /// This function panics if there is not enough remaining data in `self`,
598  /// or if `nbytes` is greater than 8.
599  #[inline]
600  pub fn get_int(&mut self, nbytes: usize) -> i64 {
601    sign_extend(self.get_uint(nbytes), nbytes)
602  }
603
604  /// Tries to get a signed n-byte integer from `self` in big-endian byte order.
605  ///
606  /// The current position is advanced by `nbytes`.
607  ///
608  /// ## Errors
609  ///
610  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
611  ///
612  /// ## Panics
613  ///
614  /// This function panics if `nbytes` is greater than 8.
615  #[inline]
616  pub fn try_get_int(&mut self, nbytes: usize) -> Result<i64, TryGetError> {
617    self
618      .try_get_uint(nbytes)
619      .map(|value| sign_extend(value, nbytes))
620  }
621
622  /// Gets a signed n-byte integer from `self` in little-endian byte order.
623  ///
624  /// The current position is advanced by `nbytes`.
625  ///
626  /// ## Panics
627  ///
628  /// This function panics if there is not enough remaining data in `self`,
629  /// or if `nbytes` is greater than 8.
630  #[inline]
631  pub fn get_int_le(&mut self, nbytes: usize) -> i64 {
632    sign_extend(self.get_uint_le(nbytes), nbytes)
633  }
634
635  /// Tries to get a signed n-byte integer from `self` in little-endian byte order.
636  ///
637  /// The current position is advanced by `nbytes`.
638  ///
639  /// ## Errors
640  ///
641  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
642  ///
643  /// ## Panics
644  ///
645  /// This function panics if `nbytes` is greater than 8.
646  #[inline]
647  pub fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, TryGetError> {
648    self
649      .try_get_uint_le(nbytes)
650      .map(|value| sign_extend(value, nbytes))
651  }
652
653  /// Gets a signed n-byte integer from `self` in native-endian byte order.
654  ///
655  /// The current position is advanced by `nbytes`.
656  ///
657  /// ## Panics
658  ///
659  /// This function panics if there is not enough remaining data in `self`,
660  /// or if `nbytes` is greater than 8.
661  #[inline]
662  pub fn get_int_ne(&mut self, nbytes: usize) -> i64 {
663    if cfg!(target_endian = "big") {
664      self.get_int(nbytes)
665    } else {
666      self.get_int_le(nbytes)
667    }
668  }
669
670  /// Tries to get a signed n-byte integer from `self` in native-endian byte order.
671  ///
672  /// The current position is advanced by `nbytes`.
673  ///
674  /// ## Errors
675  ///
676  /// Returns `Err(TryGetError)` if there is not enough remaining data in `self`.
677  ///
678  /// ## Panics
679  ///
680  /// This function panics if `nbytes` is greater than 8.
681  #[inline]
682  pub fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, TryGetError> {
683    if cfg!(target_endian = "big") {
684      self.try_get_int(nbytes)
685    } else {
686      self.try_get_int_le(nbytes)
687    }
688  }
689}
690
691impl Buffer {
692  try_put_and_put!(
693    "little-endian": {
694      u16::to_le_bytes::le,
695      i16::to_le_bytes::le,
696      u32::to_le_bytes::le,
697      i32::to_le_bytes::le,
698      u64::to_le_bytes::le,
699      i64::to_le_bytes::le,
700      u128::to_le_bytes::le,
701      i128::to_le_bytes::le,
702    }
703  );
704
705  try_put_and_put!(
706    "big-endian": {
707      u16::to_be_bytes,
708      i16::to_be_bytes,
709      u32::to_be_bytes,
710      i32::to_be_bytes,
711      u64::to_be_bytes,
712      i64::to_be_bytes,
713      u128::to_be_bytes,
714      i128::to_be_bytes,
715    }
716  );
717
718  try_put_and_put!(
719    "native-endian": {
720      u16::to_ne_bytes::ne,
721      i16::to_ne_bytes::ne,
722      u32::to_ne_bytes::ne,
723      i32::to_ne_bytes::ne,
724      u64::to_ne_bytes::ne,
725      i64::to_ne_bytes::ne,
726      u128::to_ne_bytes::ne,
727      i128::to_ne_bytes::ne,
728    }
729  );
730
731  /// Writes a signed 8 bit integer to `self`.
732  ///
733  /// The current position is advanced by 1.
734  ///
735  /// ## Examples
736  ///
737  /// ```
738  /// use smol_bytes::Buffer;
739  ///
740  /// let mut buf = Buffer::new();
741  /// buf.put_i8(-5);
742  /// assert_eq!(buf[0], 251);
743  /// ```
744  ///
745  /// ## Panics
746  ///
747  /// This function panics if there is not enough remaining capacity in `self`.
748  #[inline]
749  pub fn put_i8(&mut self, n: i8) {
750    self
751      .try_put_i8(n)
752      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
753  }
754
755  /// Tries to write a signed 8 bit integer to `self`.
756  ///
757  /// The current position is advanced by 1.
758  ///
759  /// ## Errors
760  ///
761  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
762  #[inline]
763  pub const fn try_put_i8(&mut self, n: i8) -> Result<(), TryPutError> {
764    self.try_put_u8(n as u8)
765  }
766
767  /// Writes an unsigned n-byte integer to `self` in big-endian byte order.
768  ///
769  /// The current position is advanced by `nbytes`.
770  ///
771  /// ## Panics
772  ///
773  /// This function panics if there is not enough remaining capacity in `self`,
774  /// or if `nbytes` is greater than 8.
775  #[inline]
776  pub fn put_uint(&mut self, n: u64, nbytes: usize) {
777    self
778      .try_put_uint(n, nbytes)
779      .unwrap_or_else(|e| panic!("{e}"));
780  }
781
782  /// Tries to write an unsigned n-byte integer to `self` in big-endian byte order.
783  ///
784  /// The current position is advanced by `nbytes`.
785  ///
786  /// ## Errors
787  ///
788  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
789  #[inline]
790  pub const fn try_put_uint(&mut self, n: u64, nbytes: usize) -> Result<(), TryPutIntegerError> {
791    if nbytes > 8 {
792      return Err(TryPutIntegerError::InvalidLength(InvalidIntegerLength(
793        nbytes,
794      )));
795    }
796
797    let available = self.remaining_mut();
798    if available < nbytes {
799      return Err(TryPutIntegerError::NotEnoughSpace(TryPutError {
800        requested: nbytes,
801        available,
802      }));
803    }
804
805    let bytes = n.to_be_bytes();
806    let mut i = 0;
807    while i < nbytes {
808      // SAFETY: the capacity check proves `end + nbytes <= INLINE_CAP`, and
809      // `i < nbytes`; this writes one byte within the uninitialized tail.
810      unsafe {
811        *self
812          .buf
813          .as_mut_ptr()
814          .add(self.end.to_usize() + i)
815          .cast::<u8>() = bytes[8 - nbytes + i];
816      }
817      i += 1;
818    }
819    // SAFETY: the capacity check proves the new absolute end is at most
820    // `INLINE_CAP`, and the loop initialized every newly exposed byte.
821    self.end = unsafe { InlineSize::from_u8(self.end.to_u8() + nbytes as u8) };
822    Ok(())
823  }
824
825  /// Writes an unsigned n-byte integer to `self` in little-endian byte order.
826  ///
827  /// The current position is advanced by `nbytes`.
828  ///
829  /// ## Panics
830  ///
831  /// This function panics if there is not enough remaining capacity in `self`,
832  /// or if `nbytes` is greater than 8.
833  #[inline]
834  pub fn put_uint_le(&mut self, n: u64, nbytes: usize) {
835    self
836      .try_put_uint_le(n, nbytes)
837      .unwrap_or_else(|e| panic!("{e}"))
838  }
839
840  /// Tries to write an unsigned n-byte integer to `self` in little-endian byte order.
841  ///
842  /// The current position is advanced by `nbytes`.
843  ///
844  /// ## Errors
845  ///
846  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
847  #[inline]
848  pub const fn try_put_uint_le(&mut self, n: u64, nbytes: usize) -> Result<(), TryPutIntegerError> {
849    if nbytes > 8 {
850      return Err(TryPutIntegerError::InvalidLength(InvalidIntegerLength(
851        nbytes,
852      )));
853    }
854
855    let available = self.remaining_mut();
856    if available < nbytes {
857      return Err(TryPutIntegerError::NotEnoughSpace(TryPutError {
858        requested: nbytes,
859        available,
860      }));
861    }
862
863    let bytes = n.to_le_bytes();
864    let mut i = 0;
865    while i < nbytes {
866      // SAFETY: the capacity check proves `end + nbytes <= INLINE_CAP`, and
867      // `i < nbytes`; this writes one byte within the uninitialized tail.
868      unsafe {
869        *self
870          .buf
871          .as_mut_ptr()
872          .add(self.end.to_usize() + i)
873          .cast::<u8>() = bytes[i];
874      }
875      i += 1;
876    }
877    // SAFETY: the capacity check proves the new absolute end is at most
878    // `INLINE_CAP`, and the loop initialized every newly exposed byte.
879    self.end = unsafe { InlineSize::from_u8(self.end.to_u8() + nbytes as u8) };
880    Ok(())
881  }
882
883  /// Writes an unsigned n-byte integer to `self` in native-endian byte order.
884  ///
885  /// The current position is advanced by `nbytes`.
886  ///
887  /// ## Panics
888  ///
889  /// This function panics if there is not enough remaining capacity in `self`,
890  /// or if `nbytes` is greater than 8.
891  #[inline]
892  pub fn put_uint_ne(&mut self, n: u64, nbytes: usize) {
893    self
894      .try_put_uint_ne(n, nbytes)
895      .unwrap_or_else(|e| panic!("{e}"))
896  }
897
898  /// Tries to write an unsigned n-byte integer to `self` in native-endian byte order.
899  ///
900  /// The current position is advanced by `nbytes`.
901  ///
902  /// ## Errors
903  ///
904  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
905  ///
906  /// ## Panics
907  ///
908  /// This function panics if `nbytes` is greater than 8.
909  #[inline]
910  pub const fn try_put_uint_ne(&mut self, n: u64, nbytes: usize) -> Result<(), TryPutIntegerError> {
911    if cfg!(target_endian = "big") {
912      self.try_put_uint(n, nbytes)
913    } else {
914      self.try_put_uint_le(n, nbytes)
915    }
916  }
917
918  /// Writes a signed n-byte integer to `self` in big-endian byte order.
919  ///
920  /// The current position is advanced by `nbytes`.
921  ///
922  /// ## Panics
923  ///
924  /// This function panics if there is not enough remaining capacity in `self`,
925  /// or if `nbytes` is greater than 8.
926  #[inline]
927  pub fn put_int(&mut self, n: i64, nbytes: usize) {
928    self
929      .try_put_int(n, nbytes)
930      .unwrap_or_else(|e| panic!("{e}"));
931  }
932
933  /// Tries to write a signed n-byte integer to `self` in big-endian byte order.
934  ///
935  /// The current position is advanced by `nbytes`.
936  ///
937  /// ## Errors
938  ///
939  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
940  ///
941  /// ## Panics
942  ///
943  /// This function panics if `nbytes` is greater than 8.
944  #[inline]
945  pub const fn try_put_int(&mut self, n: i64, nbytes: usize) -> Result<(), TryPutIntegerError> {
946    self.try_put_uint(n as u64, nbytes)
947  }
948
949  /// Writes a signed n-byte integer to `self` in little-endian byte order.
950  ///
951  /// The current position is advanced by `nbytes`.
952  ///
953  /// ## Panics
954  ///
955  /// This function panics if there is not enough remaining capacity in `self`,
956  /// or if `nbytes` is greater than 8.
957  #[inline]
958  pub fn put_int_le(&mut self, n: i64, nbytes: usize) {
959    self
960      .try_put_int_le(n, nbytes)
961      .unwrap_or_else(|e| panic!("{e}"));
962  }
963
964  /// Tries to write a signed n-byte integer to `self` in little-endian byte order.
965  ///
966  /// The current position is advanced by `nbytes`.
967  ///
968  /// ## Errors
969  ///
970  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
971  ///
972  /// ## Panics
973  ///
974  /// This function panics if `nbytes` is greater than 8.
975  #[inline]
976  pub const fn try_put_int_le(&mut self, n: i64, nbytes: usize) -> Result<(), TryPutIntegerError> {
977    self.try_put_uint_le(n as u64, nbytes)
978  }
979
980  /// Writes a signed n-byte integer to `self` in native-endian byte order.
981  ///
982  /// The current position is advanced by `nbytes`.
983  ///
984  /// ## Panics
985  ///
986  /// This function panics if there is not enough remaining capacity in `self`,
987  /// or if `nbytes` is greater than 8.
988  #[inline]
989  pub fn put_int_ne(&mut self, n: i64, nbytes: usize) {
990    self
991      .try_put_int_ne(n, nbytes)
992      .unwrap_or_else(|e| panic!("{e}"));
993  }
994
995  /// Tries to write a signed n-byte integer to `self` in native-endian byte order.
996  ///
997  /// The current position is advanced by `nbytes`.
998  ///
999  /// ## Errors
1000  ///
1001  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1002  ///
1003  /// ## Panics
1004  ///
1005  /// This function panics if `nbytes` is greater than 8.
1006  #[inline]
1007  pub const fn try_put_int_ne(&mut self, n: i64, nbytes: usize) -> Result<(), TryPutIntegerError> {
1008    if cfg!(target_endian = "big") {
1009      self.try_put_int(n, nbytes)
1010    } else {
1011      self.try_put_int_le(n, nbytes)
1012    }
1013  }
1014
1015  /// Writes an IEEE754 single-precision (4 bytes) floating point number to
1016  /// `self` in big-endian byte order.
1017  ///
1018  /// The current position is advanced by 4.
1019  ///
1020  /// ## Panics
1021  ///
1022  /// This function panics if there is not enough remaining capacity in `self`.
1023  #[inline]
1024  pub fn put_f32(&mut self, n: f32) {
1025    self.put_u32(n.to_bits())
1026  }
1027
1028  /// Tries to write an IEEE754 single-precision (4 bytes) floating point number to
1029  /// `self` in big-endian byte order.
1030  ///
1031  /// The current position is advanced by 4.
1032  ///
1033  /// ## Errors
1034  ///
1035  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1036  #[inline]
1037  pub const fn try_put_f32(&mut self, n: f32) -> Result<(), TryPutError> {
1038    self.try_put_u32(n.to_bits())
1039  }
1040
1041  /// Writes an IEEE754 single-precision (4 bytes) floating point number to
1042  /// `self` in little-endian byte order.
1043  ///
1044  /// The current position is advanced by 4.
1045  ///
1046  /// ## Panics
1047  ///
1048  /// This function panics if there is not enough remaining capacity in `self`.
1049  #[inline]
1050  pub fn put_f32_le(&mut self, n: f32) {
1051    self.put_u32_le(n.to_bits())
1052  }
1053
1054  /// Tries to write an IEEE754 single-precision (4 bytes) floating point number to
1055  /// `self` in little-endian byte order.
1056  ///
1057  /// The current position is advanced by 4.
1058  ///
1059  /// ## Errors
1060  ///
1061  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1062  #[inline]
1063  pub const fn try_put_f32_le(&mut self, n: f32) -> Result<(), TryPutError> {
1064    self.try_put_u32_le(n.to_bits())
1065  }
1066
1067  /// Writes an IEEE754 single-precision (4 bytes) floating point number to
1068  /// `self` in native-endian byte order.
1069  ///
1070  /// The current position is advanced by 4.
1071  ///
1072  /// ## Panics
1073  ///
1074  /// This function panics if there is not enough remaining capacity in `self`.
1075  #[inline]
1076  pub fn put_f32_ne(&mut self, n: f32) {
1077    self.put_u32_ne(n.to_bits())
1078  }
1079
1080  /// Tries to write an IEEE754 single-precision (4 bytes) floating point number to
1081  /// `self` in native-endian byte order.
1082  ///
1083  /// The current position is advanced by 4.
1084  ///
1085  /// ## Errors
1086  ///
1087  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1088  #[inline]
1089  pub const fn try_put_f32_ne(&mut self, n: f32) -> Result<(), TryPutError> {
1090    self.try_put_u32_ne(n.to_bits())
1091  }
1092
1093  /// Writes an IEEE754 double-precision (8 bytes) floating point number to
1094  /// `self` in big-endian byte order.
1095  ///
1096  /// The current position is advanced by 8.
1097  ///
1098  /// ## Panics
1099  ///
1100  /// This function panics if there is not enough remaining capacity in `self`.
1101  #[inline]
1102  pub fn put_f64(&mut self, n: f64) {
1103    self.put_u64(n.to_bits())
1104  }
1105
1106  /// Tries to write an IEEE754 double-precision (8 bytes) floating point number to
1107  /// `self` in big-endian byte order.
1108  ///
1109  /// The current position is advanced by 8.
1110  ///
1111  /// ## Errors
1112  ///
1113  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1114  #[inline]
1115  pub const fn try_put_f64(&mut self, n: f64) -> Result<(), TryPutError> {
1116    self.try_put_u64(n.to_bits())
1117  }
1118
1119  /// Writes an IEEE754 double-precision (8 bytes) floating point number to
1120  /// `self` in little-endian byte order.
1121  ///
1122  /// The current position is advanced by 8.
1123  ///
1124  /// ## Panics
1125  ///
1126  /// This function panics if there is not enough remaining capacity in `self`.
1127  #[inline]
1128  pub fn put_f64_le(&mut self, n: f64) {
1129    self.put_u64_le(n.to_bits())
1130  }
1131
1132  /// Tries to write an IEEE754 double-precision (8 bytes) floating point number to
1133  /// `self` in little-endian byte order.
1134  ///
1135  /// The current position is advanced by 8.
1136  ///
1137  /// ## Errors
1138  ///
1139  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1140  #[inline]
1141  pub const fn try_put_f64_le(&mut self, n: f64) -> Result<(), TryPutError> {
1142    self.try_put_u64_le(n.to_bits())
1143  }
1144
1145  /// Writes an IEEE754 double-precision (8 bytes) floating point number to
1146  /// `self` in native-endian byte order.
1147  ///
1148  /// The current position is advanced by 8.
1149  ///
1150  /// ## Panics
1151  ///
1152  /// This function panics if there is not enough remaining capacity in `self`.
1153  #[inline]
1154  pub fn put_f64_ne(&mut self, n: f64) {
1155    self.put_u64_ne(n.to_bits())
1156  }
1157
1158  /// Tries to write an IEEE754 double-precision (8 bytes) floating point number to
1159  /// `self` in native-endian byte order.
1160  ///
1161  /// The current position is advanced by 8.
1162  ///
1163  /// ## Errors
1164  ///
1165  /// Returns `Err(TryPutError)` if there is not enough remaining capacity in `self`.
1166  #[inline]
1167  pub const fn try_put_f64_ne(&mut self, n: f64) -> Result<(), TryPutError> {
1168    self.try_put_u64_ne(n.to_bits())
1169  }
1170}
1171
1172#[cfg(test)]
1173mod tests {
1174  #[cfg(not(feature = "std"))]
1175  extern crate std;
1176
1177  use super::*;
1178
1179  #[test]
1180  fn test_get_u8() {
1181    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03][..]).unwrap();
1182    assert_eq!(buf.get_u8(), 0x01);
1183    assert_eq!(buf.get_u8(), 0x02);
1184    assert_eq!(buf.get_u8(), 0x03);
1185    assert_eq!(buf.remaining(), 0);
1186  }
1187
1188  #[test]
1189  fn test_try_get_u8_error() {
1190    let mut buf = Buffer::new();
1191    assert!(buf.try_get_u8().is_err());
1192  }
1193
1194  #[test]
1195  fn test_get_i8() {
1196    let mut buf = Buffer::try_from(&[0xFF, 0x7F, 0x80][..]).unwrap();
1197    assert_eq!(buf.get_i8(), -1);
1198    assert_eq!(buf.get_i8(), 127);
1199    assert_eq!(buf.get_i8(), -128);
1200  }
1201
1202  #[test]
1203  fn test_get_u16() {
1204    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03, 0x04][..]).unwrap();
1205    assert_eq!(buf.get_u16(), 0x0102);
1206    assert_eq!(buf.get_u16(), 0x0304);
1207  }
1208
1209  #[test]
1210  fn test_get_u16_le() {
1211    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03, 0x04][..]).unwrap();
1212    assert_eq!(buf.get_u16_le(), 0x0201);
1213    assert_eq!(buf.get_u16_le(), 0x0403);
1214  }
1215
1216  #[test]
1217  fn test_get_i16() {
1218    let mut buf = Buffer::try_from(&[0xFF, 0xFF, 0x7F, 0xFF][..]).unwrap();
1219    assert_eq!(buf.get_i16(), -1);
1220    assert_eq!(buf.get_i16(), 32767);
1221  }
1222
1223  #[test]
1224  fn test_get_u32() {
1225    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03, 0x04][..]).unwrap();
1226    assert_eq!(buf.get_u32(), 0x01020304);
1227  }
1228
1229  #[test]
1230  fn test_get_u32_le() {
1231    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03, 0x04][..]).unwrap();
1232    assert_eq!(buf.get_u32_le(), 0x04030201);
1233  }
1234
1235  #[test]
1236  fn test_get_i32() {
1237    let mut buf = Buffer::try_from(&[0xFF, 0xFF, 0xFF, 0xFF][..]).unwrap();
1238    assert_eq!(buf.get_i32(), -1);
1239  }
1240
1241  #[test]
1242  fn test_get_u64() {
1243    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08][..]).unwrap();
1244    assert_eq!(buf.get_u64(), 0x0102030405060708);
1245  }
1246
1247  #[test]
1248  fn test_get_u64_le() {
1249    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08][..]).unwrap();
1250    assert_eq!(buf.get_u64_le(), 0x0807060504030201);
1251  }
1252
1253  #[test]
1254  fn test_get_i64() {
1255    let mut buf = Buffer::try_from(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]).unwrap();
1256    assert_eq!(buf.get_i64(), -1);
1257  }
1258
1259  #[test]
1260  fn test_get_u128() {
1261    let mut buf = Buffer::try_from(
1262      &[
1263        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
1264        0x10,
1265      ][..],
1266    )
1267    .unwrap();
1268    assert_eq!(buf.get_u128(), 0x0102030405060708090A0B0C0D0E0F10);
1269  }
1270
1271  #[test]
1272  fn test_get_u128_le() {
1273    let mut buf = Buffer::try_from(
1274      &[
1275        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
1276        0x10,
1277      ][..],
1278    )
1279    .unwrap();
1280    assert_eq!(buf.get_u128_le(), 0x100F0E0D0C0B0A090807060504030201);
1281  }
1282
1283  #[test]
1284  fn test_get_i128() {
1285    let mut buf = Buffer::try_from(
1286      &[
1287        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1288        0xFF,
1289      ][..],
1290    )
1291    .unwrap();
1292    assert_eq!(buf.get_i128(), -1);
1293  }
1294
1295  #[test]
1296  fn test_get_f32() {
1297    let mut buf = Buffer::try_from(&[0x41, 0x48, 0x00, 0x00][..]).unwrap();
1298    assert_eq!(buf.get_f32(), 12.5);
1299  }
1300
1301  #[test]
1302  fn test_get_f32_le() {
1303    let mut buf = Buffer::try_from(&[0x00, 0x00, 0x48, 0x41][..]).unwrap();
1304    assert_eq!(buf.get_f32_le(), 12.5);
1305  }
1306
1307  #[test]
1308  fn test_get_f64() {
1309    let mut buf = Buffer::try_from(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]).unwrap();
1310    assert_eq!(buf.get_f64(), 12.5);
1311  }
1312
1313  #[test]
1314  fn test_get_f64_le() {
1315    let mut buf = Buffer::try_from(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]).unwrap();
1316    assert_eq!(buf.get_f64_le(), 12.5);
1317  }
1318
1319  #[test]
1320  fn test_get_uint() {
1321    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03][..]).unwrap();
1322    assert_eq!(buf.get_uint(3), 0x010203);
1323    assert_eq!(buf.remaining(), 0);
1324  }
1325
1326  #[test]
1327  fn test_get_uint_le() {
1328    let mut buf = Buffer::try_from(&[0x01, 0x02, 0x03][..]).unwrap();
1329    assert_eq!(buf.get_uint_le(3), 0x030201);
1330    assert_eq!(buf.remaining(), 0);
1331  }
1332
1333  #[test]
1334  fn test_get_int() {
1335    let mut buf = Buffer::try_from(&[0xFF, 0xFF, 0xFF][..]).unwrap();
1336    assert_eq!(buf.get_int(3), -1);
1337  }
1338
1339  #[test]
1340  fn test_get_int_le() {
1341    let mut buf = Buffer::try_from(&[0xFF, 0xFF, 0xFF][..]).unwrap();
1342    assert_eq!(buf.get_int_le(3), -1);
1343  }
1344
1345  // Put tests
1346  #[test]
1347  fn test_put_u8() {
1348    let mut buf = Buffer::new();
1349    buf.put_u8(0x01);
1350    buf.put_u8(0x02);
1351    assert_eq!(&buf[..], &[0x01, 0x02]);
1352  }
1353
1354  #[test]
1355  fn test_try_put_u8_error() {
1356    let mut buf = Buffer::try_from(&[0u8; 62][..]).unwrap();
1357    assert!(buf.try_put_u8(0xFF).is_err());
1358  }
1359
1360  #[test]
1361  fn test_put_i8() {
1362    let mut buf = Buffer::new();
1363    buf.put_i8(-1);
1364    buf.put_i8(127);
1365    assert_eq!(&buf[..], &[0xFF, 0x7F]);
1366  }
1367
1368  #[test]
1369  fn test_put_u16() {
1370    let mut buf = Buffer::new();
1371    buf.put_u16(0x0102);
1372    assert_eq!(&buf[..], &[0x01, 0x02]);
1373  }
1374
1375  #[test]
1376  fn test_put_u16_le() {
1377    let mut buf = Buffer::new();
1378    buf.put_u16_le(0x0102);
1379    assert_eq!(&buf[..], &[0x02, 0x01]);
1380  }
1381
1382  #[test]
1383  fn test_put_i16() {
1384    let mut buf = Buffer::new();
1385    buf.put_i16(-1);
1386    assert_eq!(&buf[..], &[0xFF, 0xFF]);
1387  }
1388
1389  #[test]
1390  fn test_put_u32() {
1391    let mut buf = Buffer::new();
1392    buf.put_u32(0x01020304);
1393    assert_eq!(&buf[..], &[0x01, 0x02, 0x03, 0x04]);
1394  }
1395
1396  #[test]
1397  fn test_put_u32_le() {
1398    let mut buf = Buffer::new();
1399    buf.put_u32_le(0x01020304);
1400    assert_eq!(&buf[..], &[0x04, 0x03, 0x02, 0x01]);
1401  }
1402
1403  #[test]
1404  fn test_put_i32() {
1405    let mut buf = Buffer::new();
1406    buf.put_i32(-1);
1407    assert_eq!(&buf[..], &[0xFF, 0xFF, 0xFF, 0xFF]);
1408  }
1409
1410  #[test]
1411  fn test_put_u64() {
1412    let mut buf = Buffer::new();
1413    buf.put_u64(0x0102030405060708);
1414    assert_eq!(&buf[..], &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
1415  }
1416
1417  #[test]
1418  fn test_put_u64_le() {
1419    let mut buf = Buffer::new();
1420    buf.put_u64_le(0x0102030405060708);
1421    assert_eq!(&buf[..], &[0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
1422  }
1423
1424  #[test]
1425  fn test_put_i64() {
1426    let mut buf = Buffer::new();
1427    buf.put_i64(-1);
1428    assert_eq!(&buf[..], &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1429  }
1430
1431  #[test]
1432  fn test_put_u128() {
1433    let mut buf = Buffer::new();
1434    buf.put_u128(0x0102030405060708090A0B0C0D0E0F10);
1435    assert_eq!(
1436      &buf[..],
1437      &[
1438        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
1439        0x10
1440      ]
1441    );
1442  }
1443
1444  #[test]
1445  fn test_put_u128_le() {
1446    let mut buf = Buffer::new();
1447    buf.put_u128_le(0x0102030405060708090A0B0C0D0E0F10);
1448    assert_eq!(
1449      &buf[..],
1450      &[
1451        0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
1452        0x01
1453      ]
1454    );
1455  }
1456
1457  #[test]
1458  fn test_put_i128() {
1459    let mut buf = Buffer::new();
1460    buf.put_i128(-1);
1461    assert_eq!(
1462      &buf[..],
1463      &[
1464        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1465        0xFF
1466      ]
1467    );
1468  }
1469
1470  #[test]
1471  fn test_put_f32() {
1472    let mut buf = Buffer::new();
1473    buf.put_f32(12.5);
1474    assert_eq!(&buf[..], &[0x41, 0x48, 0x00, 0x00]);
1475  }
1476
1477  #[test]
1478  fn test_put_f32_le() {
1479    let mut buf = Buffer::new();
1480    buf.put_f32_le(12.5);
1481    assert_eq!(&buf[..], &[0x00, 0x00, 0x48, 0x41]);
1482  }
1483
1484  #[test]
1485  fn test_put_f64() {
1486    let mut buf = Buffer::new();
1487    buf.put_f64(12.5);
1488    assert_eq!(&buf[..], &[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1489  }
1490
1491  #[test]
1492  fn test_put_f64_le() {
1493    let mut buf = Buffer::new();
1494    buf.put_f64_le(12.5);
1495    assert_eq!(&buf[..], &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
1496  }
1497
1498  #[test]
1499  fn test_put_uint() {
1500    let mut buf = Buffer::new();
1501    buf.put_uint(0x010203, 3);
1502    assert_eq!(&buf[..], &[0x01, 0x02, 0x03]);
1503  }
1504
1505  #[test]
1506  fn test_put_uint_le() {
1507    let mut buf = Buffer::new();
1508    buf.put_uint_le(0x010203, 3);
1509    assert_eq!(&buf[..], &[0x03, 0x02, 0x01]);
1510  }
1511
1512  #[test]
1513  fn test_put_int() {
1514    let mut buf = Buffer::new();
1515    buf.put_int(-1, 3);
1516    assert_eq!(&buf[..], &[0xFF, 0xFF, 0xFF]);
1517  }
1518
1519  #[test]
1520  fn test_put_int_le() {
1521    let mut buf = Buffer::new();
1522    buf.put_int_le(-1, 3);
1523    assert_eq!(&buf[..], &[0xFF, 0xFF, 0xFF]);
1524  }
1525
1526  #[test]
1527  fn test_roundtrip_u16() {
1528    let mut buf = Buffer::new();
1529    let value: u16 = 0x1234;
1530    buf.put_u16(value);
1531    buf.advance(0);
1532    assert_eq!(buf.get_u16(), value);
1533  }
1534
1535  #[test]
1536  fn test_roundtrip_u32() {
1537    let mut buf = Buffer::new();
1538    let value: u32 = 0x12345678;
1539    buf.put_u32(value);
1540    buf.advance(0);
1541    assert_eq!(buf.get_u32(), value);
1542  }
1543
1544  #[test]
1545  fn test_roundtrip_u64() {
1546    let mut buf = Buffer::new();
1547    let value: u64 = 0x123456789ABCDEF0;
1548    buf.put_u64(value);
1549    buf.advance(0);
1550    assert_eq!(buf.get_u64(), value);
1551  }
1552
1553  #[test]
1554  fn test_roundtrip_u128() {
1555    let mut buf = Buffer::new();
1556    let value: u128 = 0x123456789ABCDEF0FEDCBA9876543210;
1557    buf.put_u128(value);
1558    buf.advance(0);
1559    assert_eq!(buf.get_u128(), value);
1560  }
1561
1562  #[test]
1563  fn test_roundtrip_f32() {
1564    let mut buf = Buffer::new();
1565    let value: f32 = core::f32::consts::PI;
1566    buf.put_f32(value);
1567    buf.advance(0);
1568    assert_eq!(buf.get_f32(), value);
1569  }
1570
1571  #[test]
1572  fn test_roundtrip_f64() {
1573    let mut buf = Buffer::new();
1574    let value: f64 = core::f64::consts::PI;
1575    buf.put_f64(value);
1576    buf.advance(0);
1577    assert_eq!(buf.get_f64(), value);
1578  }
1579
1580  #[test]
1581  fn test_mixed_operations() {
1582    let mut buf = Buffer::new();
1583    buf.put_u8(0x01);
1584    buf.put_u16(0x0203);
1585    buf.put_u32(0x04050607);
1586    buf.advance(0);
1587
1588    assert_eq!(buf.get_u8(), 0x01);
1589    assert_eq!(buf.get_u16(), 0x0203);
1590    assert_eq!(buf.get_u32(), 0x04050607);
1591    assert_eq!(buf.remaining(), 0);
1592  }
1593
1594  #[test]
1595  fn test_native_endian_consistency() {
1596    let mut buf = Buffer::new();
1597    let value: u32 = 0x12345678;
1598    buf.put_u32_ne(value);
1599    buf.advance(0);
1600    assert_eq!(buf.get_u32_ne(), value);
1601  }
1602
1603  #[test]
1604  #[should_panic]
1605  fn test_get_u8_panic() {
1606    let mut buf = Buffer::new();
1607    buf.get_u8(); // Should panic - no data
1608  }
1609
1610  #[test]
1611  #[should_panic]
1612  fn test_put_u8_panic() {
1613    let mut buf = Buffer::try_from(&[0u8; 62][..]).unwrap();
1614    buf.put_u8(0xFF); // Should panic - no capacity
1615  }
1616
1617  #[test]
1618  fn test_try_methods_errors() {
1619    let mut empty_buf = Buffer::new();
1620    assert!(empty_buf.try_get_u8().is_err());
1621    assert!(empty_buf.try_get_i8().is_err());
1622    assert!(empty_buf.try_get_u16().is_err());
1623    assert!(empty_buf.try_get_i16().is_err());
1624    assert!(empty_buf.try_get_u32().is_err());
1625    assert!(empty_buf.try_get_i32().is_err());
1626    assert!(empty_buf.try_get_u64().is_err());
1627    assert!(empty_buf.try_get_i64().is_err());
1628    assert!(empty_buf.try_get_u128().is_err());
1629    assert!(empty_buf.try_get_i128().is_err());
1630    assert!(empty_buf.try_get_f32().is_err());
1631    assert!(empty_buf.try_get_f64().is_err());
1632    assert!(empty_buf.try_get_uint(3).is_err());
1633    assert!(empty_buf.try_get_int(3).is_err());
1634
1635    let mut full_buf = Buffer::try_from(&[0u8; 62][..]).unwrap();
1636    assert!(full_buf.try_put_u8(0).is_err());
1637    assert!(full_buf.try_put_i8(0).is_err());
1638  }
1639
1640  #[test]
1641  fn variable_width_panics_before_availability_checks_and_preserves_cursor() {
1642    for operation in [
1643      |buffer: &mut Buffer| buffer.get_uint(9),
1644      |buffer: &mut Buffer| buffer.get_uint_le(9),
1645      |buffer: &mut Buffer| buffer.get_uint_ne(9),
1646    ] {
1647      let mut buffer = Buffer::try_from(&b"abc"[..]).unwrap();
1648      let panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| operation(&mut buffer)));
1649      assert!(panic.is_err());
1650      assert_eq!(buffer.as_slice(), b"abc");
1651    }
1652
1653    for operation in [
1654      |buffer: &mut Buffer| buffer.get_int(9),
1655      |buffer: &mut Buffer| buffer.get_int_le(9),
1656      |buffer: &mut Buffer| buffer.get_int_ne(9),
1657    ] {
1658      let mut buffer = Buffer::try_from(&b"abc"[..]).unwrap();
1659      let panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| operation(&mut buffer)));
1660      assert!(panic.is_err());
1661      assert_eq!(buffer.as_slice(), b"abc");
1662    }
1663  }
1664}