1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
use io;
use endian;
export type op_circle = struct {
pos: pos,
color: u32,
radius: u8,
};
export type op_stroke = struct {
pos0: pos,
pos1: pos,
color: u32,
radius: u8,
};
export type op = (op_circle | op_stroke);
type op_type = enum u8 {
CIRCLE,
STROKE,
};
export type deser_fail = !void;
// return value must be freed... for now. ehh
export fn ser_op(op: op) []u8 = match (op) {
case let opc: op_circle => yield ser_op_circle(opc);
case let ops: op_stroke => yield ser_op_stroke(ops);
};
export fn deser_op(bytes: []u8) (op | deser_fail) = switch (bytes[0]) {
case op_type::CIRCLE => yield deser_op_circle(bytes)?;
case op_type::STROKE => yield deser_op_stroke(bytes)?;
case => yield deser_fail;
};
fn ser_pos(bytes: []u8, pos: pos) void = {
endian::leputu32(bytes[0..4], pos.0: u32);
endian::leputu32(bytes[4..8], pos.1: u32);
};
fn deser_pos(bytes: []u8) pos = (
endian::legetu32(bytes[0..4]): i32,
endian::legetu32(bytes[4..8]): i32
);
def SER_LEN_CIRCLE = 14;
// type:1 pos: 8 color: 4, radius:1
fn ser_op_circle(opc: op_circle) []u8 = {
let buf: []u8 = alloc([0...],SER_LEN_CIRCLE);
buf[0] = op_type::CIRCLE;
let payload = buf[1..];
ser_pos(payload[0..8], opc.pos);
endian::leputu32(payload[8..12], opc.color: u32);
payload[12] = opc.radius;
return buf;
};
fn deser_op_circle(bytes: []u8) (op_circle|deser_fail) = {
if (len(bytes) != SER_LEN_CIRCLE) return deser_fail;
let payload = bytes[1..];
return op_circle {
pos = deser_pos(payload[0..8]),
color = endian::legetu32(payload[8..12]),
radius = payload[12],
};
};
def SER_LEN_STROKE = 22;
// type:1 pos0:8 pos1:8 color:4 radius:1
fn ser_op_stroke(ops: op_stroke) []u8 = {
let buf: []u8 = alloc([0...], SER_LEN_STROKE);
buf[0] = op_type::STROKE;
let payload = buf[1..];
ser_pos(payload[0..8], ops.pos0);
ser_pos(payload[8..16], ops.pos1);
endian::leputu32(payload[16..20], ops.color);
payload[20] = ops.radius;
return buf;
};
fn deser_op_stroke(bytes: []u8) (op_stroke|deser_fail) = {
if (len(bytes) != SER_LEN_STROKE) return deser_fail;
let payload = bytes[1..];
return op_stroke {
pos0 = deser_pos(payload[0..8]),
pos1 = deser_pos(payload[8..16]),
color = endian::legetu32(payload[16..20]),
radius = payload[20],
};
};
|