///|
priv struct Writer {
out : Array[Byte]
limits : Limits
}
///|
fn Writer::room(self : Writer, count : Int32) -> Unit raise OscError {
if count < 0 || count > self.limits.packet_bytes - self.out.length() {
raise Limit("encoded packet bytes")
}
}
///|
fn Writer::word(self : Writer, value : UInt32) -> Unit raise OscError {
self.room(4)
for shift in [24, 16, 8, 0] {
self.out.push((value >> shift).to_byte())
}
}
///|
fn Writer::wide(self : Writer, value : UInt64) -> Unit raise OscError {
self.room(8)
self.word((value >> 32).to_uint())
self.word(value.to_uint())
}
///|
fn Writer::padding(self : Writer, size : Int32) -> Unit raise OscError {
let n = (4 - size % 4) % 4
self.room(n)
for _ in 0.. Unit raise OscError {
if !ascii_valid(text) {
raise Invalid("OSC string requires non-NUL ASCII", self.out.length())
}
if text.length() > self.limits.string_bytes {
raise Limit("string bytes")
}
self.room(text.length() + 1)
for c in text.code_units() {
self.out.push(c.to_byte())
}
self.out.push(0)
self.padding(text.length() + 1)
}
///|
fn Writer::blob(self : Writer, bytes : Bytes) -> Unit raise OscError {
if bytes.length() > self.limits.blob_bytes {
raise Limit("blob bytes")
}
self.room(4 + bytes.length())
self.word(bytes.length().reinterpret_as_uint())
for b in bytes {
self.out.push(b)
}
self.padding(bytes.length())
}