wincode/io/mod.rs
1//! [`Reader`] and [`Writer`] implementations.
2use {
3 crate::error::read_length_encoding_overflow,
4 core::{
5 mem::{self, MaybeUninit, transmute},
6 ptr,
7 slice::{from_raw_parts, from_raw_parts_mut},
8 },
9 thiserror::Error,
10};
11
12#[derive(Debug, Clone, Copy)]
13#[repr(u8)]
14pub enum BorrowKind {
15 /// Borrowed from the call site, not extending past it.
16 CallSite,
17 /// Borrowed from the backing store, extending past the call site.
18 Backing,
19 /// Mutably borrowed from the backing store, extending past the call site.
20 BackingMut,
21}
22
23impl BorrowKind {
24 #[inline]
25 pub const fn mask(self) -> u8 {
26 1u8 << (self as u8)
27 }
28}
29
30impl core::fmt::Display for BorrowKind {
31 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32 match self {
33 BorrowKind::CallSite => f.write_str("call-site scoped borrows"),
34 BorrowKind::Backing => f.write_str("borrows extending past the call site"),
35 BorrowKind::BackingMut => f.write_str("mutable borrows extending past the call site"),
36 }
37 }
38}
39
40#[derive(Error, Debug)]
41pub enum ReadError {
42 #[error("Attempting to read {0} bytes")]
43 ReadSizeLimit(usize),
44 #[error("Unsupported borrow operation: reader does not support {0}")]
45 UnsupportedBorrow(BorrowKind),
46 #[cfg(feature = "std")]
47 #[error(transparent)]
48 Io(#[from] std::io::Error),
49}
50
51pub type ReadResult<T> = core::result::Result<T, ReadError>;
52
53#[cold]
54pub const fn read_size_limit(len: usize) -> ReadError {
55 ReadError::ReadSizeLimit(len)
56}
57
58#[inline(always)]
59pub(super) const fn transpose<const N: usize, T>(
60 src: &mut MaybeUninit<[T; N]>,
61) -> &mut [MaybeUninit<T>; N] {
62 unsafe { transmute(src) }
63}
64
65/// Trait for structured reading of bytes from a source into potentially uninitialized memory.
66///
67/// # Borrowing semantics
68/// - Only implement [`Reader::take_borrowed`] or [`Reader::take_borrowed_mut`] for sources
69/// where stable borrows into the backing storage are possible.
70/// - Callers should prefer [`Reader::copy_into_slice`] or `take_*` methods to remain
71/// compatible with readers that don't support borrowing, if possible.
72/// - Returns [`ReadError::UnsupportedBorrow`] for readers that do not support borrowing.
73///
74/// # Performance
75///
76/// The default [`Reader::copy_into_uninit_slice`] implementation initializes
77/// the destination before delegating to [`Reader::copy_into_slice`].
78/// Implementors that can safely write directly into `MaybeUninit<u8>` storage
79/// should override it to avoid this initialization. Such overrides must still
80/// initialize every destination byte before returning `Ok(())`.
81///
82/// # Safety
83///
84/// Implementors must ensure that:
85///
86/// - If `copy_into_uninit_slice` returns `Ok(())`, every element of the
87/// destination has been initialized.
88/// - All safe methods uphold Rust's validity, aliasing, and lifetime rules for
89/// every safe input. Callers are not responsible for proving that destination
90/// buffers do not overlap internal storage.
91/// - References returned by borrowing methods remain valid for their documented
92/// lifetimes.
93/// - Any unchecked reader returned by `as_trusted_for` obeys that method's
94/// documented bounds contract.
95pub unsafe trait Reader<'a> {
96 /// Borrow capabilities of this reader.
97 ///
98 /// A bitmask of [`BorrowKind`] values indicating which kinds of borrows are supported.
99 ///
100 /// Users of [`Reader`] can call [`Reader::supports_borrow`] to check if a borrow kind
101 /// is supported.
102 const BORROW_KINDS: u8 = 0;
103
104 /// Checks if this reader supports the given borrow kind.
105 ///
106 /// # Examples
107 /// ```
108 /// # use wincode::io::{Reader, BorrowKind, Cursor};
109 /// #
110 /// let reader = [1, 2, 3, 4, 5];
111 /// assert!(reader.as_slice().supports_borrow(BorrowKind::Backing));
112 ///
113 /// let mut reader = [1, 2, 3, 4, 5];
114 /// assert!(reader.as_mut_slice().supports_borrow(BorrowKind::BackingMut));
115 ///
116 /// let reader = Cursor::new([1, 2, 3, 4, 5]);
117 /// assert!(reader.supports_borrow(BorrowKind::CallSite));
118 /// assert!(!reader.supports_borrow(BorrowKind::Backing));
119 /// ```
120 #[inline]
121 fn supports_borrow(&self, kind: BorrowKind) -> bool {
122 Self::BORROW_KINDS & kind.mask() != 0
123 }
124
125 /// Return exactly `N` bytes as `[u8; N]` and advance by `N`.
126 ///
127 /// Errors if fewer than `N` bytes are available.
128 #[inline(always)]
129 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
130 let mut ar = MaybeUninit::<[u8; N]>::uninit();
131
132 self.copy_into_uninit_slice(transpose(&mut ar))?;
133
134 // SAFETY: `copy_into_uninit_slice` returned successfully, which guarantees
135 // every element of `ar` was initialized.
136 Ok(unsafe { ar.assume_init() })
137 }
138
139 /// Return the next byte and advance by `1`.
140 ///
141 /// Errors if the reader is exhausted.
142 #[inline(always)]
143 fn take_byte(&mut self) -> ReadResult<u8> {
144 Ok(self.take_array::<1>()?[0])
145 }
146
147 /// Return a borrowed slice of exactly `len` bytes and advance
148 /// the reader by `len`.
149 ///
150 /// The returned slice is tied to the reader's backing lifetime `'a`.
151 /// This means the slice may outlive the borrow of the call, and is
152 /// valid after the reader is dropped or reborrowed.
153 ///
154 /// This stronger guarantee is typically only possible for readers backed
155 /// by stable storage (for example `&'a [u8]` or memory-mapped buffers).
156 ///
157 /// Prefer [`Reader::take_scoped`] unless you specifically require a slice
158 /// that lives for `'a`. Prefer [`Reader::copy_into_slice`] if you ultimately
159 /// intend to copy the slice.
160 ///
161 /// Errors if the reader cannot provide `len` bytes or does not support
162 /// borrowing into stable storage that outlives the reader.
163 #[expect(unused_variables)]
164 fn take_borrowed(&mut self, len: usize) -> ReadResult<&'a [u8]> {
165 Err(ReadError::UnsupportedBorrow(BorrowKind::Backing))
166 }
167
168 /// Return a mutably borrowed slice of exactly `len` bytes and advance
169 /// the reader by `len`.
170 ///
171 /// The returned slice is tied to the reader's backing lifetime `'a`.
172 /// This means the slice may outlive the borrow of the call, and is
173 /// valid after the reader is dropped or reborrowed.
174 ///
175 /// This stronger guarantee is typically only possible for readers backed
176 /// by stable storage (for example `&'a mut [u8]` or memory-mapped buffers).
177 ///
178 /// Errors if the reader cannot provide `len` bytes or does not support
179 /// mutable borrowing into stable, mutable storage that outlives the reader.
180 #[expect(unused_variables)]
181 fn take_borrowed_mut(&mut self, len: usize) -> ReadResult<&'a mut [u8]> {
182 Err(ReadError::UnsupportedBorrow(BorrowKind::BackingMut))
183 }
184
185 /// Return a call-site scoped slice of exactly `len` bytes and advance by `len`.
186 ///
187 /// The returned slice is tied to the borrow of `self`, meaning it is only
188 /// valid while the current borrow of the reader is alive. Implementations
189 /// are free to return slices backed by internal buffers or transient windows
190 /// into the underlying source.
191 ///
192 /// Prefer [`Reader::copy_into_slice`] if you ultimately intend to copy the slice.
193 ///
194 /// Errors for readers that don't support call-site scoped borrowing.
195 #[expect(unused_variables)]
196 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
197 Err(ReadError::UnsupportedBorrow(BorrowKind::CallSite))
198 }
199
200 /// Advance the parent by `n_bytes` and return a [`Reader`] that can elide bounds checks within
201 /// that `n_bytes` window.
202 ///
203 /// Implementors must:
204 /// - Arrange that the returned `Trusted` reader's methods operate within
205 /// that `n_bytes` window (it may buffer or prefetch arbitrarily).
206 /// - Ensure that the returned reader either continues checking its bounds
207 /// normally or is backed by at least `n_bytes`; otherwise, return an error.
208 ///
209 /// Note:
210 /// - `as_trusted_for` is intended for callers that know they will operate
211 /// within a fixed-size window and want to avoid intermediate bounds checks.
212 ///
213 /// # Safety
214 ///
215 /// The caller must ensure that, through the returned reader, they do not
216 /// cause more than `n_bytes` bytes to be logically read or consumed
217 /// without performing additional bounds checks.
218 ///
219 /// Concretely:
220 /// - The total number of bytes accessed/consumed via the `Trusted` reader
221 /// (`copy_into_*`, `take_*`, etc.) must be **<= `n_bytes`**.
222 ///
223 /// Violating this is undefined behavior, because `Trusted` readers are
224 /// permitted to elide bounds checks within the `n_bytes` window; reading past the
225 /// `n_bytes` window may read past the end of the underlying buffer.
226 #[expect(unused_variables)]
227 #[inline(always)]
228 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<impl Reader<'a>> {
229 Ok(self)
230 }
231
232 /// Construct a trusted window for a sequence of length `len` and serialized
233 /// element size `size`.
234 ///
235 /// Always prefer this over manual unchecked arithmetic.
236 ///
237 /// # Safety
238 ///
239 /// The caller must ensure that operations through the returned reader do not
240 /// logically read or consume more than `len * size` bytes without performing
241 /// additional bounds checks.
242 ///
243 /// See [`Reader::as_trusted_for`].
244 #[inline]
245 unsafe fn as_trusted_for_seq(
246 &mut self,
247 len: usize,
248 size: usize,
249 ) -> Result<impl Reader<'a>, crate::error::ReadError> {
250 let Some(window) = len.checked_mul(size) else {
251 return Err(read_length_encoding_overflow("usize::MAX"));
252 };
253 Ok(unsafe { self.as_trusted_for(window) }?)
254 }
255
256 /// Get a mutable reference to the [`Reader`].
257 ///
258 /// Useful in situations where one only has an `impl Reader<'de>` that
259 /// needs to be passed to mulitple functions requiring `impl Reader<'de>`.
260 ///
261 /// Always prefer this over `&mut reader` to avoid recursive borrows.
262 ///
263 /// ```
264 /// # use wincode::{io::Reader, ReadResult, config::Config, SchemaRead};
265 /// # use core::mem::MaybeUninit;
266 /// struct FooBar {
267 /// foo: u32,
268 /// bar: u32,
269 /// }
270 ///
271 /// unsafe impl<'de, C: Config> SchemaRead<'de, C> for FooBar {
272 /// type Dst = Self;
273 ///
274 /// fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self>) -> ReadResult<()> {
275 /// // `reader.by_ref()`; Good ✅
276 /// let foo = <u32 as SchemaRead<'de, C>>::get(reader.by_ref())?;
277 /// let bar = <u32 as SchemaRead<'de, C>>::get(reader)?;
278 /// dst.write(FooBar { foo, bar });
279 /// Ok(())
280 /// }
281 /// }
282 /// ```
283 #[inline(always)]
284 fn by_ref(&mut self) -> impl Reader<'a> {
285 self
286 }
287
288 /// Attempts to copy and consume exactly `dst.len()` bytes.
289 ///
290 /// On success, exactly `dst.len()` bytes are consumed and every element of
291 /// `dst` contains the corresponding byte. On error, some bytes may have been
292 /// consumed; `dst` remains initialized, but its contents are unspecified.
293 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()>;
294
295 /// Attempts to copy and consume exactly `dst.len()` bytes into potentially
296 /// uninitialized storage.
297 ///
298 /// On success, exactly `dst.len()` bytes are consumed and every element of
299 /// `dst` is initialized. On error, some bytes may have been consumed; the
300 /// initialization state and contents of `dst` are unspecified.
301 ///
302 /// The default implementation initializes the destination before calling
303 /// [`Reader::copy_into_slice`]. Implementations may override it to write directly
304 /// into uninitialized storage.
305 ///
306 /// # Implementor requirements
307 ///
308 /// Before returning `Ok(())`, implementations must initialize every element of
309 /// `dst`. This postcondition is required for soundness. Methods such as `take_array`
310 /// treat the entire destination as initialized after `Ok(())`.
311 /// Returning `Ok(())` while any destination byte remains uninitialized may cause undefined behavior.
312 #[inline(always)]
313 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
314 dst.fill(MaybeUninit::new(0));
315 // SAFETY: Every element is initialized with a valid `u8`, and
316 // `MaybeUninit<u8>` has the same layout as `u8`.
317 let dst = unsafe { transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(dst) };
318 self.copy_into_slice(dst)
319 }
320
321 /// Attempts to copy and consume exactly `size_of::<T>()` bytes from the
322 /// [`Reader`] into `dst`.
323 ///
324 /// # Safety
325 ///
326 /// - The caller must ensure that, if this method returns `Ok(())`, the bytes
327 /// copied into `dst` form a valid representation of `T` before `dst` is
328 /// treated as initialized. This includes all validity and provenance
329 /// requirements of `T`.
330 /// - The caller must ensure that the memory occupied by `dst` does not overlap
331 /// the source bytes accessed by the reader.
332 #[inline]
333 unsafe fn copy_into_t<T>(&mut self, dst: &mut MaybeUninit<T>) -> ReadResult<()> {
334 // SAFETY: `dst` provides `size_of::<T>()` contiguous writable bytes, and
335 // `MaybeUninit<u8>` has alignment 1.
336 let dst = unsafe {
337 from_raw_parts_mut(dst.as_mut_ptr().cast::<MaybeUninit<u8>>(), size_of::<T>())
338 };
339 self.copy_into_uninit_slice(dst)
340 }
341
342 /// Attempts to copy and consume exactly `dst.len() * size_of::<T>()` bytes
343 /// from the [`Reader`] into `dst`.
344 ///
345 /// # Safety
346 ///
347 /// - The caller must ensure that, if this method returns `Ok(())`, each
348 /// consecutive `size_of::<T>()` byte region copied into `dst` forms a valid
349 /// representation of `T` before the elements are treated as initialized.
350 /// This includes all validity and provenance requirements of `T`.
351 /// - The caller must ensure that the memory occupied by `dst` does not overlap
352 /// the source bytes accessed by the reader.
353 #[inline]
354 unsafe fn copy_into_slice_t<T>(&mut self, dst: &mut [MaybeUninit<T>]) -> ReadResult<()> {
355 let len = size_of_val(dst);
356 // SAFETY: `dst` provides `size_of_val(dst)` contiguous writable bytes,
357 // and `MaybeUninit<u8>` has alignment 1.
358 let dst = unsafe { from_raw_parts_mut(dst.as_mut_ptr().cast::<MaybeUninit<u8>>(), len) };
359 self.copy_into_uninit_slice(dst)
360 }
361}
362
363unsafe impl<'a, R: Reader<'a> + ?Sized> Reader<'a> for &mut R {
364 const BORROW_KINDS: u8 = R::BORROW_KINDS;
365
366 #[inline(always)]
367 fn supports_borrow(&self, kind: BorrowKind) -> bool {
368 (**self).supports_borrow(kind)
369 }
370
371 #[inline(always)]
372 fn by_ref(&mut self) -> impl Reader<'a> {
373 &mut **self
374 }
375
376 #[inline(always)]
377 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
378 (*self).take_array()
379 }
380
381 #[inline(always)]
382 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
383 (*self).take_scoped(len)
384 }
385
386 #[inline(always)]
387 fn take_borrowed(&mut self, len: usize) -> ReadResult<&'a [u8]> {
388 (*self).take_borrowed(len)
389 }
390
391 #[inline(always)]
392 fn take_borrowed_mut(&mut self, len: usize) -> ReadResult<&'a mut [u8]> {
393 (*self).take_borrowed_mut(len)
394 }
395
396 #[inline(always)]
397 fn take_byte(&mut self) -> ReadResult<u8> {
398 (*self).take_byte()
399 }
400
401 #[inline(always)]
402 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<impl Reader<'a>> {
403 unsafe { (*self).as_trusted_for(n_bytes) }
404 }
405
406 #[inline(always)]
407 unsafe fn as_trusted_for_seq(
408 &mut self,
409 len: usize,
410 size: usize,
411 ) -> Result<impl Reader<'a>, crate::error::ReadError> {
412 unsafe { (*self).as_trusted_for_seq(len, size) }
413 }
414
415 #[inline(always)]
416 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
417 (*self).copy_into_slice(dst)
418 }
419
420 #[inline(always)]
421 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
422 (*self).copy_into_uninit_slice(dst)
423 }
424
425 #[inline(always)]
426 unsafe fn copy_into_t<T>(&mut self, dst: &mut MaybeUninit<T>) -> ReadResult<()> {
427 unsafe { (*self).copy_into_t(dst) }
428 }
429
430 #[inline(always)]
431 unsafe fn copy_into_slice_t<T>(&mut self, dst: &mut [MaybeUninit<T>]) -> ReadResult<()> {
432 unsafe { (*self).copy_into_slice_t(dst) }
433 }
434}
435
436#[derive(Error, Debug)]
437pub enum WriteError {
438 #[error("Attempting to write {0} bytes")]
439 WriteSizeLimit(usize),
440 #[cfg(feature = "std")]
441 #[error(transparent)]
442 Io(#[from] std::io::Error),
443}
444
445#[cold]
446const fn write_size_limit(len: usize) -> WriteError {
447 WriteError::WriteSizeLimit(len)
448}
449
450pub type WriteResult<T> = core::result::Result<T, WriteError>;
451
452/// Trait for structured writing of bytes into a source of potentially uninitialized memory.
453pub trait Writer {
454 /// Get a mutable reference to the [`Writer`].
455 ///
456 /// Useful in situations where one has an `impl Writer` that
457 /// needs to be passed to mulitple functions requiring `impl Writer`.
458 ///
459 /// Always prefer this over `&mut writer` to avoid recursive borrows.
460 ///
461 /// ```
462 /// # use wincode::{io::Writer, WriteResult, config::Config, SchemaWrite};
463 /// # use core::mem::MaybeUninit;
464 /// struct FooBar {
465 /// foo: u32,
466 /// bar: u32,
467 /// }
468 ///
469 /// unsafe impl<C: Config> SchemaWrite<C> for FooBar {
470 /// type Src = Self;
471 /// #
472 /// # fn size_of(src: &Self::Src) -> WriteResult<usize> {
473 /// # let foo = <u32 as SchemaWrite<C>>::size_of(&src.foo)?;
474 /// # let bar = <u32 as SchemaWrite<C>>::size_of(&src.bar)?;
475 /// # Ok(foo + bar)
476 /// # }
477 ///
478 /// fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
479 /// // `writer.by_ref()`; Good ✅
480 /// let foo = <u32 as SchemaWrite<C>>::write(writer.by_ref(), &src.foo)?;
481 /// let bar = <u32 as SchemaWrite<C>>::write(writer, &src.bar)?;
482 /// Ok(())
483 /// }
484 /// }
485 /// ```
486 #[inline(always)]
487 fn by_ref(&mut self) -> impl Writer {
488 self
489 }
490
491 /// Finalize the writer by performing any required cleanup or flushing.
492 ///
493 /// # Regarding trusted writers
494 ///
495 /// Trusted writers are not guaranteed to live as long as the parent [`Writer`] that
496 /// created them, and are typically short-lived. wincode will call `finish` after
497 /// trusted writers have completed their work, so they may rely on `finish` perform
498 /// local cleanup when needed. Importantly, trusted writers must not perform actions
499 /// that would invalidate the parent [`Writer`].
500 ///
501 /// For example, a file writer may buffer internally and delegate to trusted
502 /// sub-writers with their own buffers. These trusted writers should not close
503 /// the underlying file descriptor or other parent-owned resources, as that would
504 /// invalidate the parent writer.
505 fn finish(&mut self) -> WriteResult<()> {
506 Ok(())
507 }
508
509 /// Write exactly `src.len()` bytes from the given `src` into the writer.
510 fn write(&mut self, src: &[u8]) -> WriteResult<()>;
511
512 /// Advance the parent by `n_bytes` and return a [`Writer`] that can elide bounds checks within
513 /// that `n_bytes` window.
514 ///
515 /// Implementors must:
516 /// - Ensure that either at least `n_bytes` bytes are available backing the
517 /// returned writer, or return an error.
518 /// - Arrange that the returned `Trusted` writer's methods operate within
519 /// that `n_bytes` window (it may buffer or prefetch arbitrarily).
520 ///
521 /// Note:
522 /// - `as_trusted_for` is intended for callers that know they will operate
523 /// within an exact-size window and want to avoid intermediate bounds checks.
524 ///
525 /// # Safety
526 ///
527 /// The caller must treat the returned writer as having exclusive access to
528 /// exactly `n_bytes` bytes of **uninitialized** output space in the parent,
529 /// and must:
530 ///
531 /// - Ensure that no write performed through the `Trusted` writer can
532 /// address memory outside of that `n_bytes` window.
533 /// - In case the caller does not return an error, ensure that, before the
534 /// `Trusted` writer is finished or the parent writer is used again,
535 /// **every byte** in that `n_bytes` window has been initialized at least
536 /// once via the `Trusted` writer.
537 /// - In case the caller does not return an error, call [`Writer::finish`]
538 /// on the `Trusted` writer when writing is complete and before the parent
539 /// writer is used again.
540 ///
541 /// Concretely:
542 /// - All writes performed via the `Trusted` writer (`write`, `write_t`,
543 /// `write_slice_t`, etc.) must stay within the `[0, n_bytes)` region of
544 /// the reserved space.
545 /// - It is permitted to overwrite the same bytes multiple times, but if the
546 /// caller returns no error, the union of all bytes written must cover the
547 /// entire `[0, n_bytes)` window.
548 ///
549 /// Violating this is undefined behavior, because:
550 /// - `Trusted` writers are permitted to elide bounds checks within the
551 /// `n_bytes` window; writing past the window may write past the end of
552 /// the underlying destination.
553 /// - Failing to initialize all `n_bytes` without returning an error may
554 /// leave uninitialized memory in the destination that later safe code
555 /// assumes to be fully initialized.
556 #[expect(unused_variables)]
557 #[inline(always)]
558 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer> {
559 /// Default trusted [`Writer`] wrapper used when an implementation does
560 /// not provide a specialized [`Writer::as_trusted_for`].
561 ///
562 /// This wrapper intentionally does not implement [`Writer::finish`].
563 /// The documentation for [`Writer::finish`] and the safety contract of
564 /// [`Writer::as_trusted_for`] tell callers to call `finish` on trusted
565 /// writers before using the parent writer again. Returning `Ok(self)`
566 /// directly would make the trusted writer identical to the parent
567 /// writer, so those callers would end up calling `finish` on the parent
568 /// before they are done using it.
569 ///
570 /// Keeping `finish` on the wrapper as a no-op preserves the expectation
571 /// that trusted writers are finalized after use without forcing an early
572 /// `finish` call on the underlying parent writer.
573 struct TrustedDefault<'a, W: ?Sized> {
574 inner: &'a mut W,
575 }
576
577 impl<W: Writer + ?Sized> Writer for TrustedDefault<'_, W> {
578 #[inline(always)]
579 fn write(&mut self, src: &[u8]) -> WriteResult<()> {
580 self.inner.write(src)
581 }
582
583 #[inline(always)]
584 unsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()> {
585 unsafe { self.inner.write_slice_t(src) }
586 }
587
588 #[inline(always)]
589 unsafe fn write_t<T: ?Sized>(&mut self, src: &T) -> WriteResult<()> {
590 unsafe { self.inner.write_t(src) }
591 }
592
593 #[inline(always)]
594 fn by_ref(&mut self) -> impl Writer {
595 TrustedDefault { inner: self.inner }
596 }
597
598 #[inline(always)]
599 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer> {
600 Ok(TrustedDefault { inner: self.inner })
601 }
602
603 #[inline(always)]
604 fn finish(&mut self) -> WriteResult<()> {
605 Ok(())
606 }
607 }
608
609 Ok(TrustedDefault { inner: self })
610 }
611
612 /// Write `T` as bytes into the source.
613 ///
614 /// # Safety
615 ///
616 /// - `T` must be plain ol' data.
617 #[inline]
618 unsafe fn write_t<T: ?Sized>(&mut self, src: &T) -> WriteResult<()> {
619 let src = unsafe { from_raw_parts((src as *const T).cast::<u8>(), size_of_val(src)) };
620 self.write(src)?;
621 Ok(())
622 }
623
624 /// Write `[T]` as bytes into the source.
625 ///
626 /// # Safety
627 ///
628 /// - `T` must be plain ol' data.
629 #[inline]
630 unsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()> {
631 let len = size_of_val(src);
632 let src = unsafe { from_raw_parts(src.as_ptr().cast::<u8>(), len) };
633 self.write(src)?;
634 Ok(())
635 }
636}
637
638impl<W: Writer + ?Sized> Writer for &mut W {
639 #[inline(always)]
640 fn by_ref(&mut self) -> impl Writer {
641 &mut **self
642 }
643
644 #[inline(always)]
645 fn finish(&mut self) -> WriteResult<()> {
646 (*self).finish()
647 }
648
649 #[inline(always)]
650 fn write(&mut self, src: &[u8]) -> WriteResult<()> {
651 (*self).write(src)
652 }
653
654 #[inline(always)]
655 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer> {
656 unsafe { (*self).as_trusted_for(n_bytes) }
657 }
658
659 #[inline(always)]
660 unsafe fn write_t<T: ?Sized>(&mut self, src: &T) -> WriteResult<()> {
661 unsafe { (*self).write_t(src) }
662 }
663
664 #[inline(always)]
665 unsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()> {
666 unsafe { (*self).write_slice_t(src) }
667 }
668}
669
670mod cursor;
671pub mod slice;
672#[cfg(feature = "std")]
673pub mod std_read;
674#[cfg(feature = "std")]
675pub mod std_write;
676#[cfg(feature = "alloc")]
677mod vec;
678pub use cursor::Cursor;
679#[cfg(test)]
680pub(crate) mod test_util;