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