/
nv-lang
/
nova
Обзор
Документация
Войти
/
nv-lang
/
nova
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
std/src/runtime/write_buffer.nv
268 строк
10 KB
Evgeniy Golovin
lint(std/src,examples): fix remaining singles (6/6) — slice-copy, compound-assign, for-range, spelling
01 авг 2026, 17:59
01 авг 2026, 17:59
8b8304f
Код
Авторство
О чём код?
// WriteBuffer реализован полностью на Nova. // Тип: consume record с полем `mut buf []u8`. // Ранее: external type + C runtime (Nova_WriteBuffer + 30 inline C функций). // Теперь: Nova record; все методы на Nova-body над []u8 primitives // (push / append / extend_from / reserve / copy_from — memmove/memcpy). // // API contract (paritет с предыдущим C-runtime): // @write_byte/bytes/zero/char/str // @write_{u8,i8,u16_le,u16_be,...,u64_be,f32_le,f32_be,f64_le,f64_be} // @len, @capacity, @clone // consume @into_bytes -> []u8 // #no_prelude — break import cycle (prelude → collections → write_buffer). // Explicit imports cover only what we need. #no_prelude module runtime.write_buffer // f64/f32 `.to_bits()` used below (write_f32_le/be, write_f64_le/be) is a // plain Nova-body method in std/runtime/numeric.nv, NOT a compiler // intrinsic. `#no_prelude` files must import it explicitly. import std.runtime.numeric // ─── Type ─── // // **Design note:** WriteBuffer — НЕ consume type (в отличие от StringBuilder). // `consume @into()` метод даёт ownership transfer и type-safe // «no-reuse-after-into», но binding не требует `consume` keyword — это // сохраняет backward-compat с predecessor C runtime, где // `let mut wb = WriteBuffer.new()` был стандартным паттерном. export type WriteBuffer { mut buf []u8 } // ─── Constructors ─── // Default initial capacity — 16 bytes, matches предыдущий C runtime // (NOVA_WRITE_BUFFER_INIT_CAP). Same name as in std/runtime/string_builder.nv — // module-private const, codegen mangles C-name через `Nova_const_<modpath>_*`. const INITIAL_CAPACITY = 16 // Пустой WriteBuffer с pre-allocated capacity 16. export fn WriteBuffer.new(cap int = INITIAL_CAPACITY) -> Self requires cap >= 0 => { buf: []u8.new(cap: cap) } // WriteBuffer из существующих байт (deep copy — append через memmove). // Param `b` is readonly by default. // // [M-static-conv-array-record-mono-cc-fail] обход: static `.from` оставлен // вместо extension-метода `[]u8 @to_writebuffer()` — строящий user-record // тела, тот extension воспроизводимо ломает mono-коллектор (см. read_buffer.nv // коммент, идентичный класс бага: `Nova_NovaArray_nova_int_method_to_X` // undefined на линковке). Оставлено как static `.from` до фикса; // W_STATIC_CONVERSION находка сохранена намеренно. // nova:allow W_STATIC_CONVERSION -- rename заблокирован [M-static-conv-array-record-mono-cc-fail] (mono-баг extension-на-[]u8-с-record-телом); вернуть to_* после фикса export fn WriteBuffer.from(b []u8) -> Self { mut wb WriteBuffer = { buf: []u8.new(cap: b.len()) } wb.buf.append(b) wb } // ─── Query ─── // Текущий размер в байтах. export fn WriteBuffer @len() -> int => @buf.len() // Allocated capacity в байтах. // // `@capacity()` alias РЕТРАКТИРОВАН (дублировал канонический `@cap()`) — // `@cap()` теперь единственный 0-arg getter половины `cap`/`cap(n)` // property-пары (with_capacity удалён). export fn WriteBuffer @cap() -> int => @buf.cap() // Set capacity to exactly `n` bytes (delegates to the underlying `[]u8`'s // own exact `mut @cap(n)` — no rounding). Replacement for the removed // `WriteBuffer.with_capacity` static constructor: `WriteBuffer.new(cap: n)`. export fn WriteBuffer mut @cap(n int) -> @ requires n >= @len() { @buf.cap(n) } // Независимая копия (deep copy buffer). Read-only access — original не consume'ится. export fn WriteBuffer @clone() -> Self { mut copy WriteBuffer = { buf: []u8.new(cap: @buf.len()) } copy.buf.append(@buf) copy } // ─── Mutating writes (fluent -> @) ─── // Append один byte. Returns self for chaining. export fn WriteBuffer mut @write_byte(v u8) -> @ { @buf.push(v) } // Append массив байт (bulk memmove через []u8.append). // Param `src` is readonly by default. export fn WriteBuffer mut @write_bytes(src []u8) -> @ { @buf.append(src) } // Append n нулевых байт. n <= 0 → no-op. // Bulk memset extension (O(1) growth amortized + single memset(0) для всего // сегмента vs наивный push-loop с amortized realloc'ами). export fn WriteBuffer mut @write_zero(n int) -> @ requires n >= 0 { if n <= 0 { return } @buf.append_zero(n) } // UTF-8 encode codepoint (1-4 байта). Returns self. // Логика повторяет StringBuilder.@append(char). export fn WriteBuffer mut @write_char(c char) -> @ { ro (b, n) = c.encode_utf8() @buf.append(b[..n]) } // Append UTF-8 байты из str (bulk memmove через []u8.append + as_bytes). export fn WriteBuffer mut @write_str(s str) -> @ { @buf.append(s.bytes()) } // ─── 18 numeric × LE/BE ─── // // Все типизированные writes сводятся к LE/BE byte unpacking через // `as int` (bit-preserving cast) + shift/truncate. `as u8` — это // truncating cast на нижний байт, sign safely ignored. // 1 byte unsigned, без endianness. export fn WriteBuffer mut @write_u8(v u8) -> @ { @buf.push(v) } // 1 byte signed, без endianness — bit-pattern preserved через `as u8`. export fn WriteBuffer mut @write_i8(v i8) -> @ { @buf.push(v as u8) } // u16 little-endian (2 байта). export fn WriteBuffer mut @write_u16_le(v u16) -> @ { ro x = v as int @buf.push(x as u8) .push((x >> 8) as u8) } // u16 big-endian (2 байта). export fn WriteBuffer mut @write_u16_be(v u16) -> @ { ro x = v as int @buf.push((x >> 8) as u8) .push(x as u8) } // i16 little-endian (2 байта). export fn WriteBuffer mut @write_i16_le(v i16) -> @ { ro x = v as int @buf.push(x as u8) .push((x >> 8) as u8) } // i16 big-endian (2 байта). export fn WriteBuffer mut @write_i16_be(v i16) -> @ { ro x = v as int @buf.push((x >> 8) as u8) .push(x as u8) } // u32 little-endian (4 байта). export fn WriteBuffer mut @write_u32_le(v u32) -> @ { ro x = v as int @buf.push(x as u8) .push((x >> 8) as u8) .push((x >> 16) as u8) .push((x >> 24) as u8) } // u32 big-endian (4 байта). export fn WriteBuffer mut @write_u32_be(v u32) -> @ { ro x = v as int @buf.push((x >> 24) as u8) .push((x >> 16) as u8) .push((x >> 8) as u8) .push(x as u8) } // i32 little-endian (4 байта). export fn WriteBuffer mut @write_i32_le(v i32) -> @ { ro x = v as int @buf.push(x as u8) .push((x >> 8) as u8) .push((x >> 16) as u8) .push((x >> 24) as u8) } // i32 big-endian (4 байта). export fn WriteBuffer mut @write_i32_be(v i32) -> @ { ro x = v as int @buf.push((x >> 24) as u8) .push((x >> 16) as u8) .push((x >> 8) as u8) .push(x as u8) } // u64 little-endian (8 байт). export fn WriteBuffer mut @write_u64_le(v u64) -> @ { ro x = v as int @buf.push(x as u8) .push((x >> 8) as u8) .push((x >> 16) as u8) .push((x >> 24) as u8) .push((x >> 32) as u8) .push((x >> 40) as u8) .push((x >> 48) as u8) .push((x >> 56) as u8) } // u64 big-endian (8 байт). export fn WriteBuffer mut @write_u64_be(v u64) -> @ { ro x = v as int @buf.push((x >> 56) as u8) .push((x >> 48) as u8) .push((x >> 40) as u8) .push((x >> 32) as u8) .push((x >> 24) as u8) .push((x >> 16) as u8) .push((x >> 8) as u8) .push(x as u8) } // i64 little-endian (8 байт). export fn WriteBuffer mut @write_i64_le(v i64) -> @ { ro x = v as int @buf.push(x as u8) .push((x >> 8) as u8) .push((x >> 16) as u8) .push((x >> 24) as u8) .push((x >> 32) as u8) .push((x >> 40) as u8) .push((x >> 48) as u8) .push((x >> 56) as u8) } // i64 big-endian (8 байт). export fn WriteBuffer mut @write_i64_be(v i64) -> @ { ro x = v as int @buf.push((x >> 56) as u8) .push((x >> 48) as u8) .push((x >> 40) as u8) .push((x >> 32) as u8) .push((x >> 24) as u8) .push((x >> 16) as u8) .push((x >> 8) as u8) .push(x as u8) } // f32 / f64 — IEEE 754 reinterpret-cast через {f32,f64}.to_bits() // (std/runtime/numeric.nv), затем как unsigned int соответствующей ширины. // f32 little-endian IEEE 754. export fn WriteBuffer mut @write_f32_le(v f32) -> @ => @write_u32_le(v.to_bits()) // f32 big-endian IEEE 754. export fn WriteBuffer mut @write_f32_be(v f32) -> @ => @write_u32_be(v.to_bits()) // f64 little-endian IEEE 754. export fn WriteBuffer mut @write_f64_le(v f64) -> @ => @write_u64_le(v.to_bits()) // f64 big-endian IEEE 754. export fn WriteBuffer mut @write_f64_be(v f64) -> @ => @write_u64_be(v.to_bits()) // ─── Finalize ─── // Финализировать в []u8. После @into_bytes() WriteBuffer consumed. // Ownership transfer — возвращает внутренний buf напрямую (no copy). // #coerce — declares the implicit finalize-lane pair `WriteBuffer → []u8` // (owning zero-cost MOVE). #coerce export fn WriteBuffer consume @into_bytes() -> []u8 => @buf