///|
/// Growable byte buffer backed by FixedArray[Byte].
/// All internal access is bounds-check free.
struct Buffer {
mut buf : FixedArray[Byte]
mut pos : Int
}
///|
/// Create a new buffer with the given initial capacity.
pub fn Buffer::new(size_hint? : Int = 256) -> Buffer {
{ buf: make_uninit(size_hint), pos: 0 }
}
///|
/// Ensure space for at least `additional` more bytes. Grows with doubling strategy.
pub fn Buffer::ensure_capacity(self : Buffer, additional : Int) -> Unit {
let required = self.pos + additional
if required > self.buf.length() {
let mut new_cap = self.buf.length() * 2
if new_cap < required {
new_cap = required
}
let new_buf = make_uninit(new_cap)
blit_fixed_array(new_buf, 0, self.buf, 0, self.pos)
self.buf = new_buf
}
}
///|
/// Append a single byte.
pub fn Buffer::write_byte(self : Buffer, b : Byte) -> Unit {
self.ensure_capacity(1)
self.buf.unsafe_set(self.pos, b)
self.pos += 1
}
///|
/// Append a single byte without capacity check. Caller must ensure capacity.
pub fn Buffer::write_byte_unchecked(self : Buffer, b : Byte) -> Unit {
self.buf.unsafe_set(self.pos, b)
self.pos += 1
}
///|
/// Append all bytes from `src`.
pub fn Buffer::write_bytes(self : Buffer, src : Bytes) -> Unit {
let len = src.length()
self.ensure_capacity(len)
blit_bytes(self.buf, self.pos, src, 0, len)
self.pos += len
}
///|
/// Append all bytes from `src`.
pub fn Buffer::write_bytesview(self : Buffer, src : BytesView) -> Unit {
let len = src.length()
self.ensure_capacity(len)
blit_bytesview(self.buf, self.pos, src, src.start_offset(), len)
self.pos += len
}
///|
/// Append `len` bytes from `src` starting at `offset`.
pub fn Buffer::write_fixed(
self : Buffer,
src : FixedArray[Byte],
offset : Int,
len : Int,
) -> Unit {
self.ensure_capacity(len)
blit_fixed_array(self.buf, self.pos, src, offset, len)
self.pos += len
}
///|
/// Read byte at absolute position. Bounds-check free.
pub fn Buffer::get_byte(self : Buffer, pos : Int) -> Byte {
self.buf.unsafe_get(pos)
}
///|
/// Copy `len` bytes from `src_pos` in the buffer to the current write position.
/// Handles overlapping regions correctly.
pub fn Buffer::copy_from_self(self : Buffer, src_pos : Int, len : Int) -> Unit {
self.ensure_capacity(len)
let distance = self.pos - src_pos
if distance >= len {
blit_fixed_array(self.buf, self.pos, self.buf, src_pos, len)
self.pos += len
} else {
let buf = self.buf
let mut dst = self.pos
let mut src = src_pos
for _ in 0.. Int {
self.pos
}
///|
/// Direct access to backing array.
pub fn Buffer::data(self : Buffer) -> FixedArray[Byte] {
self.buf
}
///|
/// Finalize: allocate exact-size uninit array, blit, reinterpret as Bytes.
pub fn Buffer::to_bytes(self : Buffer) -> Bytes {
let result = make_uninit(self.pos)
blit_fixed_array(result, 0, self.buf, 0, self.pos)
result.unsafe_reinterpret_as_bytes()
}
///|
/// Advance write position by `n`. Caller must have written directly to `data()`.
pub fn Buffer::unsafe_advance(self : Buffer, n : Int) -> Unit {
self.pos += n
}
///|
/// Reset write position to 0. Reuses allocated memory.
pub fn Buffer::reset(self : Buffer) -> Unit {
self.pos = 0
}