# codec.ludic - bytes little-endian, one message written at a time (nw_*) and one read (nr_*). # Numbers go as their raw bits: a float as float_bits, never rounded and never fixed. export function nb_put8(p: []byte, o: int, v: int) -> void { p[o] = v & 255 } export function nb_put32(p: []byte, o: int, v: int) -> void { p[o] = v & 255 p[o + 1] = (v >> 8) & 255 p[o + 2] = (v >> 16) & 255 p[o + 3] = (v >> 24) & 255 } export function nb_get8(p: []byte, o: int) -> int { return p[o] & 255 } export function nb_get32(p: []byte, o: int) -> int { return (p[o] & 255) | ((p[o + 1] & 255) << 8) | ((p[o + 2] & 255) << 16) | ((p[o + 3] & 255) << 24) } # n bytes from src at s to dst at d, forwards: within one buffer it may only move bytes DOWN export function nb_copy(dst: []byte, d: int, src: []byte, s: int, n: int) -> void { for i in 0 .. n { dst[d + i] = src[s + i] } } # the writer: past the MTU it counts on and keeps nothing, and np_queue cuts the message there export function nw_begin(net_st: mut NetState) -> void { net_st.net__wl = 0 } export function nw_i(net_st: mut NetState, v: int) -> void { if net_st.net__wl + 4 <= NET_MTU { nb_put32(net_st.net__wb, net_st.net__wl, v) } net_st.net__wl += 4 } export function nw_b(net_st: mut NetState, v: bool) -> void { if v { nw_i(net_st, 1) } else { nw_i(net_st, 0) } } export function nw_f(net_st: mut NetState, v: float) -> void { nw_i(net_st, float_bits(v)) } # a string of at most 200 bytes; nw_text takes a longer one up to its own cap export function nw_s(net_st: mut NetState, s: string) -> void { nw_text(net_st, s, 200) } export function nw_text(net_st: mut NetState, s: string, cap: int) -> void { var n = len(s) if n > cap { n = cap } nw_i(net_st, n) for i in 0 .. n { if net_st.net__wl < NET_MTU { net_st.net__wb[net_st.net__wl] = s[i] } net_st.net__wl += 1 } } export function nw_len(net_st: NetState) -> int { return net_st.net__wl } # the reader: a short or bad message reads as zeros and sets nr_bad() export function nr_i(net_st: mut NetState) -> int { if net_st.net__rp + 4 > net_st.net__rl { net_st.net__rbad = true return 0 } let v = nb_get32(net_st.net__rb, net_st.net__rp) net_st.net__rp += 4 return v } export function nr_b(net_st: mut NetState) -> bool { return nr_i(net_st) != 0 } export function nr_f(net_st: mut NetState) -> float { return float_from_bits(nr_i(net_st)) } export function nr_s(net_st: mut NetState) -> string { return nr_text(net_st, 200) } export function nr_text(net_st: mut NetState, cap: int) -> string { let n = nr_i(net_st) if n < 0 or n > cap or net_st.net__rp + n > net_st.net__rl { net_st.net__rbad = true return "" } let sb = net_st.net__tsb sb_clear(sb) for i in 0 .. n { sb_byte(sb, net_st.net__rb[net_st.net__rp + i]) } net_st.net__rp += n return sb_intern(sb, net_st.net__ttb) } export function nr_bad(net_st: NetState) -> bool { return net_st.net__rbad } # a message that came in, made the one nr_* reads export function net_read(net_st: mut NetState, m: NetMessage) -> void { nb_copy(net_st.net__rb, 0, m.data, 0, m.len) net_st.net__rl = m.len net_st.net__rp = 0 net_st.net__rbad = false } # the message just written, as if it had come in (a loopback: a test, a host telling itself); the # record is kept, so it is good until the next net_written export function net_written(net_st: mut NetState) -> NetMessage { if net_st.net__wr == null { net_st.net__wr = new NetMessage net_st.net__wr.data = buffer(NET_MTU) } let m = net_st.net__wr m.from = net_st.net__my_pid m.len = min(net_st.net__wl, NET_MTU) nb_copy(m.data, 0, net_st.net__wb, 0, m.len) return m } # the message being read, copied out as the next one to write (a host passing it on) export function net_copy_read(net_st: mut NetState) -> void { nw_begin(net_st) nb_copy(net_st.net__wb, 0, net_st.net__rb, 0, net_st.net__rl) net_st.net__wl = net_st.net__rl }