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], }; };