Skip to main content

wincode/io/
slice.rs

1use {super::*, core::marker::PhantomData};
2
3/// Helpers for trusted slice operations.
4pub(super) mod trusted_slice {
5    use super::*;
6
7    #[inline]
8    pub(super) fn fill_buf(bytes: &[u8], n_bytes: usize) -> &[u8] {
9        unsafe { bytes.get_unchecked(..n_bytes.min(bytes.len())) }
10    }
11
12    #[inline]
13    pub(super) fn fill_exact(bytes: &[u8], n_bytes: usize) -> &[u8] {
14        unsafe { bytes.get_unchecked(..n_bytes) }
15    }
16
17    #[inline]
18    pub(super) unsafe fn consume_unchecked(bytes: &mut &[u8], amt: usize) {
19        *bytes = unsafe { bytes.get_unchecked(amt..) };
20    }
21
22    #[inline]
23    pub(super) fn consume(bytes: &mut &[u8], amt: usize) {
24        unsafe { consume_unchecked(bytes, amt) };
25    }
26
27    /// Get a slice of `len` bytes for writing, advancing the writer by `len` bytes.
28    #[inline]
29    pub(super) fn get_slice_mut<'a>(
30        buffer: &mut &'a mut [MaybeUninit<u8>],
31        len: usize,
32    ) -> &'a mut [MaybeUninit<u8>] {
33        let (dst, rest) = unsafe { mem::take(buffer).split_at_mut_unchecked(len) };
34        *buffer = rest;
35        dst
36    }
37}
38
39/// In-memory [`Reader`] that does not perform bounds checking, with zero-copy support.
40///
41/// Generally this should not be constructed directly, but rather by calling [`Reader::as_trusted_for`]
42/// on a trusted [`Reader`]. This will ensure that the safety invariants are upheld.
43///
44/// # Safety
45///
46/// - The inner buffer must have sufficient capacity for all reads. It is UB if this is not upheld.
47pub struct TrustedSliceReaderZeroCopy<'a> {
48    cursor: &'a [u8],
49}
50
51impl<'a> TrustedSliceReaderZeroCopy<'a> {
52    pub(super) const fn new(bytes: &'a [u8]) -> Self {
53        Self { cursor: bytes }
54    }
55}
56
57impl<'a> Reader<'a> for TrustedSliceReaderZeroCopy<'a> {
58    type Trusted<'b>
59        = Self
60    where
61        Self: 'b;
62
63    #[inline]
64    fn fill_buf(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
65        Ok(trusted_slice::fill_buf(self.cursor, n_bytes))
66    }
67
68    #[inline]
69    fn fill_exact(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
70        Ok(trusted_slice::fill_exact(self.cursor, n_bytes))
71    }
72
73    #[inline]
74    fn borrow_exact(&mut self, len: usize) -> ReadResult<&'a [u8]> {
75        let (src, rest) = unsafe { self.cursor.split_at_unchecked(len) };
76        self.cursor = rest;
77        Ok(src)
78    }
79
80    #[inline]
81    unsafe fn consume_unchecked(&mut self, amt: usize) {
82        trusted_slice::consume_unchecked(&mut self.cursor, amt);
83    }
84
85    #[inline]
86    fn consume(&mut self, amt: usize) -> ReadResult<()> {
87        trusted_slice::consume(&mut self.cursor, amt);
88        Ok(())
89    }
90
91    #[inline]
92    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<Self::Trusted<'_>> {
93        Ok(TrustedSliceReaderZeroCopy::new(self.borrow_exact(n_bytes)?))
94    }
95}
96
97/// In-memory [`Reader`] for mutable slices that does not perform bounds checking,
98/// with zero-copy support.
99///
100/// # Safety
101///
102/// - The inner buffer must have sufficient capacity for all reads. It is UB if this is not upheld.
103pub struct TrustedSliceReaderZeroCopyMut<'a> {
104    cursor: &'a mut [u8],
105}
106
107impl<'a> TrustedSliceReaderZeroCopyMut<'a> {
108    pub(super) const fn new(bytes: &'a mut [u8]) -> Self {
109        Self { cursor: bytes }
110    }
111}
112
113impl<'a> Reader<'a> for TrustedSliceReaderZeroCopyMut<'a> {
114    type Trusted<'b>
115        = Self
116    where
117        Self: 'b;
118
119    #[inline]
120    fn fill_buf(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
121        Ok(trusted_slice::fill_buf(self.cursor, n_bytes))
122    }
123
124    #[inline]
125    fn fill_exact(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
126        Ok(trusted_slice::fill_exact(self.cursor, n_bytes))
127    }
128
129    #[inline]
130    fn borrow_exact_mut(&mut self, len: usize) -> ReadResult<&'a mut [u8]> {
131        let (src, rest) = unsafe { mem::take(&mut self.cursor).split_at_mut_unchecked(len) };
132        self.cursor = rest;
133        Ok(src)
134    }
135
136    #[inline]
137    unsafe fn consume_unchecked(&mut self, amt: usize) {
138        self.cursor = unsafe { mem::take(&mut self.cursor).get_unchecked_mut(amt..) };
139    }
140
141    #[inline]
142    fn consume(&mut self, amt: usize) -> ReadResult<()> {
143        unsafe { Self::consume_unchecked(self, amt) };
144        Ok(())
145    }
146
147    #[inline]
148    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<Self::Trusted<'_>> {
149        Ok(TrustedSliceReaderZeroCopyMut::new(
150            self.borrow_exact_mut(n_bytes)?,
151        ))
152    }
153}
154
155/// In-memory [`Reader`] that does not perform bounds checking.
156///
157/// Generally this should not be constructed directly, but rather by calling [`Reader::as_trusted_for`]
158/// on a trusted [`Reader`]. This will ensure that the safety invariants are upheld.
159///
160/// Use [`TrustedSliceReaderZeroCopy`] for zero-copy support.
161///
162/// # Safety
163///
164/// - The inner buffer must have sufficient capacity for all reads. It is UB if this is not upheld.
165pub struct TrustedSliceReader<'a, 'b> {
166    cursor: &'b [u8],
167    _marker: PhantomData<&'a ()>,
168}
169
170impl<'a, 'b> TrustedSliceReader<'a, 'b> {
171    pub(super) const fn new(bytes: &'b [u8]) -> Self {
172        Self {
173            cursor: bytes,
174            _marker: PhantomData,
175        }
176    }
177}
178
179impl<'a, 'b> Reader<'a> for TrustedSliceReader<'a, 'b> {
180    type Trusted<'c>
181        = Self
182    where
183        Self: 'c;
184
185    #[inline]
186    fn fill_buf(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
187        Ok(trusted_slice::fill_buf(self.cursor, n_bytes))
188    }
189
190    #[inline]
191    fn fill_exact(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
192        Ok(trusted_slice::fill_exact(self.cursor, n_bytes))
193    }
194
195    #[inline]
196    unsafe fn consume_unchecked(&mut self, amt: usize) {
197        trusted_slice::consume_unchecked(&mut self.cursor, amt);
198    }
199
200    #[inline]
201    fn consume(&mut self, amt: usize) -> ReadResult<()> {
202        trusted_slice::consume(&mut self.cursor, amt);
203        Ok(())
204    }
205
206    #[inline]
207    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<Self::Trusted<'_>> {
208        let (src, rest) = unsafe { self.cursor.split_at_unchecked(n_bytes) };
209        self.cursor = rest;
210        Ok(TrustedSliceReader::new(src))
211    }
212}
213
214impl<'a> Reader<'a> for &'a [u8] {
215    type Trusted<'b>
216        = TrustedSliceReaderZeroCopy<'a>
217    where
218        Self: 'b;
219
220    #[inline]
221    fn fill_buf(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
222        // SAFETY: we clamp the end bound to the length of the slice.
223        Ok(unsafe { self.get_unchecked(..n_bytes.min(self.len())) })
224    }
225
226    #[inline]
227    fn fill_exact(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
228        let Some(src) = self.get(..n_bytes) else {
229            return Err(read_size_limit(n_bytes));
230        };
231        Ok(src)
232    }
233
234    #[inline]
235    fn borrow_exact(&mut self, len: usize) -> ReadResult<&'a [u8]> {
236        let Some((src, rest)) = self.split_at_checked(len) else {
237            return Err(read_size_limit(len));
238        };
239        *self = rest;
240        Ok(src)
241    }
242
243    #[inline]
244    unsafe fn consume_unchecked(&mut self, amt: usize) {
245        *self = unsafe { self.get_unchecked(amt..) };
246    }
247
248    #[inline]
249    fn consume(&mut self, amt: usize) -> ReadResult<()> {
250        if self.len() < amt {
251            return Err(read_size_limit(amt));
252        }
253        // SAFETY: we just checked that self.len() >= amt.
254        unsafe { self.consume_unchecked(amt) };
255        Ok(())
256    }
257
258    #[inline]
259    unsafe fn as_trusted_for(&mut self, n: usize) -> ReadResult<Self::Trusted<'_>> {
260        Ok(TrustedSliceReaderZeroCopy::new(self.borrow_exact(n)?))
261    }
262}
263
264impl<'a> Reader<'a> for &'a mut [u8] {
265    type Trusted<'b>
266        = TrustedSliceReaderZeroCopyMut<'a>
267    where
268        Self: 'b;
269
270    #[inline]
271    fn fill_buf(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
272        // SAFETY: we clamp the end bound to the length of the slice.
273        Ok(unsafe { self.get_unchecked(..n_bytes.min(self.len())) })
274    }
275
276    #[inline]
277    fn fill_exact(&mut self, n_bytes: usize) -> ReadResult<&[u8]> {
278        let Some(src) = self.get(..n_bytes) else {
279            return Err(read_size_limit(n_bytes));
280        };
281        Ok(src)
282    }
283
284    #[inline]
285    fn borrow_exact_mut(&mut self, len: usize) -> ReadResult<&'a mut [u8]> {
286        let Some((src, rest)) = mem::take(self).split_at_mut_checked(len) else {
287            return Err(read_size_limit(len));
288        };
289        *self = rest;
290        Ok(src)
291    }
292
293    #[inline]
294    unsafe fn consume_unchecked(&mut self, amt: usize) {
295        *self = unsafe { mem::take(self).get_unchecked_mut(amt..) };
296    }
297
298    #[inline]
299    fn consume(&mut self, amt: usize) -> ReadResult<()> {
300        if self.len() < amt {
301            return Err(read_size_limit(amt));
302        }
303        // SAFETY: we just checked that self.len() >= amt.
304        unsafe { self.consume_unchecked(amt) };
305        Ok(())
306    }
307
308    #[inline]
309    unsafe fn as_trusted_for(&mut self, n: usize) -> ReadResult<Self::Trusted<'_>> {
310        Ok(TrustedSliceReaderZeroCopyMut::new(
311            self.borrow_exact_mut(n)?,
312        ))
313    }
314}
315
316/// In-memory [`Writer`] that does not perform bounds checking.
317///
318/// Generally this should not be constructed directly, but rather by calling [`Writer::as_trusted_for`]
319/// on a trusted [`Writer`]. This will ensure that the safety invariants are upheld.
320///
321/// # Safety
322///
323/// - The inner buffer must have sufficient capacity for all writes. It is UB if this is not upheld.
324pub struct TrustedSliceWriter<'a> {
325    buffer: &'a mut [MaybeUninit<u8>],
326}
327
328#[cfg(test)]
329impl core::ops::Deref for TrustedSliceWriter<'_> {
330    type Target = [MaybeUninit<u8>];
331
332    fn deref(&self) -> &Self::Target {
333        self.buffer
334    }
335}
336
337impl<'a> TrustedSliceWriter<'a> {
338    #[inline(always)]
339    pub(super) const fn new(buffer: &'a mut [MaybeUninit<u8>]) -> Self {
340        Self { buffer }
341    }
342}
343
344impl<'a> Writer for TrustedSliceWriter<'a> {
345    type Trusted<'b>
346        = TrustedSliceWriter<'b>
347    where
348        Self: 'b;
349
350    #[inline]
351    fn write(&mut self, src: &[u8]) -> WriteResult<()> {
352        let dst = trusted_slice::get_slice_mut(&mut self.buffer, src.len());
353        unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) };
354        Ok(())
355    }
356
357    #[inline]
358    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<Self::Trusted<'_>> {
359        Ok(TrustedSliceWriter::new(trusted_slice::get_slice_mut(
360            &mut self.buffer,
361            n_bytes,
362        )))
363    }
364}
365
366/// Get a slice of `len` bytes for writing, advancing the writer by `len` bytes, or
367/// returning an error if the input slice does not have at least `len` bytes remaining.
368#[inline]
369fn advance_slice_mut_checked<'a, T>(
370    input: &mut &'a mut [T],
371    len: usize,
372) -> WriteResult<&'a mut [T]> {
373    let Some((dst, rest)) = mem::take(input).split_at_mut_checked(len) else {
374        return Err(write_size_limit(len));
375    };
376    *input = rest;
377    Ok(dst)
378}
379
380/// Get a slice of `len` bytes for writing returning an error if the input slice does not have
381/// at least `len` bytes remaining.
382#[inline]
383fn get_slice_mut_checked<T>(input: &mut [T], len: usize) -> WriteResult<&'_ mut [T]> {
384    let Some((dst, _)) = input.split_at_mut_checked(len) else {
385        return Err(write_size_limit(len));
386    };
387    Ok(dst)
388}
389
390impl Writer for &mut [MaybeUninit<u8>] {
391    type Trusted<'b>
392        = TrustedSliceWriter<'b>
393    where
394        Self: 'b;
395
396    #[inline]
397    fn write(&mut self, src: &[u8]) -> WriteResult<()> {
398        let dst = advance_slice_mut_checked(self, src.len())?;
399        unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) };
400        Ok(())
401    }
402
403    #[inline]
404    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<Self::Trusted<'_>> {
405        Ok(TrustedSliceWriter::new(advance_slice_mut_checked(
406            self, n_bytes,
407        )?))
408    }
409}
410
411impl Writer for [MaybeUninit<u8>] {
412    type Trusted<'b>
413        = TrustedSliceWriter<'b>
414    where
415        Self: 'b;
416
417    #[inline]
418    fn write(&mut self, src: &[u8]) -> WriteResult<()> {
419        let dst = get_slice_mut_checked(self, src.len())?;
420        unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) };
421        Ok(())
422    }
423
424    #[inline]
425    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<Self::Trusted<'_>> {
426        Ok(TrustedSliceWriter::new(get_slice_mut_checked(
427            self, n_bytes,
428        )?))
429    }
430}
431
432impl Writer for &mut [u8] {
433    type Trusted<'b>
434        = TrustedSliceWriter<'b>
435    where
436        Self: 'b;
437
438    #[inline]
439    fn write(&mut self, src: &[u8]) -> WriteResult<()> {
440        let dst = advance_slice_mut_checked(self, src.len())?;
441        // Avoid the bounds check of `copy_from_slice` by using `copy_nonoverlapping`,
442        // since we already bounds check in `get_slice_mut`.
443        unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()) };
444        Ok(())
445    }
446
447    #[inline]
448    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<Self::Trusted<'_>> {
449        let buf = advance_slice_mut_checked(self, n_bytes)?;
450        // SAFETY: we just created a slice of `n_bytes` initialized bytes, so casting to
451        // `&mut [MaybeUninit<u8>]` is safe.
452        let buf = unsafe { transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(buf) };
453        Ok(TrustedSliceWriter::new(buf))
454    }
455}
456
457impl Writer for [u8] {
458    type Trusted<'b>
459        = TrustedSliceWriter<'b>
460    where
461        Self: 'b;
462
463    #[inline]
464    fn write(&mut self, src: &[u8]) -> WriteResult<()> {
465        let dst = get_slice_mut_checked(self, src.len())?;
466        // Avoid the bounds check of `copy_from_slice` by using `copy_nonoverlapping`,
467        // since we already bounds check in `get_slice_mut`.
468        unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()) };
469        Ok(())
470    }
471
472    #[inline]
473    unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<Self::Trusted<'_>> {
474        let buf = get_slice_mut_checked(self, n_bytes)?;
475        // SAFETY: we just created a slice of `n_bytes` initialized bytes, so casting to
476        // `&mut [MaybeUninit<u8>]` is safe.
477        let buf = unsafe { transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(buf) };
478        Ok(TrustedSliceWriter::new(buf))
479    }
480}
481
482#[cfg(all(test, feature = "alloc"))]
483mod tests {
484    #![allow(clippy::arithmetic_side_effects)]
485    use {super::*, crate::proptest_config::proptest_cfg, alloc::vec::Vec, proptest::prelude::*};
486
487    #[test]
488    fn test_reader_peek() {
489        let mut reader = b"hello" as &[u8];
490        assert!(matches!(reader.peek(), Ok(&b'h')));
491    }
492
493    #[test]
494    fn test_reader_peek_empty() {
495        let mut reader = b"" as &[u8];
496        assert!(matches!(reader.peek(), Err(ReadError::ReadSizeLimit(1))));
497    }
498
499    /// Execute the given block with supported readers.
500    macro_rules! with_readers {
501        ($bytes:expr, |$reader:ident| $body:block) => {{
502            {
503                let mut $reader = $bytes.as_slice();
504                $body
505            }
506            {
507                let mut $reader = TrustedSliceReaderZeroCopy::new($bytes);
508                $body
509            }
510            {
511                let mut $reader = Cursor::new($bytes);
512                $body
513            }
514        }};
515    }
516
517    /// Execute the given block with readers that will bounds check (and thus not panic).
518    macro_rules! with_untrusted_readers {
519        ($bytes:expr, |$reader:ident| $body:block) => {{
520            {
521                let mut $reader = $bytes.as_slice();
522                $body
523            }
524        }};
525    }
526
527    /// Execute the given block with slice reference writer and trusted slice writer for the given buffer.
528    macro_rules! with_writers {
529        ($buffer:expr, |$writer:ident| $body:block) => {{
530            {
531                let $writer = &mut $buffer.spare_capacity_mut();
532                $body
533                $buffer.clear();
534            }
535            {
536                let mut $writer = TrustedSliceWriter::new($buffer.spare_capacity_mut());
537                $body
538                $buffer.clear();
539            }
540            {
541                let _capacity = $buffer.capacity();
542                $buffer.resize(_capacity, 0);
543                let $writer = &mut $buffer.as_mut_slice();
544                $body
545                $buffer.clear();
546            }
547        }};
548    }
549
550    // Execute the given block with slice writer of the given preallocated buffer.
551    macro_rules! with_known_len_writers {
552        ($buffer:expr, |$writer:ident| $body_write:block, $body_check:expr) => {{
553            let capacity = $buffer.capacity();
554            {
555                $buffer.resize(capacity, 0);
556                $buffer.fill(0);
557                let $writer = $buffer.as_mut_slice();
558                $body_write
559                $body_check;
560                $buffer.clear();
561            }
562            {
563                $buffer.fill(0);
564                $buffer.clear();
565                let $writer = $buffer.spare_capacity_mut();
566                $body_write
567                unsafe { $buffer.set_len(capacity) }
568                $body_check;
569            }
570        }};
571    }
572
573    proptest! {
574        #![proptest_config(proptest_cfg())]
575
576        #[test]
577        fn test_reader_copy_into_slice(bytes in any::<Vec<u8>>()) {
578            with_readers!(&bytes, |reader| {
579                let mut vec = Vec::with_capacity(bytes.len());
580                let half = bytes.len() / 2;
581                let dst = vec.spare_capacity_mut();
582                reader.copy_into_slice(&mut dst[..half]).unwrap();
583                unsafe { reader.as_trusted_for(bytes.len() - half) }
584                    .unwrap()
585                    .copy_into_slice(&mut dst[half..])
586                    .unwrap();
587                unsafe { vec.set_len(bytes.len()) };
588                prop_assert_eq!(&vec, &bytes);
589            });
590        }
591
592        #[test]
593        fn test_reader_fill_exact(bytes in any::<Vec<u8>>()) {
594            with_readers!(&bytes, |reader| {
595                let read = reader.fill_exact(bytes.len()).unwrap();
596                prop_assert_eq!(&read, &bytes);
597            });
598        }
599
600        #[test]
601        fn slice_reader_fill_exact_input_too_large(bytes in any::<Vec<u8>>()) {
602            with_untrusted_readers!(&bytes, |reader| {
603                prop_assert!(matches!(reader.fill_exact(bytes.len() + 1), Err(ReadError::ReadSizeLimit(x)) if x == bytes.len() + 1));
604            });
605        }
606
607        #[test]
608        fn test_reader_copy_into_slice_input_too_large(bytes in any::<Vec<u8>>()) {
609            with_untrusted_readers!(&bytes, |reader| {
610                let mut vec = Vec::with_capacity(bytes.len() + 1);
611                let dst = vec.spare_capacity_mut();
612                prop_assert!(matches!(reader.copy_into_slice(dst), Err(ReadError::ReadSizeLimit(x)) if x == bytes.len() + 1));
613            });
614        }
615
616        #[test]
617        fn test_reader_consume(bytes in any::<Vec<u8>>()) {
618            with_readers!(&bytes, |reader| {
619                reader.consume(bytes.len()).unwrap();
620                prop_assert!(matches!(reader.fill_buf(1), Ok(&[])));
621            });
622        }
623
624        #[test]
625        fn test_reader_consume_input_too_large(bytes in any::<Vec<u8>>()) {
626            let mut reader = bytes.as_slice();
627            prop_assert!(matches!(reader.consume(bytes.len() + 1), Err(ReadError::ReadSizeLimit(x)) if x == bytes.len() + 1));
628        }
629
630        #[test]
631        fn test_reader_copy_into_t(ints in proptest::collection::vec(any::<u64>(), 0..=100)) {
632            let bytes = ints.iter().flat_map(|int| int.to_le_bytes()).collect::<Vec<u8>>();
633            with_readers!(&bytes, |reader| {
634                for int in &ints {
635                    let mut val = MaybeUninit::<u64>::uninit();
636                    unsafe { reader.copy_into_t(&mut val).unwrap() };
637                    unsafe { prop_assert_eq!(val.assume_init(), *int) };
638                }
639            });
640        }
641
642        #[test]
643        fn test_reader_copy_into_slice_t(ints in proptest::collection::vec(any::<u64>(), 0..=100)) {
644            let bytes = ints.iter().flat_map(|int| int.to_le_bytes()).collect::<Vec<u8>>();
645            with_readers!(&bytes, |reader| {
646                let mut vals: Vec<u64> = Vec::with_capacity(ints.len());
647                let dst = vals.spare_capacity_mut();
648                unsafe { reader.copy_into_slice_t(dst).unwrap() };
649                unsafe { vals.set_len(ints.len()) };
650                prop_assert_eq!(&vals, &ints);
651            });
652        }
653
654        #[test]
655        fn test_writer_write(bytes in any::<Vec<u8>>()) {
656            let capacity = bytes.len();
657            let mut buffer = Vec::with_capacity(capacity);
658            with_writers!(&mut buffer, |writer| {
659                writer.write(&bytes).unwrap();
660                let written = capacity - writer.len();
661                unsafe { buffer.set_len(written) };
662                prop_assert_eq!(&buffer, &bytes);
663            });
664
665            with_known_len_writers!(&mut buffer, |writer| {
666                writer.write(&bytes).unwrap();
667            }, prop_assert_eq!(&buffer, &bytes));
668        }
669
670        #[test]
671        fn test_writer_write_input_too_large(bytes in proptest::collection::vec(any::<u8>(), 1..=100)) {
672            let mut buffer = Vec::with_capacity(bytes.len() - 1);
673            let writer = &mut buffer.spare_capacity_mut();
674            prop_assert!(matches!(writer.write(&bytes), Err(WriteError::WriteSizeLimit(x)) if x == bytes.len()));
675
676            let writer = buffer.spare_capacity_mut();
677            prop_assert!(matches!(writer.write(&bytes), Err(WriteError::WriteSizeLimit(x)) if x == bytes.len()));
678        }
679
680        #[test]
681        fn test_writer_write_t(int in any::<u64>()) {
682            let capacity = 8;
683            let mut buffer = Vec::with_capacity(capacity);
684            with_writers!(&mut buffer, |writer| {
685                unsafe { writer.write_t(&int).unwrap() };
686                let written = capacity - writer.len();
687                unsafe { buffer.set_len(written) };
688                prop_assert_eq!(&buffer, &int.to_le_bytes());
689            });
690
691            with_known_len_writers!(&mut buffer, |writer| {
692                unsafe { writer.write_t(&int).unwrap() };
693            }, prop_assert_eq!(&buffer, &int.to_le_bytes()));
694        }
695
696        #[test]
697        fn test_writer_write_slice_t(ints in proptest::collection::vec(any::<u64>(), 0..=100)) {
698            let bytes = ints.iter().flat_map(|int| int.to_le_bytes()).collect::<Vec<u8>>();
699            let capacity = bytes.len();
700            let mut buffer = Vec::with_capacity(capacity);
701            with_writers!(&mut buffer, |writer| {
702                unsafe { writer.write_slice_t(&ints).unwrap() };
703                let written = capacity - writer.len();
704                unsafe { buffer.set_len(written) };
705                prop_assert_eq!(&buffer, &bytes);
706            });
707
708            with_known_len_writers!(&mut buffer, |writer| {
709                unsafe { writer.write_slice_t(&ints).unwrap() };
710            }, prop_assert_eq!(&buffer, &bytes));
711        }
712    }
713}