93 lines
1.9 KiB
Odin
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
|
|
}
|