aboutsummaryrefslogtreecommitdiff
path: root/drawing/op.ha
blob: 82a412f39b6ef7292a56831fd4e6722e29ecbe5f (plain)
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],
	};
};