silk.mem.raw_buffer.
Typed raw storage made from an allocation, for code that implements containers.
When to use#
Application code uses silk.collections.list.List, silk.collections.bytes.Bytes, or silk.mem.box.Box. Use RawBuffer
only when you implement a container that keeps its own record of capacity and of which slots are
initialized.
Details#
A RawBuffer<T> holds one allocation and a count of T slots. It does not record which slots
are initialized. Use RawBuffer.slot with the silk.mem.slot operations to change one slot, and
RawBuffer.copy, RawBuffer.view, and RawBuffer.viewMut to work on ranges.
RawBuffer.slot and RawBuffer.fill check the count and trap outside it. The unsafe
operations do not check.
Gotchas#
When a raw buffer is dropped, it releases its allocation but does not drop the values in it. A container must drop or take each initialized slot before it drops the buffer, or those values leak.
Examples#
Fill a byte buffer and read it back#
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.mem.layout { Layout }
import silk.mem.raw_buffer { RawBuffer }
import silk.num.u8
pub effect fn main() -> i32
! OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let allocation = run Allocator.allocate(Layout.of<[u8; 3]>())
|> Effect.provideMut<Allocator>(&mut allocator)
unsafe {
let mut buffer = RawBuffer.from<u8>(move allocation, 3)
RawBuffer.fill(&mut buffer, 0, 3, 14)
let values = RawBuffer.view<u8>(&buffer, 0, 3)
if u8.toI32(values[0] + values[1] + values[2]) != 42 {
return 1
}
}
return 0
}Import as RawBuffer with import silk.mem.raw_buffer { RawBuffer }.
Public declarations: 1.
RawBuffer#
pub struct RawBufferThe owner type of the raw buffer operations. It has no fields and is never constructed.
When to use#
Application code uses silk.collections.list.List, silk.collections.bytes.Bytes, or silk.mem.box.Box. Use these
operations only when you implement a container that keeps its own record of capacity and of
which slots are initialized.
Details#
A RawBuffer<T> holds one allocation and a count of T slots. It does not record which slots
are initialized. RawBuffer.slot and RawBuffer.fill check the count and trap outside it.
The unsafe operations do not check.
Gotchas#
When a raw buffer is dropped, it releases its allocation but does not drop the values in it. A container must drop or take each initialized slot before it drops the buffer, or those values leak.
This struct is not the builtin RawBuffer<T> storage type that RawBuffer.from returns.
Implementation RawBuffer#
impl RawBufferAssociated function from#
pub unsafe fn from<T>(allocation: Intrinsic.Allocation, count: usize) -> Intrinsic.RawBuffer<T>Returns a raw buffer of count slots of T that owns allocation. All slots are
uninitialized.
Gotchas#
The caller must prove that the allocation is large enough for count values of T and is
aligned for T. Layout.repeat(Layout.of<T>(), count) gives a layout that fits.
Associated function slot#
pub fn slot<'storage, T>(buffer: &'storage mut Intrinsic.RawBuffer<T>, index: usize) -> Intrinsic.Slot<'storage, T>Selects the slot at index for one silk.mem.slot operation.
Details#
The selection borrows the buffer exclusively until a slot operation consumes it. Lifetimes
inside T are not part of that borrow.
Gotchas#
An index that is not less than RawBuffer.count traps. The slot does not know if it is
initialized. The caller must track that.
Associated function count#
pub fn count<T>(buffer: &Intrinsic.RawBuffer<T>) -> usizeReturns the number of slots in the buffer. This is the capacity, not the number of initialized slots.
Associated function read#
pub unsafe fn read<T: Copy>(buffer: &Intrinsic.RawBuffer<T>, index: usize) -> TReturns a copy of the value in the slot at index. The slot stays initialized.
Gotchas#
The caller must prove that index is less than RawBuffer.count and that the slot is
initialized. If T is a reference, the copy keeps its own lifetime, also after the buffer is
released.
Associated function copy#
pub unsafe fn copy<T>(destination: &mut Intrinsic.RawBuffer<T>, destinationOffset: usize, source: &[T], length: usize) -> ()Moves length initialized values from source into the buffer, starting at slot
destinationOffset.
Details#
The source and the destination can overlap. The result is the same as a copy through a temporary buffer. After the call, the destination slots are initialized.
Gotchas#
The caller must prove that both ranges are in bounds and that the source values are initialized. The values move, so the caller must not use or drop them at the source again. The destination slots must be uninitialized, or their old values leak.
Associated function fill#
pub fn fill(buffer: &mut Intrinsic.RawBuffer<u8>, offset: usize, length: usize, value: u8) -> ()Sets length bytes, starting at slot offset, to value. After the call, those slots are
initialized.
Gotchas#
A range that goes past RawBuffer.count traps.
Associated function view#
pub unsafe fn view<T>(buffer: &Intrinsic.RawBuffer<T>, offset: usize, length: usize) -> &[T]Returns a shared slice of length slots, starting at slot offset.
Gotchas#
The caller must prove that the range is in bounds and that each slot in it is initialized.
Associated function viewMut#
pub unsafe fn viewMut<T>(buffer: &mut Intrinsic.RawBuffer<T>, offset: usize, length: usize) -> &mut [T]Returns an exclusive slice of length slots, starting at slot offset.
Gotchas#
The caller must prove that the range is in bounds and that each slot in it is initialized.
Category: Memory.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.