'Bincode' is the working name I've given to a pair (well, trio) of functions designed to work with binary formats. I know my general approach here isn't altogether unique, but I think in implementation it has some qualities of its own that I at least have found to be endearing.
Consume (+ Advance)
CONSUME takes a reference to a BINARY! and a named binary datatype (such as 'SIGNED-32, 'FLOAT-64, etc) or an INTEGER!, returns that value (or errors out if there's not enough input) and updates the reference to the point after said value.
source: #{010003}
consume source 'signed-16
; returns 64, source => #{03}
Additionally CONSUME can take a BLOCK! in which shorthand functions for the various datatypes are available:
source: #{03010203}
values: collect [
consume source [
loop unsigned-8 [
keep unsigned-8
]
]
]
; values => [1 2 3], source => #{}
ADVANCE simply skips a given INTEGER! amount.
Accumulate
ACCUMULATE goes in the reverse direction using the same shorthand functions:
accumulate #{} [
utf-8 65
utf-8 8212
float-64 pi
repeat x 3 [
unsigned-8 x
]
]
; => #{41E28094400921FB54442D18010203}
This snippet is another pass at creating a single-pixel PNG image (with an assist from a R2 DEFLATE wrapper):
chunkify: func [
target [binary!]
header [word!]
data [binary!]
/compress
][
header: as-binary form header
if compress [
data: deflate/envelope data 'zlib
]
accumulate target [
unsigned-32 length? data
accumulate header
accumulate data
accumulate crc32-checksum-of join header data
]
]
probe accumulate png: #{} [
accumulate #{
89504E47
0D0A1A0A
}
chunkify png 'IHDR #{
00000001
00000001
08 02 00 00 00
}
chunkify/compress png 'IDAT #{
00 CC0000
}
chunkify png 'tEXt join #{} [
"Title" null "Single Pixel!"
]
chunkify png 'IEND #{}
]
Notes
Fairly sure this is bait for a lot of where Ren-C has gone with uparse/streaming/ports etc. That's fine, what I'm looking for is the vocabulary that stretches over a handful of common file formats (including Zip). I don't necessarily think that this is a silver bullet, though it has worked well enough to be used in that domain with enough clarity to make adjustments and retain readability. Doesn't seem too much of a stretch to consider this sitting over a stream or even compressed stream too.