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("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("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("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(" 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            unsafe {
250                self.advance_mut(cnt);
251            }
252        }
253    }
254
255    /// Writes an unsigned 8 bit integer to `self`.
256    ///
257    /// The current position is advanced by 1.
258    ///
259    /// # Examples
260    ///
261    /// ```
262    /// use ntex_bytes::BufMut;
263    ///
264    /// let mut buf = vec![];
265    /// buf.put_u8(0x01);
266    /// assert_eq!(buf, b"\x01");
267    /// ```
268    ///
269    /// # Panics
270    ///
271    /// This function panics if there is not enough remaining capacity in
272    /// `self`.
273    #[inline]
274    fn put_u8(&mut self, n: u8) {
275        let src = [n];
276        self.put_slice(&src);
277    }
278
279    /// Writes a signed 8 bit integer to `self`.
280    ///
281    /// The current position is advanced by 1.
282    ///
283    /// # Examples
284    ///
285    /// ```
286    /// use ntex_bytes::BufMut;
287    ///
288    /// let mut buf = vec![];
289    /// buf.put_i8(0x01);
290    /// assert_eq!(buf, b"\x01");
291    /// ```
292    ///
293    /// # Panics
294    ///
295    /// This function panics if there is not enough remaining capacity in
296    /// `self`.
297    fn put_i8(&mut self, n: i8) {
298        self.put_slice(&[n as u8]);
299    }
300
301    put_int_impl! {
302        put_u16, u16, to_be_bytes, "an unsigned 16 bit integer", "big-endian", 2, "0x0809", r"\x08\x09";
303        put_u16_le, u16, to_le_bytes, "an unsigned 16 bit integer", "little-endian", 2, "0x0809", r"\x09\x08";
304        put_i16, i16, to_be_bytes, "a signed 16 bit integer", "big-endian", 2, "0x0809", r"\x08\x09";
305        put_i16_le, i16, to_le_bytes, "a signed 16 bit integer", "little-endian", 2, "0x0809", r"\x09\x08";
306        put_u32, u32, to_be_bytes, "an unsigned 32 bit integer", "big-endian", 4, "0x0809A0A1", r"\x08\x09\xA0\xA1";
307        put_u32_le, u32, to_le_bytes, "an unsigned 32 bit integer", "little-endian", 4, "0x0809A0A1", r"\xA1\xA0\x09\x08";
308        put_i32, i32, to_be_bytes, "a signed 32 bit integer", "big-endian", 4, "0x0809A0A1", r"\x08\x09\xA0\xA1";
309        put_i32_le, i32, to_le_bytes, "a signed 32 bit integer", "little-endian", 4, "0x0809A0A1", r"\xA1\xA0\x09\x08";
310        put_u64, u64, to_be_bytes, "an unsigned 64 bit integer", "big-endian", 8, "0x0102030405060708", r"\x01\x02\x03\x04\x05\x06\x07\x08";
311        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";
312        put_i64, i64, to_be_bytes, "a signed 64 bit integer", "big-endian", 8, "0x0102030405060708", r"\x01\x02\x03\x04\x05\x06\x07\x08";
313        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";
314        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";
315        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";
316        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";
317        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";
318    }
319
320    /// Writes an unsigned n-byte integer to `self` in big-endian byte order.
321    ///
322    /// The current position is advanced by `nbytes`.
323    ///
324    /// # Examples
325    ///
326    /// ```
327    /// use ntex_bytes::BufMut;
328    ///
329    /// let mut buf = vec![];
330    /// buf.put_uint(0x010203, 3);
331    /// assert_eq!(buf, b"\x01\x02\x03");
332    /// ```
333    ///
334    /// # Panics
335    ///
336    /// This function panics if there is not enough remaining capacity in
337    /// `self`, or if `nbytes > 8`.
338    #[inline]
339    fn put_uint(&mut self, n: u64, nbytes: usize) {
340        self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
341    }
342
343    /// Writes an unsigned n-byte integer to `self` in the little-endian byte order.
344    ///
345    /// The current position is advanced by `nbytes`.
346    ///
347    /// # Examples
348    ///
349    /// ```
350    /// use ntex_bytes::BufMut;
351    ///
352    /// let mut buf = vec![];
353    /// buf.put_uint_le(0x010203, 3);
354    /// assert_eq!(buf, b"\x03\x02\x01");
355    /// ```
356    ///
357    /// # Panics
358    ///
359    /// This function panics if there is not enough remaining capacity in
360    /// `self`, or if `nbytes > 8`.
361    #[inline]
362    fn put_uint_le(&mut self, n: u64, nbytes: usize) {
363        self.put_slice(&n.to_le_bytes()[0..nbytes]);
364    }
365
366    /// Writes a signed n-byte integer to `self` in big-endian byte order.
367    ///
368    /// The current position is advanced by `nbytes`.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use ntex_bytes::BufMut;
374    ///
375    /// let mut buf = vec![];
376    /// buf.put_int(0x010203, 3);
377    /// assert_eq!(buf, b"\x01\x02\x03");
378    /// ```
379    ///
380    /// # Panics
381    ///
382    /// This function panics if there is not enough remaining capacity in
383    /// `self`, or if `nbytes > 8`.
384    #[inline]
385    fn put_int(&mut self, n: i64, nbytes: usize) {
386        self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
387    }
388
389    /// Writes a signed n-byte integer to `self` in little-endian byte order.
390    ///
391    /// The current position is advanced by `nbytes`.
392    ///
393    /// # Examples
394    ///
395    /// ```
396    /// use ntex_bytes::BufMut;
397    ///
398    /// let mut buf = vec![];
399    /// buf.put_int_le(0x010203, 3);
400    /// assert_eq!(buf, b"\x03\x02\x01");
401    /// ```
402    ///
403    /// # Panics
404    ///
405    /// This function panics if there is not enough remaining capacity in
406    /// `self`, or if `nbytes > 8`.
407    #[inline]
408    fn put_int_le(&mut self, n: i64, nbytes: usize) {
409        self.put_slice(&n.to_le_bytes()[0..nbytes]);
410    }
411
412    /// Writes an IEEE754 single-precision (4 bytes) floating point number to
413    /// `self` in big-endian byte order.
414    ///
415    /// The current position is advanced by 4.
416    ///
417    /// # Examples
418    ///
419    /// ```
420    /// use ntex_bytes::BufMut;
421    ///
422    /// let mut buf = vec![];
423    /// buf.put_f32(1.2f32);
424    /// assert_eq!(buf, b"\x3F\x99\x99\x9A");
425    /// ```
426    ///
427    /// # Panics
428    ///
429    /// This function panics if there is not enough remaining capacity in
430    /// `self`.
431    #[inline]
432    fn put_f32(&mut self, n: f32) {
433        self.put_u32(n.to_bits());
434    }
435
436    /// Writes an IEEE754 single-precision (4 bytes) floating point number to
437    /// `self` in little-endian byte order.
438    ///
439    /// The current position is advanced by 4.
440    ///
441    /// # Examples
442    ///
443    /// ```
444    /// use ntex_bytes::BufMut;
445    ///
446    /// let mut buf = vec![];
447    /// buf.put_f32_le(1.2f32);
448    /// assert_eq!(buf, b"\x9A\x99\x99\x3F");
449    /// ```
450    ///
451    /// # Panics
452    ///
453    /// This function panics if there is not enough remaining capacity in
454    /// `self`.
455    #[inline]
456    fn put_f32_le(&mut self, n: f32) {
457        self.put_u32_le(n.to_bits());
458    }
459
460    /// Writes an IEEE754 double-precision (8 bytes) floating point number to
461    /// `self` in big-endian byte order.
462    ///
463    /// The current position is advanced by 8.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// use ntex_bytes::BufMut;
469    ///
470    /// let mut buf = vec![];
471    /// buf.put_f64(1.2f64);
472    /// assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
473    /// ```
474    ///
475    /// # Panics
476    ///
477    /// This function panics if there is not enough remaining capacity in
478    /// `self`.
479    #[inline]
480    fn put_f64(&mut self, n: f64) {
481        self.put_u64(n.to_bits());
482    }
483
484    /// Writes an IEEE754 double-precision (8 bytes) floating point number to
485    /// `self` in little-endian byte order.
486    ///
487    /// The current position is advanced by 8.
488    ///
489    /// # Examples
490    ///
491    /// ```
492    /// use ntex_bytes::BufMut;
493    ///
494    /// let mut buf = vec![];
495    /// buf.put_f64_le(1.2f64);
496    /// assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
497    /// ```
498    ///
499    /// # Panics
500    ///
501    /// This function panics if there is not enough remaining capacity in
502    /// `self`.
503    #[inline]
504    fn put_f64_le(&mut self, n: f64) {
505        self.put_u64_le(n.to_bits());
506    }
507}
508
509macro_rules! deref_forward_bufmut {
510    () => {
511        fn remaining_mut(&self) -> usize {
512            (**self).remaining_mut()
513        }
514
515        fn chunk_mut(&mut self) -> &mut UninitSlice {
516            (**self).chunk_mut()
517        }
518
519        unsafe fn advance_mut(&mut self, cnt: usize) {
520            (**self).advance_mut(cnt);
521        }
522
523        fn put_slice(&mut self, src: &[u8]) {
524            (**self).put_slice(src);
525        }
526
527        fn put_u8(&mut self, n: u8) {
528            (**self).put_u8(n);
529        }
530
531        fn put_i8(&mut self, n: i8) {
532            (**self).put_i8(n);
533        }
534    };
535}
536
537impl<T: BufMut + ?Sized> BufMut for &mut T {
538    deref_forward_bufmut!();
539}
540
541impl<T: BufMut + ?Sized> BufMut for Box<T> {
542    deref_forward_bufmut!();
543}
544
545impl BufMut for Vec<u8> {
546    #[inline]
547    fn remaining_mut(&self) -> usize {
548        usize::MAX - self.len()
549    }
550
551    #[inline]
552    unsafe fn advance_mut(&mut self, cnt: usize) {
553        let len = self.len();
554        let remaining = self.capacity() - len;
555        // only the spare capacity exposed by `chunk_mut` can be initialized
556        assert!(
557            cnt <= remaining,
558            "cannot advance past the capacity of the buffer, cnt:{cnt} remaining:{remaining}"
559        );
560
561        self.set_len(len + cnt);
562    }
563
564    #[inline]
565    fn chunk_mut(&mut self) -> &mut UninitSlice {
566        if self.capacity() == self.len() {
567            self.reserve(64); // Grow the vec
568        }
569
570        let cap = self.capacity();
571        let len = self.len();
572
573        let ptr = self.as_mut_ptr();
574        unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, cap)[len..] }
575    }
576}
577
578impl BufMut for &mut [u8] {
579    #[inline]
580    fn remaining_mut(&self) -> usize {
581        self.len()
582    }
583
584    #[inline]
585    fn chunk_mut(&mut self) -> &mut UninitSlice {
586        // the bytes are initialized, `UninitSlice` never reads or de-initializes them
587        unsafe { UninitSlice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
588    }
589
590    #[inline]
591    unsafe fn advance_mut(&mut self, cnt: usize) {
592        // Lifetime dance taken from `impl Write for &mut [u8]`.
593        let (_, b) = core::mem::take(self).split_at_mut(cnt);
594        *self = b;
595    }
596
597    #[inline]
598    fn put_slice(&mut self, src: &[u8]) {
599        self[..src.len()].copy_from_slice(src);
600        unsafe {
601            self.advance_mut(src.len());
602        }
603    }
604}
605
606// The existence of this function makes the compiler catch if the BufMut
607// trait is "object-safe" or not.
608fn _assert_trait_object(_b: &dyn BufMut) {}
609
610#[cfg(test)]
611#[allow(unused_allocation, warnings)]
612mod tests {
613    use super::*;
614    use crate::BytesMut;
615
616    #[test]
617    #[allow(clippy::needless_borrow, clippy::too_many_lines)]
618    fn buf_mut_tests() {
619        let mut buf = vec![];
620        buf.put_u8(0x01);
621        assert_eq!(buf, b"\x01");
622
623        assert_eq!(buf.remaining_mut(), usize::MAX - 1);
624        assert_eq!((&buf).remaining_mut(), usize::MAX - 1);
625        assert_eq!(Box::new(buf).remaining_mut(), usize::MAX - 1);
626
627        let mut buf = [b'1'; 10];
628        let mut b = buf.as_mut();
629        assert_eq!(b.remaining_mut(), 10);
630        assert!(b.has_remaining_mut());
631        b.put_slice(b"123");
632        assert_eq!(&buf[..], b"1231111111");
633
634        let mut b: &mut [u8] = buf.as_mut();
635        let chunk = b.chunk_mut();
636        chunk.write_byte(0, b'9');
637        assert_eq!(&buf[..], b"9231111111");
638
639        let mut b = buf.as_mut();
640        let chunk = b.chunk_mut();
641        chunk.copy_from_slice(b"0000000000");
642        assert_eq!(&buf[..], b"0000000000");
643
644        let mut b = buf.as_mut();
645        assert_eq!(format!("{:?}", b.chunk_mut()), "UninitSlice[...]");
646
647        let b = buf.as_mut();
648        let mut bb = Box::new(b);
649        unsafe { bb.advance_mut(1) };
650        let chunk = bb.chunk_mut();
651        chunk.copy_from_slice(b"111111111");
652        assert_eq!(&buf[..], b"0111111111");
653
654        let mut buf = BytesMut::new();
655        buf.put_u8(0x01);
656        assert_eq!(buf, b"\x01"[..]);
657
658        let mut buf = BytesMut::new();
659        buf.put_u8(0x01);
660        assert_eq!(buf, b"\x01"[..]);
661
662        let mut buf = vec![];
663        buf.put_i8(0x01);
664        assert_eq!(buf, b"\x01");
665
666        let mut buf = BytesMut::new();
667        buf.put_i8(0x01);
668        assert_eq!(buf, b"\x01"[..]);
669
670        let mut buf = BytesMut::new();
671        buf.put_i8(0x01);
672        assert_eq!(buf, b"\x01"[..]);
673        assert_eq!((&mut buf).remaining_mut(), 111);
674        let chunk = (&mut buf).chunk_mut();
675        chunk.write_byte(0, b'9');
676        unsafe { (&mut buf).advance_mut(1) };
677        assert_eq!((&mut buf).remaining_mut(), 110);
678
679        let mut buf = vec![];
680        buf.put_i16(0x0809);
681        assert_eq!(buf, b"\x08\x09");
682
683        let mut buf = vec![];
684        buf.put_i16_le(0x0809);
685        assert_eq!(buf, b"\x09\x08");
686
687        let mut buf = vec![];
688        buf.put_u32(0x0809_A0A1);
689        assert_eq!(buf, b"\x08\x09\xA0\xA1");
690
691        let mut buf = vec![];
692        buf.put_i32(0x0809_A0A1);
693        assert_eq!(buf, b"\x08\x09\xA0\xA1");
694
695        let mut buf = vec![];
696        buf.put_i32_le(0x0809_A0A1);
697        assert_eq!(buf, b"\xA1\xA0\x09\x08");
698
699        let mut buf = vec![];
700        buf.put_u64(0x0102_0304_0506_0708);
701        assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
702
703        let mut buf = vec![];
704        buf.put_u64_le(0x0102_0304_0506_0708);
705        assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
706
707        let mut buf = vec![];
708        buf.put_i64(0x0102_0304_0506_0708);
709        assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
710
711        let mut buf = vec![];
712        buf.put_i64_le(0x0102_0304_0506_0708);
713        assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
714
715        let mut buf = vec![];
716        buf.put_u128(0x0102_0304_0506_0708_0910_1112_1314_1516);
717        assert_eq!(
718            buf,
719            b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
720        );
721
722        let mut buf = vec![];
723        buf.put_u128_le(0x0102_0304_0506_0708_0910_1112_1314_1516);
724        assert_eq!(
725            buf,
726            b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01"
727        );
728
729        let mut buf = vec![];
730        buf.put_i128(0x0102_0304_0506_0708_0910_1112_1314_1516);
731        assert_eq!(
732            buf,
733            b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
734        );
735
736        let mut buf = vec![];
737        buf.put_i128_le(0x0102_0304_0506_0708_0910_1112_1314_1516);
738        assert_eq!(
739            buf,
740            b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01"
741        );
742
743        let mut buf = vec![];
744        buf.put_uint(0x01_0203, 3);
745        assert_eq!(buf, b"\x01\x02\x03");
746
747        let mut buf = vec![];
748        buf.put_uint_le(0x01_0203, 3);
749        assert_eq!(buf, b"\x03\x02\x01");
750
751        let mut buf = vec![];
752        buf.put_int(0x01_0203, 3);
753        assert_eq!(buf, b"\x01\x02\x03");
754
755        let mut buf = vec![];
756        buf.put_int_le(0x01_0203, 3);
757        assert_eq!(buf, b"\x03\x02\x01");
758
759        let mut buf = vec![];
760        buf.put_f32(1.2f32);
761        assert_eq!(buf, b"\x3F\x99\x99\x9A");
762
763        let mut buf = vec![];
764        buf.put_f32_le(1.2f32);
765        assert_eq!(buf, b"\x9A\x99\x99\x3F");
766
767        let mut buf = vec![];
768        buf.put_f64(1.2f64);
769        assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
770
771        let mut buf = vec![];
772        buf.put_f64_le(1.2f64);
773        assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
774    }
775}