Struct scroll_buffer::DynamicBuffer [−][src]
pub struct DynamicBuffer { /* fields omitted */ }
Expand description
A buffer designed for Pwrite
that dynamically expands to hold all types written into it.
Uses a standard Vec
under the hood.
Use Cases
- You don’t know exactly how much you’re writing ahead of time.
- Your types change size depending on context parameters or specific values.
Allocations
By default, this buffer expands every time one byte is written. The with_increment
constructor can be used to change how much the buffer expands to reduce overall number of allocations.
Pwrite and TryIntoCtx
Types must implement TryIntoCtx
with a second generic parameter of DynamicBuffer
to be used.
use scroll::{ctx::TryIntoCtx, Error, LE, Pwrite};
use scroll_buffer::DynamicBuffer;
struct EvenOdd(u32);
impl TryIntoCtx<(), DynamicBuffer> for EvenOdd {
type Error = Error;
fn try_into_ctx(self, buf: &mut DynamicBuffer, _: ()) -> Result<usize, Self::Error> {
let offset = &mut 0;
if self.0 % 2 == 0 {
buf.gwrite_with(self.0, offset, LE)?;
} else {
buf.gwrite_with(self.0 as u64, offset, LE)?;
}
Ok(*offset)
}
}
let mut buf = DynamicBuffer::new();
let offset = buf.pwrite(EvenOdd(2), 0).unwrap();
assert_eq!(buf.get(), [2, 0, 0, 0]);
buf.pwrite(EvenOdd(3), offset).unwrap();
assert_eq!(buf.get()[offset..], [3, 0, 0, 0, 0, 0, 0, 0]);
Why can’t I use types that already implement the default TryIntoCtx?
The default type parameters for TryIntoCtx
expose a mutable raw slice to write into.
This is great for pre-allocated buffers and types that have a static written size; however,
we cannot create a custom slice type that performs dynamic expansions under the hood.
As a result, we need to expose a separate writing type that can track offsets and calculate when to allocate.
However, if your TryIntoCtx
impls don’t use any special slice APIs and just use Pwrite
and/or
basic indexing, it’s extremely easy to migrate! Just add the DynamicBuffer
generic type.
Implementations
Constructs an empty DynamicBuffer
with the default allocation increment of one byte.
Constructs an empty DynamicBuffer
with a custom allocation increment.
Gets a slice of all written bytes. Does not include extra bytes allocated by a large increment.
use scroll::{LE, Pwrite};
use scroll_buffer::DynamicBuffer;
let mut buf = DynamicBuffer::new();
assert_eq!(buf.get(), []);
buf.pwrite_with(2u32, 0, LE).unwrap();
assert_eq!(buf.get(), [2, 0, 0, 0]);
Resets the buffer’s contents. Maintains already allocated capacity.
use scroll::{LE, Pwrite};
use scroll_buffer::DynamicBuffer;
let mut buf = DynamicBuffer::new();
buf.pwrite_with(2u16, 0, LE).unwrap();
assert_eq!(buf.get(), [2, 0]);
buf.clear();
assert_eq!(buf.get(), []);
// does not reallocate!
buf.pwrite_with(0xffu8, 0, LE).unwrap();
assert_eq!(buf.get(), [0xff]);
Trait Implementations
fn pwrite_with<N: TryIntoCtx<Ctx, Self, Error = E>>(
&mut self,
n: N,
offset: usize,
ctx: Ctx
) -> Result<usize, E>
fn pwrite_with<N: TryIntoCtx<Ctx, Self, Error = E>>(
&mut self,
n: N,
offset: usize,
ctx: Ctx
) -> Result<usize, E>
Write N
at offset I
with context Ctx
Read more
fn pwrite<N>(&mut self, n: N, offset: usize) -> Result<usize, E> where
N: TryIntoCtx<Ctx, Self, Error = E>,
Ctx: Default,
Write n
into self
at offset
, with a default Ctx
. Updates the offset.
fn gwrite_with<N>(
&mut self,
n: N,
offset: &mut usize,
ctx: Ctx
) -> Result<usize, E> where
N: TryIntoCtx<Ctx, Self, Error = E>,
fn gwrite_with<N>(
&mut self,
n: N,
offset: &mut usize,
ctx: Ctx
) -> Result<usize, E> where
N: TryIntoCtx<Ctx, Self, Error = E>,
Write n
into self
at offset
, with the ctx
. Updates the offset.