zeros = repeat(bit, 0)
fn varint_u32.encode(x: [32]bit) ~ varint_u32.decode(bytes: [?: 1..=5]u8) {
scan x ~ bytes {
result.push(byte)
if x[7..].prefix_of(zeros) ~ byte & 0x80 == 0 {
byte = x.pop(7)
x.pop(0..)
} else {
byte = x.pop(7) | 0x80
}
}
}
zeros = repeat(bit, 0)
fn shrink_u32.encode(x: [32]bit) ~ shrink_u32.decode(bytes: [n: 1..=5]u8) {
scan x ~ bytes {
result.push(byte)
byte = x.pop(8)
if x[0..].prefix_of(zeros) ~ result.empty() {
x.pop(0..)
}
}
}
fn length_prefix.encode(b: [n: 0..1<<32]u8) ~ length_prefix.decode(bytes: [?: n+1..=n+5]u8) {
bytes.write(varint_length)
varint_length = varint_u32(n)
bytes.write_fixed(n, b)
}
-
Length prefixing with reverse
extern fn reverse(b: [n]u8) ~ reverse(b: [n]u8);
fn length_prefix.encode(b: [n: 0..1<<32]u8) ~ length_prefix.decode(bytes: [?: n+1..=n+5]u8) {
bytes.write(varint_length)
varint_length = varint_u32.encode(n)
bytes.write_fixed(n, reversed)
reversed = reverse(b)
}
fn length_prefix.encode(b: [n: 0..1<<32]u8) ~ length_prefix.decode(bytes: [?: n+1..=n+5]u8) {
varint_length = varint_u32.encode(n)
bytes.write(varint_length)
reversed = reverse(b)
bytes.write_fixed<n>(reversed)
}
-
Syntax for state definition
forward state [?]T {
mut push(x: T) ~ pop()
mut write(x: [?]T) ~ read()
mut<n: 0..1<<32> write_fixed(x: [n]T) ~ read_fixed()
}
forward state BlocksLru {
mut encode(offset: u32) ~ decode(encoded: u32)
mut touch(offset: u32): void
}
forward state FwdBitStream {
mut init(): void
mut flush(): void
mut close(): void
mut<n: 0..=64> push(b: [n]bits) ~ pop()
}
backward state BwdBitStream {
mut init_write() ~ close_read()
mut flush() ~ reload()
mut close_write() ~ init_read()
mut<n: 0..=64> push(b: [n]bits) ~ pop()
}
fn invalid.encode(x: u32) ~ invalid.decode(bytes: [?]u32) {
var ( blocks: BlocksLru )
y = blocks.encode(x)
z = blocks.encode(y)
bytes.push(z)
}
const RGBA = struct {
r: 0..256,
g: 0..256,
b: 0..256,
a: 0..256,
}
const Header {
magic: "qoif"
width: 0..1<<32
height: 0..1<<32
channels: {3, 4}
colorspace: {0, 1}
}
const Operation = union {
QOI_OP_RGB = struct { r: 0..256, g: 0..256, b: 0..256 },
QOI_OP_RGBA = struct { r: 0..256, g: 0..256, b: 0..256, a: 0..256 },
QOI_OP_INDEX = struct { index: 0..64 },
QOI_OP_DIFF = struct { dr: -2..2, dg: -2..2, db: -2..2 },
QOI_OP_LUMA = struct { dr: -32..32, dr_dg: -8..8, db_dg: -8..8 },
QOI_OP_RUN = struct { run: 0..64 },
}
fn qoi.encode({ header: Header, operations: [n]Operation }) ~ qoi.decode(bytes: [?]u8) {
bytes.write_fixed<4>("qoif")
bytes.write_fixed<4>(header.width)
bytes.write_fixed<4>(header.height)
bytes.write_fixed<4>(header.channels)
bytes.write_fixed<4>(header.colorspace)
~ size = header.width * header.height
scan operations ~ bytes {
current = operations.pop()
match current {
.QOI_OP_RGB ~ bytes[0] == 0b11111110 {
bytes.write_fixed<4>([0b11111110, current.r, current.g, current.b])
~ size -= 1
}
.QOI_OP_RGBA ~ bytes[0] == 0b11111111 {
bytes.write_fixed<5>([0b11111111, current.r, current.g, current.b, current.a])
~ size -= 1
}
.QOI_OP_INDEX ~ bytes[0][0..2] == 0b00 {
bytes.write_fixed<1>([0b00 || current.index])
~ size -= 1
}
.QOI_OP_DIFF ~ bytes[0][0..2] == 0b01 {
bytes.write_fixed<1>([0b01 || current.dr + 2 || current.dg + 2 || current.db + 2])
~ size -= 1
}
.QOI_OP_LUMA ~ bytes[0][0..2] == 0b10 {
bytes.write_fixed<2>([0b10 || current.dg + 32, current.dr_dg + 8 || current.db_dg + 8])
~ size -= 1
}
.QOI_OP_RUN ~ bytes[0][0..2] == 0b11 {
bytes.write_fixed<1>([0b11 || current.run])
~ size -= current.run
}
}
if ~ size == 0 {
break
}
}
bytes.write_fixed<8>([0, 0, 0, 0, 0, 0, 0, 1])
}
forward state qoi.Recent {
}
fn qoi.compress(image: [height: 0..1<<32, width: 0..1<<32]RGBA) ~ qoi.decompress({ header: Header, operations: [n]Operation }) {
header = Header { width: width, height: height, channels: 4, colorspace: 0 }
scan image ~ operations {
}
}