Skip to main content

ntex_bytes/buf/
buf_mut.rs

1use std::{cmp, mem};
2
3use super::UninitSlice;
4
5/// Generates the fixed-width integer `put_*` methods of `BufMut`, with docs.
6macro_rules! put_int_impl {
7    ($($name:ident, $ty:ty, $conv:ident, $what:literal, $order:literal, $size:literal, $val:literal, $bytes:literal;)*) => {$(
8        #[doc = concat!("Writes ", $what, " to `self` in ", $order, " byte order.")]
9        ///
10        #[doc = concat!("The current position is advanced by ", $size, ".")]
11        ///
12        /// # Examples
13        ///
14        /// ```
15        /// use ntex_bytes::BufMut;
16        ///
17        /// let mut buf = vec![];
18        #[doc = concat!("buf.", stringify!($name), "(", $val, ");")]
19        #[doc = concat!("assert_eq!(buf, b\"", $bytes, "\");")]
20        /// ```
21        ///
22        /// # Panics
23        ///
24        /// This function panics if there is not enough remaining capacity in
25        /// `self`.
26        #[inline]
27        fn $name(&mut self, n: $ty) {
28            self.put_slice(&n.$conv());
29        }
30    )*};
31}
32/// A trait for values that provide sequential write access to bytes.
33///
34/// A buffer stores bytes in memory such that write operations are infallible.
35/// The underlying storage may or may not be in contiguous memory. A `BufMut`
36/// value is a cursor into the buffer. Writing to `BufMut` advances the cursor
37/// position.
38///
39/// Fixed-size buffers such as `&mut [u8]` panic when a write does not fit.
40/// Growable buffers such as `Vec<u8>`, [`BytesMut`](crate::BytesMut) and
41/// [`BytePages`](crate::BytePages) allocate more space on demand instead, so
42/// the `put_*` methods never run out of capacity for them.
43///
44/// The simplest `BufMut` is a `Vec<u8>`.
45///
46/// ```
47/// use ntex_bytes::BufMut;
48///
49/// let mut buf = vec![];
50///
51/// buf.put_slice(b"hello world");
52///
53/// assert_eq!(buf, b"hello world");
54/// ```
55pub trait BufMut {
56    /// Returns the number of bytes that can be written from the current
57    /// position until the end of the buffer is reached.
58    ///
59    /// This value is greater than or equal to the length of the slice returned
60    /// by `chunk_mut`.
61    ///
62    /// # Examples
63    ///
64    /// ```
65    /// use ntex_bytes::BufMut;
66    ///
67    /// let mut dst = [0; 10];
68    /// let mut buf = &mut dst[..];
69    ///
70    /// let original_remaining = buf.remaining_mut();
71    /// buf.put_slice(b"hello");
72    ///
73    /// assert_eq!(original_remaining - 5, buf.remaining_mut());
74    /// ```
75    ///
76    /// # Implementer notes
77    ///
78    /// Implementations of `remaining_mut` should ensure that the return value
79    /// does not change unless a call is made to `advance_mut` or any other
80    /// function that is documented to change the `BufMut`'s current position.
81    fn remaining_mut(&self) -> usize;
82
83    /// Advance the internal cursor of the `BufMut`
84    ///
85    /// The next call to `chunk_mut` will return a slice starting `cnt` bytes
86    /// further into the underlying buffer.
87    ///
88    /// # Safety
89    ///
90    /// The caller must ensure that the `cnt` bytes being advanced past have
91    /// been initialized.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use ntex_bytes::BufMut;
97    ///
98    /// let mut buf = Vec::with_capacity(16);
99    ///
100    /// unsafe {
101    ///     buf.chunk_mut()[0..2].copy_from_slice(b"he");
102    ///     buf.advance_mut(2);
103    ///
104    ///     buf.chunk_mut()[0..3].copy_from_slice(b"llo");
105    ///     buf.advance_mut(3);
106    /// }
107    ///
108    /// assert_eq!(5, buf.len());
109    /// assert_eq!(buf, b"hello");
110    /// ```
111    ///
112    /// # Panics
113    ///
114    /// This function **may** panic if `cnt > self.remaining_mut()`.
115    ///
116    /// # Implementer notes
117    ///
118    /// It is recommended for implementations of `advance_mut` to panic if
119    /// `cnt > self.remaining_mut()`. If the implementation does not panic,
120    /// the call must behave as if `cnt == self.remaining_mut()`.
121    ///
122    /// A call with `cnt == 0` should never panic and be a no-op.
123    unsafe fn advance_mut(&mut self, cnt: usize);
124
125    /// Returns true if there is space in `self` for more bytes.
126    ///
127    /// This is equivalent to `self.remaining_mut() != 0`.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use ntex_bytes::BufMut;
133    ///
134    /// let mut dst = [0; 5];
135    /// let mut buf = &mut dst[..];
136    ///
137    /// assert!(buf.has_remaining_mut());
138    ///
139    /// buf.put_slice(b"hello");
140    ///
141    /// assert!(!buf.has_remaining_mut());
142    /// ```
143    #[inline]
144    fn has_remaining_mut(&self) -> bool {
145        self.remaining_mut() > 0
146    }
147
148    /// Returns a mutable slice starting at the current `BufMut` position and of
149    /// length between 0 and `BufMut::remaining_mut()`. Note that this *can* be shorter than the
150    /// whole remainder of the buffer (this allows non-continuous implementation).
151    ///
152    /// This is a lower level function. Most operations are done with other
153    /// functions.
154    ///
155    /// The returned byte slice may represent uninitialized memory.
156    ///
157    /// # Examples
158    ///
159    /// ```
160    /// use ntex_bytes::BufMut;
161    ///
162    /// let mut buf = Vec::with_capacity(16);
163    ///
164    /// unsafe {
165    ///     buf.chunk_mut()[0..2].copy_from_slice(b"he");
166    ///
167    ///     buf.advance_mut(2);
168    ///
169    ///     buf.chunk_mut()[0..3].copy_from_slice(b"llo");
170    ///
171    ///     buf.advance_mut(3);
172    /// }
173    ///
174    /// assert_eq!(5, buf.len());
175    /// assert_eq!(buf, b"hello");
176    /// ```
177    ///
178    /// # Implementer notes
179    ///
180    /// This function should never panic. `chunk_mut` should return an empty
181    /// slice **if and only if** `remaining_mut` returns 0. In other words,
182    /// `chunk_mut` returning an empty slice implies that `remaining_mut` will
183    /// return 0 and `remaining_mut` returning 0 implies that `chunk_mut` will
184    /// return an empty slice.
185    fn chunk_mut(&mut self) -> &mut UninitSlice;
186
187    /// Transfer bytes into `self` from `src` and advance the cursor by the
188    /// number of bytes written.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use ntex_bytes::BufMut;
194    ///
195    /// let mut buf = vec![];
196    ///
197    /// buf.put_u8(b'h');
198    /// buf.put(&b"ello"[..]);
199    /// buf.put_slice(b" world");
200    ///
201    /// assert_eq!(buf, b"hello world");
202    /// ```
203    ///
204    /// # Panics
205    ///
206    /// Panics if `self` does not have enough capacity to contain `src`.
207    fn put<T: super::Buf>(&mut self, mut src: T)
208    where
209        Self: Sized,
210    {
211        while src.has_remaining() {
212            let s = src.chunk();
213            let l = s.len();
214            self.put_slice(s);
215            src.advance(l);
216        }
217    }
218
219    /// Transfer bytes into `self` from `src` and advance the cursor by the
220    /// number of bytes written.
221    ///
222    /// `self` must have enough remaining capacity to contain all of `src`.
223    ///
224    /// ```
225    /// use ntex_bytes::BufMut;
226    ///
227    /// let mut dst = [0; 6];
228    ///
229    /// {
230    ///     let mut buf = &mut dst[..];
231    ///     buf.put_slice(b"hello");
232    ///
233    ///     assert_eq!(1, buf.remaining_mut());
234    /// }
235    ///
236    /// assert_eq!(b"hello\0", &dst);
237    /// ```
238    fn put_slice(&mut self, src: &[u8]) {
239        let mut off = 0;
240
241        assert!(self.remaining_mut() >= src.len(), "buffer overflow");
242
243        while off < src.len() {
244            let dst = self.chunk_mut();
245            let cnt = cmp::min(dst.len(), src.len() - off);
246            dst[..cnt].copy_from_slice(&src[off..off + cnt]);
247            off += cnt;
248
249            // SAFETY: The `cnt` bytes in the writable chunk were initialized by the copy above.
250            unsafe {
251                self.advance_mut(cnt);
252            }
253        }
254    }
255
256    /// Writes an unsigned 8 bit integer to `self`.
257    ///
258    /// The current position is advanced by 1.
259    ///
260    /// # Examples
261    ///
262    /// ```
263    /// use ntex_bytes::BufMut;
264    ///
265    /// let mut buf = vec![];
266    /// buf.put_u8(0x01);
267    /// assert_eq!(buf, b"\x01");
268    /// ```
269    ///
270    /// # Panics
271    ///
272    /// This function panics if there is not enough remaining capacity in
273    /// `self`.
274    #[inline]
275    fn put_u8(&mut self, n: u8) {
276        let src = [n];
277        self.put_slice(&src);
278    }
279
280    /// Writes a signed 8 bit integer to `self`.
281    ///
282    /// The current position is advanced by 1.
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// use ntex_bytes::BufMut;
288    ///
289    /// let mut buf = vec![];
290    /// buf.put_i8(0x01);
291    /// assert_eq!(buf, b"\x01");
292    /// ```
293    ///
294    /// # Panics
295    ///
296    /// This function panics if there is not enough remaining capacity in
297    /// `self`.
298    fn put_i8(&mut self, n: i8) {
299        self.put_slice(&[n as u8]);
300    }
301
302    put_int_impl! {
303        put_u16, u16, to_be_bytes, "an unsigned 16 bit integer", "big-endian", 2, "0x0809", r"\x08\x09";
304        put_u16_le, u16, to_le_bytes, "an unsigned 16 bit integer", "little-endian", 2, "0x0809", r"\x09\x08";
305        put_i16, i16, to_be_bytes, "a signed 16 bit integer", "big-endian", 2, "0x0809", r"\x08\x09";
306        put_i16_le, i16, to_le_bytes, "a signed 16 bit integer", "little-endian", 2, "0x0809", r"\x09\x08";
307        put_u32, u32, to_be_bytes, "an unsigned 32 bit integer", "big-endian", 4, "0x0809A0A1", r"\x08\x09\xA0\xA1";
308        put_u32_le, u32, to_le_bytes, "an unsigned 32 bit integer", "little-endian", 4, "0x0809A0A1", r"\xA1\xA0\x09\x08";
309        put_i32, i32, to_be_bytes, "a signed 32 bit integer", "big-endian", 4, "0x0809A0A1", r"\x08\x09\xA0\xA1";
310        put_i32_le, i32, to_le_bytes, "a signed 32 bit integer", "little-endian", 4, "0x0809A0A1", r"\xA1\xA0\x09\x08";
311        put_u64, u64, to_be_bytes, "an unsigned 64 bit integer", "big-endian", 8, "0x0102030405060708", r"\x01\x02\x03\x04\x05\x06\x07\x08";
312        put_u64_le, u64, to_le_bytes, "an unsigned 64 bit integer", "little-endian", 8, "0x0102030405060708", r"\x08\x07\x06\x05\x04\x03\x02\x01";
313        put_i64, i64, to_be_bytes, "a signed 64 bit integer", "big-endian", 8, "0x0102030405060708", r"\x01\x02\x03\x04\x05\x06\x07\x08";
314        put_i64_le, i64, to_le_bytes, "a signed 64 bit integer", "little-endian", 8, "0x0102030405060708", r"\x08\x07\x06\x05\x04\x03\x02\x01";
315        put_u128, u128, to_be_bytes, "an unsigned 128 bit integer", "big-endian", 16, "0x01020304050607080910111213141516", r"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16";
316        put_u128_le, u128, to_le_bytes, "an unsigned 128 bit integer", "little-endian", 16, "0x01020304050607080910111213141516", r"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01";
317        put_i128, i128, to_be_bytes, "a signed 128 bit integer", "big-endian", 16, "0x01020304050607080910111213141516", r"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16";
318        put_i128_le, i128, to_le_bytes, "a signed 128 bit integer", "little-endian", 16, "0x01020304050607080910111213141516", r"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01";
319    }
320
321    /// Writes an unsigned n-byte integer to `self` in big-endian byte order.
322    ///
323    /// The current position is advanced by `nbytes`.
324    ///
325    /// # Examples
326    ///
327    /// ```
328    /// use ntex_bytes::BufMut;
329    ///
330    /// let mut buf = vec![];
331    /// buf.put_uint(0x010203, 3);
332    /// assert_eq!(buf, b"\x01\x02\x03");
333    /// ```
334    ///
335    /// # Panics
336    ///
337    /// This function panics if there is not enough remaining capacity in
338    /// `self`, or if `nbytes > 8`.
339    #[inline]
340    fn put_uint(&mut self, n: u64, nbytes: usize) {
341        self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
342    }
343
344    /// Writes an unsigned n-byte integer to `self` in the little-endian byte order.
345    ///
346    /// The current position is advanced by `nbytes`.
347    ///
348    /// # Examples
349    ///
350    /// ```
351    /// use ntex_bytes::BufMut;
352    ///
353    /// let mut buf = vec![];
354    /// buf.put_uint_le(0x010203, 3);
355    /// assert_eq!(buf, b"\x03\x02\x01");
356    /// ```
357    ///
358    /// # Panics
359    ///
360    /// This function panics if there is not enough remaining capacity in
361    /// `self`, or if `nbytes > 8`.
362    #[inline]
363    fn put_uint_le(&mut self, n: u64, nbytes: usize) {
364        self.put_slice(&n.to_le_bytes()[0..nbytes]);
365    }
366
367    /// Writes a signed n-byte integer to `self` in big-endian byte order.
368    ///
369    /// The current position is advanced by `nbytes`.
370    ///
371    /// # Examples
372    ///
373    /// ```
374    /// use ntex_bytes::BufMut;
375    ///
376    /// let mut buf = vec![];
377    /// buf.put_int(0x010203, 3);
378    /// assert_eq!(buf, b"\x01\x02\x03");
379    /// ```
380    ///
381    /// # Panics
382    ///
383    /// This function panics if there is not enough remaining capacity in
384    /// `self`, or if `nbytes > 8`.
385    #[inline]
386    fn put_int(&mut self, n: i64, nbytes: usize) {
387        self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
388    }
389
390    /// Writes a signed n-byte integer to `self` in little-endian byte order.
391    ///
392    /// The current position is advanced by `nbytes`.
393    ///
394    /// # Examples
395    ///
396    /// ```
397    /// use ntex_bytes::BufMut;
398    ///
399    /// let mut buf = vec![];
400    /// buf.put_int_le(0x010203, 3);
401    /// assert_eq!(buf, b"\x03\x02\x01");
402    /// ```
403    ///
404    /// # Panics
405    ///
406    /// This function panics if there is not enough remaining capacity in
407    /// `self`, or if `nbytes > 8`.
408    #[inline]
409    fn put_int_le(&mut self, n: i64, nbytes: usize) {
410        self.put_slice(&n.to_le_bytes()[0..nbytes]);
411    }
412
413    /// Writes an IEEE754 single-precision (4 bytes) floating point number to
414    /// `self` in big-endian byte order.
415    ///
416    /// The current position is advanced by 4.
417    ///
418    /// # Examples
419    ///
420    /// ```
421    /// use ntex_bytes::BufMut;
422    ///
423    /// let mut buf = vec![];
424    /// buf.put_f32(1.2f32);
425    /// assert_eq!(buf, b"\x3F\x99\x99\x9A");
426    /// ```
427    ///
428    /// # Panics
429    ///
430    /// This function panics if there is not enough remaining capacity in
431    /// `self`.
432    #[inline]
433    fn put_f32(&mut self, n: f32) {
434        self.put_u32(n.to_bits());
435    }
436
437    /// Writes an IEEE754 single-precision (4 bytes) floating point number to
438    /// `self` in little-endian byte order.
439    ///
440    /// The current position is advanced by 4.
441    ///
442    /// # Examples
443    ///
444    /// ```
445    /// use ntex_bytes::BufMut;
446    ///
447    /// let mut buf = vec![];
448    /// buf.put_f32_le(1.2f32);
449    /// assert_eq!(buf, b"\x9A\x99\x99\x3F");
450    /// ```
451    ///
452    /// # Panics
453    ///
454    /// This function panics if there is not enough remaining capacity in
455    /// `self`.
456    #[inline]
457    fn put_f32_le(&mut self, n: f32) {
458        self.put_u32_le(n.to_bits());
459    }
460
461    /// Writes an IEEE754 double-precision (8 bytes) floating point number to
462    /// `self` in big-endian byte order.
463    ///
464    /// The current position is advanced by 8.
465    ///
466    /// # Examples
467    ///
468    /// ```
469    /// use ntex_bytes::BufMut;
470    ///
471    /// let mut buf = vec![];
472    /// buf.put_f64(1.2f64);
473    /// assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
474    /// ```
475    ///
476    /// # Panics
477    ///
478    /// This function panics if there is not enough remaining capacity in
479    /// `self`.
480    #[inline]
481    fn put_f64(&mut self, n: f64) {
482        self.put_u64(n.to_bits());
483    }
484
485    /// Writes an IEEE754 double-precision (8 bytes) floating point number to
486    /// `self` in little-endian byte order.
487    ///
488    /// The current position is advanced by 8.
489    ///
490    /// # Examples
491    ///
492    /// ```
493    /// use ntex_bytes::BufMut;
494    ///
495    /// let mut buf = vec![];
496    /// buf.put_f64_le(1.2f64);
497    /// assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
498    /// ```
499    ///
500    /// # Panics
501    ///
502    /// This function panics if there is not enough remaining capacity in
503    /// `self`.
504    #[inline]
505    fn put_f64_le(&mut self, n: f64) {
506        self.put_u64_le(n.to_bits());
507    }
508}
509
510macro_rules! deref_forward_bufmut {
511    () => {
512        fn remaining_mut(&self) -> usize {
513            (**self).remaining_mut()
514        }
515
516        fn chunk_mut(&mut self) -> &mut UninitSlice {
517            (**self).chunk_mut()
518        }
519
520        unsafe fn advance_mut(&mut self, cnt: usize) {
521            (**self).advance_mut(cnt);
522        }
523
524        fn put_slice(&mut self, src: &[u8]) {
525            (**self).put_slice(src);
526        }
527
528        fn put_u8(&mut self, n: u8) {
529            (**self).put_u8(n);
530        }
531
532        fn put_i8(&mut self, n: i8) {
533            (**self).put_i8(n);
534        }
535    };
536}
537
538impl<T: BufMut + ?Sized> BufMut for &mut T {
539    deref_forward_bufmut!();
540}
541
542impl<T: BufMut + ?Sized> BufMut for Box<T> {
543    deref_forward_bufmut!();
544}
545
546impl BufMut for Vec<u8> {
547    #[inline]
548    fn remaining_mut(&self) -> usize {
549        usize::MAX - self.len()
550    }
551
552    #[inline]
553    unsafe fn advance_mut(&mut self, cnt: usize) {
554        let len = self.len();
555        let remaining = self.capacity() - len;
556        // only the spare capacity exposed by `chunk_mut` can be initialized
557        assert!(
558            cnt <= remaining,
559            "cannot advance past the capacity of the buffer, cnt:{cnt} remaining:{remaining}"
560        );
561
562        self.set_len(len + cnt);
563    }
564
565    #[inline]
566    fn chunk_mut(&mut self) -> &mut UninitSlice {
567        if self.capacity() == self.len() {
568            self.reserve(64); // Grow the vec
569        }
570
571        let cap = self.capacity();
572        let len = self.len();
573
574        let ptr = self.as_mut_ptr();
575        // SAFETY: The vector owns its allocation exclusively, and `len..cap` is its writable spare
576        // capacity.
577        unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, cap)[len..] }
578    }
579}
580
581impl BufMut for &mut [u8] {
582    #[inline]
583    fn remaining_mut(&self) -> usize {
584        self.len()
585    }
586
587    #[inline]
588    fn chunk_mut(&mut self) -> &mut UninitSlice {
589        // SAFETY: The exclusive slice covers these bytes; `UninitSlice` cannot read or
590        // de-initialize them.
591        unsafe { UninitSlice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
592    }
593
594    #[inline]
595    unsafe fn advance_mut(&mut self, cnt: usize) {
596        // Lifetime dance taken from `impl Write for &mut [u8]`.
597        let (_, b) = core::mem::take(self).split_at_mut(cnt);
598        *self = b;
599    }
600
601    #[inline]
602    fn put_slice(&mut self, src: &[u8]) {
603        self[..src.len()].copy_from_slice(src);
604        // SAFETY: The copied prefix is initialized and `src.len()` fits the destination checked by
605        // slicing above.
606        unsafe {
607            self.advance_mut(src.len());
608        }
609    }
610}
611
612// The existence of this function makes the compiler catch if the BufMut
613// trait is "object-safe" or not.
614fn _assert_trait_object(_b: &dyn BufMut) {}
615
616#[cfg(test)]
617#[allow(unused_allocation, warnings)]
618mod tests {
619    use super::*;
620    use crate::BytesMut;
621
622    /// STATEMENT: `BufMut` implementations write expected bytes and report remaining writable capacity.
623    ///
624    /// HOW:
625    /// - Write through vectors, mutable slices, boxed slices, and `BytesMut`, checking bytes, chunk access, and capacity after advancement.
626    /// - Encode integer and floating-point values in both byte orders and compare each exact byte sequence.
627    #[test]
628    #[allow(clippy::needless_borrow, clippy::too_many_lines)]
629    fn buf_mut_tests() {
630        let mut buf = vec![];
631        buf.put_u8(0x01);
632        assert_eq!(buf, b"\x01");
633
634        assert_eq!(buf.remaining_mut(), usize::MAX - 1);
635        assert_eq!((&buf).remaining_mut(), usize::MAX - 1);
636        assert_eq!(Box::new(buf).remaining_mut(), usize::MAX - 1);
637
638        let mut buf = [b'1'; 10];
639        let mut b = buf.as_mut();
640        assert_eq!(b.remaining_mut(), 10);
641        assert!(b.has_remaining_mut());
642        b.put_slice(b"123");
643        assert_eq!(&buf[..], b"1231111111");
644
645        let mut b: &mut [u8] = buf.as_mut();
646        let chunk = b.chunk_mut();
647        chunk.write_byte(0, b'9');
648        assert_eq!(&buf[..], b"9231111111");
649
650        let mut b = buf.as_mut();
651        let chunk = b.chunk_mut();
652        chunk.copy_from_slice(b"0000000000");
653        assert_eq!(&buf[..], b"0000000000");
654
655        let mut b = buf.as_mut();
656        assert_eq!(format!("{:?}", b.chunk_mut()), "UninitSlice[...]");
657
658        let b = buf.as_mut();
659        let mut bb = Box::new(b);
660        // SAFETY: The boxed slice has ten initialized bytes, so advancing by one stays within bounds.
661        unsafe { bb.advance_mut(1) };
662        let chunk = bb.chunk_mut();
663        chunk.copy_from_slice(b"111111111");
664        assert_eq!(&buf[..], b"0111111111");
665
666        let mut buf = BytesMut::new();
667        buf.put_u8(0x01);
668        assert_eq!(buf, b"\x01"[..]);
669
670        let mut buf = BytesMut::new();
671        buf.put_u8(0x01);
672        assert_eq!(buf, b"\x01"[..]);
673
674        let mut buf = vec![];
675        buf.put_i8(0x01);
676        assert_eq!(buf, b"\x01");
677
678        let mut buf = BytesMut::new();
679        buf.put_i8(0x01);
680        assert_eq!(buf, b"\x01"[..]);
681
682        let mut buf = BytesMut::new();
683        buf.put_i8(0x01);
684        assert_eq!(buf, b"\x01"[..]);
685        assert_eq!((&mut buf).remaining_mut(), crate::storage::MIN_CAPACITY - 1);
686        let chunk = (&mut buf).chunk_mut();
687        chunk.write_byte(0, b'9');
688        // SAFETY: The first spare byte was initialized by `write_byte` immediately above.
689        unsafe { (&mut buf).advance_mut(1) };
690        assert_eq!((&mut buf).remaining_mut(), crate::storage::MIN_CAPACITY - 2);
691
692        let mut buf = vec![];
693        buf.put_i16(0x0809);
694        assert_eq!(buf, b"\x08\x09");
695
696        let mut buf = vec![];
697        buf.put_i16_le(0x0809);
698        assert_eq!(buf, b"\x09\x08");
699
700        let mut buf = vec![];
701        buf.put_u32(0x0809_A0A1);
702        assert_eq!(buf, b"\x08\x09\xA0\xA1");
703
704        let mut buf = vec![];
705        buf.put_i32(0x0809_A0A1);
706        assert_eq!(buf, b"\x08\x09\xA0\xA1");
707
708        let mut buf = vec![];
709        buf.put_i32_le(0x0809_A0A1);
710        assert_eq!(buf, b"\xA1\xA0\x09\x08");
711
712        let mut buf = vec![];
713        buf.put_u64(0x0102_0304_0506_0708);
714        assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
715
716        let mut buf = vec![];
717        buf.put_u64_le(0x0102_0304_0506_0708);
718        assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
719
720        let mut buf = vec![];
721        buf.put_i64(0x0102_0304_0506_0708);
722        assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
723
724        let mut buf = vec![];
725        buf.put_i64_le(0x0102_0304_0506_0708);
726        assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
727
728        let mut buf = vec![];
729        buf.put_u128(0x0102_0304_0506_0708_0910_1112_1314_1516);
730        assert_eq!(
731            buf,
732            b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
733        );
734
735        let mut buf = vec![];
736        buf.put_u128_le(0x0102_0304_0506_0708_0910_1112_1314_1516);
737        assert_eq!(
738            buf,
739            b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01"
740        );
741
742        let mut buf = vec![];
743        buf.put_i128(0x0102_0304_0506_0708_0910_1112_1314_1516);
744        assert_eq!(
745            buf,
746            b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
747        );
748
749        let mut buf = vec![];
750        buf.put_i128_le(0x0102_0304_0506_0708_0910_1112_1314_1516);
751        assert_eq!(
752            buf,
753            b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01"
754        );
755
756        let mut buf = vec![];
757        buf.put_uint(0x01_0203, 3);
758        assert_eq!(buf, b"\x01\x02\x03");
759
760        let mut buf = vec![];
761        buf.put_uint_le(0x01_0203, 3);
762        assert_eq!(buf, b"\x03\x02\x01");
763
764        let mut buf = vec![];
765        buf.put_int(0x01_0203, 3);
766        assert_eq!(buf, b"\x01\x02\x03");
767
768        let mut buf = vec![];
769        buf.put_int_le(0x01_0203, 3);
770        assert_eq!(buf, b"\x03\x02\x01");
771
772        let mut buf = vec![];
773        buf.put_f32(1.2f32);
774        assert_eq!(buf, b"\x3F\x99\x99\x9A");
775
776        let mut buf = vec![];
777        buf.put_f32_le(1.2f32);
778        assert_eq!(buf, b"\x9A\x99\x99\x3F");
779
780        let mut buf = vec![];
781        buf.put_f64(1.2f64);
782        assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
783
784        let mut buf = vec![];
785        buf.put_f64_le(1.2f64);
786        assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
787    }
788}