93 lines
1.9 KiB
Odin

package lbp
import "base:intrinsics"
import "core:io"
import "core:mem"
import "core:strings"
Error :: union #shared_nil {
io.Error,
mem.Allocator_Error,
}
Coder :: struct {
stream: io.Stream,
version: i32,
allocator: mem.Allocator,
write: bool,
}
init_read :: proc(reader: io.Reader, allocator: mem.Allocator) -> (coder: Coder, err: Error) {
_, ok := io.to_reader(reader)
assert(ok, "init_read expected a reader")
coder = Coder {
stream = reader,
allocator = allocator,
write = false,
}
err = serialize_number(&coder, &coder.version)
return coder, err
}
init_write :: proc(writer: io.Writer, version: i32) -> (coder: Coder, err: Error) {
_, ok := io.to_writer(writer)
assert(ok, "init_write expected a writer")
coder = Coder {
stream = writer,
allocator = mem.panic_allocator(),
write = true,
version = version,
}
return coder, nil
}
serialize_bytes :: proc(e: ^Coder, val: []byte) -> io.Error {
if e.write {
_, err := io.write(e.stream, val)
return err
} else {
_, err := io.read(e.stream, val)
return err
}
}
serialize_number :: proc(
c: ^Coder,
val: ^$T,
) -> Error where intrinsics.type_is_integer(T) ||
intrinsics.type_is_float(T) {
num_bytes := size_of(val)
return serialize_bytes(c, mem.byte_slice(rawptr(val), size_of(T)))
}
serialize_vector :: proc(
c: ^Coder,
val: $T/^[$C]$V,
) -> Error where intrinsics.type_is_integer(V) ||
intrinsics.type_is_float(T) {
for i in 0 ..< len(val) {
serialize_number(c, &val[i])
}
}
serialize_string :: proc(c: ^Coder, val: ^string) -> Error {
if c.write {
bytes := transmute([]byte)(val^)
length := i32(len(bytes))
serialize_number(c, &length) or_return
serialize_bytes(c, bytes) or_return
} else {
length: i32
serialize_number(c, &length) or_return
bytes := make([]byte, length, c.allocator) or_return
serialize_bytes(c, bytes) or_return
val^ = string(bytes)
}
return nil
}