#+build linux package wayland import "base:runtime" import "core:io" _unmarshal_raw :: proc(stream: io.Stream, $Value_Type: typeid) -> (value: Value_Type, error: io.Error) where Value_Type == u32 || Value_Type == i32 || Value_Type == Object_ID || Value_Type == Message_Header { VALUE_LEN :: size_of(Value_Type) bytes: [VALUE_LEN]byte n_read := io.read(stream, bytes[:]) or_return if n_read < VALUE_LEN { return {}, .Unexpected_EOF } return transmute(Value_Type) bytes, nil } _unmarshal_fixed :: proc(stream: io.Stream) -> (value: Fixed, error: io.Error) { raw_value := _unmarshal_raw(stream, u32) or_return return Fixed{i=raw_value}, nil } _unmarshal_string :: proc(stream: io.Stream, allocator: runtime.Allocator) -> (str: string, error: io.Error) { str_len := _unmarshal_raw(stream, u32) or_return if str_len == 0 { return } // -1 because the string ends will a null terminator. buf := make([]byte, str_len - 1, allocator) n_read := io.read(stream, buf) or_return if n_read < len(buf) { error = .Unexpected_EOF return } // Pad to 4 bytes @(static) padding_buf: [4]byte remainder := (4 - (str_len % 4)) % 4 // +1 for unread null terminator. io.read(stream, padding_buf[:remainder+1]) return string(buf), nil } _unmarshal_to :: proc(destination: ^$T, stream: io.Stream, allocator: runtime.Allocator) -> io.Error { when T == u32 || T == i32 || T == Object_ID || T == Message_Header { destination^ = _unmarshal_raw(stream, T) or_return } else when T == Fixed { destination^ = _unmarshal_fixed(stream) or_return } else when T == string { destination^ = _unmarshal_string(stream, allocator) or_return } return nil }