pub trait Writer {
// Required method
fn write(&mut self, src: &[u8]) -> WriteResult<()>;
// Provided methods
fn by_ref(&mut self) -> impl Writer { ... }
fn finish(&mut self) -> WriteResult<()> { ... }
unsafe fn as_trusted_for(
&mut self,
n_bytes: usize,
) -> WriteResult<impl Writer> { ... }
unsafe fn write_t<T: ?Sized>(&mut self, src: &T) -> WriteResult<()> { ... }
unsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()> { ... }
}Expand description
Trait for structured writing of bytes into a source of potentially uninitialized memory.
Required Methods§
Sourcefn write(&mut self, src: &[u8]) -> WriteResult<()>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
Write exactly src.len() bytes from the given src into the writer.
Provided Methods§
Sourcefn by_ref(&mut self) -> impl Writer
fn by_ref(&mut self) -> impl Writer
Get a mutable reference to the Writer.
Useful in situations where one has an impl Writer that
needs to be passed to mulitple functions requiring impl Writer.
Always prefer this over &mut writer to avoid recursive borrows.
struct FooBar {
foo: u32,
bar: u32,
}
unsafe impl<C: Config> SchemaWrite<C> for FooBar {
type Src = Self;
fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
// `writer.by_ref()`; Good ✅
let foo = <u32 as SchemaWrite<C>>::write(writer.by_ref(), &src.foo)?;
let bar = <u32 as SchemaWrite<C>>::write(writer, &src.bar)?;
Ok(())
}
}Sourcefn finish(&mut self) -> WriteResult<()>
fn finish(&mut self) -> WriteResult<()>
Finalize the writer by performing any required cleanup or flushing.
§Regarding trusted writers
Trusted writers are not guaranteed to live as long as the parent Writer that
created them, and are typically short-lived. wincode will call finish after
trusted writers have completed their work, so they may rely on finish perform
local cleanup when needed. Importantly, trusted writers must not perform actions
that would invalidate the parent Writer.
For example, a file writer may buffer internally and delegate to trusted sub-writers with their own buffers. These trusted writers should not close the underlying file descriptor or other parent-owned resources, as that would invalidate the parent writer.
Sourceunsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Advance the parent by n_bytes and return a Writer that can elide bounds checks within
that n_bytes window.
Implementors must:
- Ensure that either at least
n_bytesbytes are available backing the returned writer, or return an error. - Arrange that the returned
Trustedwriter’s methods operate within thatn_byteswindow (it may buffer or prefetch arbitrarily).
Note:
as_trusted_foris intended for callers that know they will operate within an exact-size window and want to avoid intermediate bounds checks.
§Safety
The caller must treat the returned writer as having exclusive access to
exactly n_bytes bytes of uninitialized output space in the parent,
and must:
- Ensure that no write performed through the
Trustedwriter can address memory outside of thatn_byteswindow. - In case the caller does not return an error, ensure that, before the
Trustedwriter is finished or the parent writer is used again, every byte in thatn_byteswindow has been initialized at least once via theTrustedwriter. - In case the caller does not return an error, call
Writer::finishon theTrustedwriter when writing is complete and before the parent writer is used again.
Concretely:
- All writes performed via the
Trustedwriter (write,write_t,write_slice_t, etc.) must stay within the[0, n_bytes)region of the reserved space. - It is permitted to overwrite the same bytes multiple times, but if the
caller returns no error, the union of all bytes written must cover the
entire
[0, n_bytes)window.
Violating this is undefined behavior, because:
Trustedwriters are permitted to elide bounds checks within then_byteswindow; writing past the window may write past the end of the underlying destination.- Failing to initialize all
n_byteswithout returning an error may leave uninitialized memory in the destination that later safe code assumes to be fully initialized.
Sourceunsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()>
unsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()>
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl Writer for &mut [MaybeUninit<u8>]
impl Writer for &mut [MaybeUninit<u8>]
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
Source§impl Writer for &mut [u8]
impl Writer for &mut [u8]
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
Source§impl Writer for Cursor<&mut Vec<u8>>
impl Writer for Cursor<&mut Vec<u8>>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
fn finish(&mut self) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Source§impl Writer for Cursor<&mut [u8]>
impl Writer for Cursor<&mut [u8]>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
fn finish(&mut self) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Source§impl Writer for Cursor<Box<[u8]>>
impl Writer for Cursor<Box<[u8]>>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
fn finish(&mut self) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Source§impl Writer for Cursor<Vec<u8>>
impl Writer for Cursor<Vec<u8>>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
fn finish(&mut self) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Source§impl Writer for Vec<u8>
Writer implementation for Vec<u8> that appends to the vector. The vector will grow as needed.
impl Writer for Vec<u8>
Writer implementation for Vec<u8> that appends to the vector. The vector will grow as needed.
§Examples
Writing to a new vector.
let mut vec = Vec::new();
let bytes = [1, 2, 3];
vec.write(&bytes).unwrap();
assert_eq!(vec, &[1, 2, 3]);Writing to an existing vector.
let mut vec = vec![1, 2, 3];
let bytes = [4, 5, 6];
vec.write(&bytes).unwrap();
assert_eq!(vec, &[1, 2, 3, 4, 5, 6]);fn write(&mut self, src: &[u8]) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Source§impl<W: Writer + ?Sized> Writer for &mut W
impl<W: Writer + ?Sized> Writer for &mut W
fn by_ref(&mut self) -> impl Writer
fn finish(&mut self) -> WriteResult<()>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
unsafe fn write_t<T: ?Sized>(&mut self, src: &T) -> WriteResult<()>
unsafe fn write_slice_t<T>(&mut self, src: &[T]) -> WriteResult<()>
Source§impl<const N: usize> Writer for Cursor<[u8; N]>
impl<const N: usize> Writer for Cursor<[u8; N]>
fn write(&mut self, src: &[u8]) -> WriteResult<()>
fn finish(&mut self) -> WriteResult<()>
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer>
Implementors§
impl Writer for wincode::io::Cursor<&mut Vec<u8>>
alloc only.Writer implementation for &mut Vec<u8> that overwrites the underlying vector’s memory.
The vector will grow as needed.
§Examples
Overwriting an existing vector.
let mut vec = vec![0; 3];
let mut cursor = Cursor::new(&mut vec);
let bytes = [1, 2, 3, 4];
cursor.write(&bytes).unwrap();
assert_eq!(&vec, &[1, 2, 3, 4]);Growing a vector.
let mut vec = vec![];
let mut cursor = Cursor::new(&mut vec);
let bytes = [1, 2, 3];
cursor.write(&bytes).unwrap();
assert_eq!(&vec, &[1, 2, 3]);impl Writer for wincode::io::Cursor<&mut [MaybeUninit<u8>]>
impl Writer for wincode::io::Cursor<&mut [u8]>
impl Writer for wincode::io::Cursor<Vec<u8>>
alloc only.Writer implementation for Vec<u8> that overwrites the underlying vector’s memory.
The vector will grow as needed.
§Examples
Overwriting an existing vector.
let mut cursor = Cursor::new(vec![0; 3]);
let bytes = [1, 2, 3, 4];
cursor.write(&bytes).unwrap();
assert_eq!(cursor.into_inner(), &[1, 2, 3, 4]);Growing a vector.
let mut cursor = Cursor::new(vec![]);
let bytes = [1, 2, 3];
cursor.write(&bytes).unwrap();
assert_eq!(cursor.into_inner(), &[1, 2, 3]);