From 2222dc78a3a7220299fafddaae7d10cc486c61ac Mon Sep 17 00:00:00 2001 From: eunhhu Date: Mon, 19 Oct 2026 05:16:07 +0100 Subject: The three spec apps without their workarounds (Pure 140 after its decision point): inflate's code takes a bare list and its output is a bytes state, its block's tables built in the handler (lets' lists in inner blocks), 132 lines to 121; DNS's compression compares a suffix with == (bytes compared), 115 to 106; HTTP's left bytes a bytes state, names and codings compared as bytes, its field lines returned as a bare list, 159 to 148 --- examples/dns.aup | 15 ++------ examples/http.aup | 41 ++++++++------------ examples/inflate.aup | 105 ++++++++++++++++++++++----------------------------- 3 files changed, 64 insertions(+), 97 deletions(-) diff --git a/examples/dns.aup b/examples/dns.aup index fdc6722..8f7239a 100644 --- a/examples/dns.aup +++ b/examples/dns.aup @@ -100,18 +100,9 @@ view wire { let done = false while !done && r.name[k] != 0 { for s in seen { - if !done && s.name.bytes == r.name.bytes - k { - let same = true # bytes have no ==: compared a byte at a time - for b in 0 .. s.name.bytes { - if s.name[b] != r.name[k + b] { - same = false - break - } - } - if same { - out = out + two(49152 + s.at) # 0xc000: a pointer - done = true - } + if !done && s.name == r.name[k .. r.name.bytes] { + out = out + two(49152 + s.at) # 0xc000: a pointer + done = true } } if !done { diff --git a/examples/http.aup b/examples/http.aup index 15a4647..e2c2045 100644 --- a/examples/http.aup +++ b/examples/http.aup @@ -5,9 +5,6 @@ record Field { name: bytes value: bytes } -record Fields { - of: list of Field -} record Request { method: bytes target: bytes @@ -16,11 +13,8 @@ record Request { body: bytes trailers: list of Field } -record Left { - data: bytes -} state requests: list of Request -state pending: list of Left # the bytes no request has completed (a list of one: bytes are no state) +state pending: bytes # the bytes no request has completed input packet = message { data: bytes } fn letter(b) = b >= 0x61 && b <= 0x7a || b >= 0x41 && b <= 0x5a @@ -62,7 +56,7 @@ fn field(d, i, e) -> Field { } # The field lines from i to an empty line, and where it ends; -1 if they have not all come. -fn fields(d, i) -> Fields, number { +fn fields(d, i) { let out: list of Field let j = i let e = crlf(d, j) @@ -71,7 +65,7 @@ fn fields(d, i) -> Fields, number { j = e + 2 e = crlf(d, j) } - return Fields { of: out }, if e < 0 { -1 } else { e + 2 } + return out, if e < 0 { -1 } else { e + 2 } } # The request at the start of d, and its length; -1 if d holds only part of one. @@ -85,19 +79,18 @@ fn request(d) -> Request, number { require s1 > 0 && s2 > s1 + 1 && s2 + 9 == e for k in 0 .. s1 { require token(d[k]) } for k in s1 + 1 .. s2 { require d[k] >= 0x21 && d[k] <= 0x7e } - require text(d[s2 + 1 .. e - 1]) == "HTTP/1." && (d[e - 1] == 0x30 || d[e - 1] == 0x31) + require d[s2 + 1 .. e - 1] == "HTTP/1." && (d[e - 1] == 0x30 || d[e - 1] == 0x31) let found, i = fields(d, e + 2) if i < 0 { return Request {}, -1 } let hosts, coded, lengths, length = 0, 0, 0, 0 let chunked = false - for f in found.of { - let n = text(f.name) # a token: its bytes are text - if n == "host" { hosts = hosts + 1 } - if n == "transfer-encoding" { + for f in found { + if f.name == "host" { hosts = hosts + 1 } + if f.name == "transfer-encoding" { coded = coded + 1 - chunked = text(lower(f.value)) == "chunked" + chunked = lower(f.value) == "chunked" } - if n == "content-length" { + if f.name == "content-length" { lengths = lengths + 1 require f.value.bytes > 0 for k in 0 .. f.value.bytes { @@ -108,7 +101,7 @@ fn request(d) -> Request, number { } require hosts <= 1 && (hosts == 1 || d[e - 1] == 0x30) # HTTP/1.1 names its host let body = d[0 .. 0] - let trailers = Fields { of: [] } + let trailers: list of Field let j = i if coded > 0 { require lengths == 0 && coded == 1 && chunked @@ -133,7 +126,7 @@ fn request(d) -> Request, number { if n == 0 { let t, after = fields(d, c + 2) if after < 0 { return Request {}, -1 } - trailers = t + for f in t { trailers.append(f) } j = after more = false } else { @@ -149,16 +142,12 @@ fn request(d) -> Request, number { body = d[i .. i + length] j = i + length } - return Request { method: d[0 .. s1], target: d[s1 + 1 .. s2], minor: number(d[e - 1] - 0x30), fields: found.of, body: body, - trailers: trailers.of }, j + return Request { method: d[0 .. s1], target: d[s1 + 1 .. s2], minor: number(d[e - 1] - 0x30), fields: found, body: body, + trailers: trailers }, j } on packet { - let d = packet.data - if pending.count > 0 { - d = pending[0].data + d - pending.remove(pending.first) - } + let d = pending + packet.data let going = true while going && d.bytes > 0 { let r, n = request(d) @@ -169,5 +158,5 @@ on packet { d = d[n .. d.bytes] } } - if d.bytes > 0 { pending.append(Left { data: d }) } + pending = d } diff --git a/examples/inflate.aup b/examples/inflate.aup index 4516411..5144c25 100644 --- a/examples/inflate.aup +++ b/examples/inflate.aup @@ -4,13 +4,7 @@ record Code { counts: list of number # how many codes of each length, 0 to 15 symbols: list of number # the symbols in their codes' order } -record Lengths { - of: list of number -} -record Inflated { - data: bytes -} -state inflated: list of Inflated # the last stream's bytes (a list of one: a record is no state alone) +state inflated: bytes # the last stream's bytes input inflate = message { data: bytes } fn bit(d, at) = d[at // 8] >> at % 8 & 1 @@ -22,13 +16,13 @@ fn take(d, at, n) { return number(v) } -fn code(l) -> Code { +fn code(lengths) -> Code { let counts: list of number = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let symbols: list of number - for x in l.of { counts[x] = counts[x] + 1 } + for x in lengths { counts[x] = counts[x] + 1 } for n in 1 .. 16 { - for s in 0 .. l.of.count { - if l.of[s] == n { symbols.append(s) } + for s in 0 .. lengths.count { + if lengths[s] == n { symbols.append(s) } } } return Code { counts: counts, symbols: symbols } @@ -48,50 +42,6 @@ fn decode(d, at, c) { return 0, at } -# A block's literal and length code and its distance code, fixed (kind 1) or from bit at (kind 2), and the bit after. -fn codes(d, at, kind) -> Code, Code, number { - let lengths: list of number - let distances: list of number - let both: list of number - let order: list of number = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15] - let small: list of number = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - let i = at - if kind == 1 { - for s in 0 .. 288 { lengths.append(if s < 144 { 8 } else if s < 256 { 9 } else if s < 280 { 7 } else { 8 }) } - for s in 0 .. 30 { distances.append(5) } - return code(Lengths { of: lengths }), code(Lengths { of: distances }), i - } - let literals = take(d, i, 5) + 257 - let count = take(d, i + 5, 5) + 1 - let n = take(d, i + 10, 4) + 4 - i = i + 14 - for k in 0 .. n { small[order[k]] = take(d, i + 3 * k, 3) } - i = i + 3 * n - let c = code(Lengths { of: small }) - while both.count < literals + count { - let symbol, next = decode(d, i, c) - i = next - if symbol < 16 { - both.append(symbol) - } else if symbol == 16 { - require both.count > 0 # a repeat with nothing before it - let previous = both[both.count - 1] - for k in 0 .. 3 + take(d, i, 2) { both.append(previous) } - i = i + 2 - } else if symbol == 17 { - for k in 0 .. 3 + take(d, i, 3) { both.append(0) } - i = i + 3 - } else { - for k in 0 .. 11 + take(d, i, 7) { both.append(0) } - i = i + 7 - } - } - require both.count == literals + count - for s in 0 .. literals { lengths.append(both[s]) } - for s in literals .. literals + count { distances.append(both[s]) } - return code(Lengths { of: lengths }), code(Lengths { of: distances }), i -} - on inflate { let length_base: list of number = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258] @@ -100,6 +50,7 @@ on inflate { 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577] let distance_extra: list of number = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13] + let order: list of number = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15] let d = inflate.data let out: list of i64 let at = 0 @@ -116,8 +67,45 @@ on inflate { at = (b + 4 + size) * 8 } else { require kind != 3 - let lc, dc, next = codes(d, at, kind) - at = next + let lengths: list of number + let distances: list of number + if kind == 1 { + for s in 0 .. 288 { lengths.append(if s < 144 { 8 } else if s < 256 { 9 } else if s < 280 { 7 } else { 8 }) } + for s in 0 .. 30 { distances.append(5) } + } else { + let literals = take(d, at, 5) + 257 + let count = take(d, at + 5, 5) + 1 + let n = take(d, at + 10, 4) + 4 + at = at + 14 + let small: list of number = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + for k in 0 .. n { small[order[k]] = take(d, at + 3 * k, 3) } + at = at + 3 * n + let c = code(small) + let both: list of number + while both.count < literals + count { + let symbol, next = decode(d, at, c) + at = next + if symbol < 16 { + both.append(symbol) + } else if symbol == 16 { + require both.count > 0 # a repeat with nothing before it + let previous = both[both.count - 1] + for k in 0 .. 3 + take(d, at, 2) { both.append(previous) } + at = at + 2 + } else if symbol == 17 { + for k in 0 .. 3 + take(d, at, 3) { both.append(0) } + at = at + 3 + } else { + for k in 0 .. 11 + take(d, at, 7) { both.append(0) } + at = at + 7 + } + } + require both.count == literals + count + for s in 0 .. literals { lengths.append(both[s]) } + for s in literals .. literals + count { distances.append(both[s]) } + } + let lc = code(lengths) + let dc = code(distances) let symbol, then = decode(d, at, lc) at = then while symbol != 256 { @@ -138,6 +126,5 @@ on inflate { } } } - if inflated.count > 0 { inflated.remove(inflated.first) } - inflated.append(Inflated { data: bytes(out) }) + inflated = bytes(out) } -- cgit v1.2.3