The typed buffers are slices: words/floats/fixeds/doubles/pointers(n) make
zeroed, bounds-checked []int/[]float/... and the type names mean them. buffer(n)
is a []byte, with text_of, Fs.read_bytes/write_bytes and view(xs, start, n).
bytes(), indexing a raw pointer or bytes, free, resize, Memory.*, raw file calls,
data_of and C externs are refused outside unsafe { } / unsafe function, and a
project's own files may write unsafe only with --unsafe; the runtime and packages
are the platform. A slice passed to an extern goes as its data.
What the change found: Sync's atomics on a slice header, words(n) uninitialised,
input's fixed axes in ints, truetype's fixed outlines as ints, skin matrices
typed int, gl_shader's source table made from raw bytes. render3d gets safe
entry points (safe_api.ludic). Rendering is byte-identical; a frame costs the same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.4 KiB
Text
43 lines
1.4 KiB
Text
# bytes.ludic — L7: bytes a program can hold without raw memory. A `[]byte` from buffer(n) is
|
|
# bounds-checked like any slice; these turn one into text and move one to and from a file. The
|
|
# runtime is the platform, so the raw calls underneath (file_read, the NUL-terminated copy) are
|
|
# its business, not the caller's.
|
|
|
|
# the first n bytes of b as text (it stops at b's end, and the text ends at a zero byte if one comes first)
|
|
function text_of(b: []byte, n: int) -> string {
|
|
var k = n
|
|
if b == null { k = 0 }
|
|
if k > len(b) { k = len(b) }
|
|
if k < 0 { k = 0 }
|
|
let out = bytes(k + 1)
|
|
var i = 0
|
|
while i < k {
|
|
out[i] = b[i]
|
|
i += 1
|
|
}
|
|
out[k] = 0
|
|
return out
|
|
}
|
|
# a whole file as bytes - through the asset pack when the file is in one - or null
|
|
function fs_read_bytes(path: string) -> []byte {
|
|
let f = file_open(path, "rb")
|
|
if f == null { return null }
|
|
file_seek(f, 0, 2)
|
|
let n = file_tell(f)
|
|
file_seek(f, 0, 0)
|
|
let b = buffer(n)
|
|
let got = file_read(f, b, n)
|
|
file_close(f)
|
|
if got < n { return view(b, 0, got) }
|
|
return b
|
|
}
|
|
# the first `count` bytes of b to a file, replacing it; false when it cannot be written whole
|
|
function fs_write_bytes(path: string, b: []byte, count: int) -> bool {
|
|
var k = count
|
|
if k > len(b) { k = len(b) }
|
|
let f = file_open(path, "wb")
|
|
if f == null { return false }
|
|
let put = file_write(f, b, k)
|
|
file_close(f)
|
|
return put == k
|
|
}
|