Hands up: who likes parsing and writing binary structures?
Hands up: who likes parsing and writing binary formats?
OK, just a few of you, in the back. You're free to go.
Everyone else: Xenomorph eases the pain of working with binary formats. Instead of fiddling with counting bytes:
@itemlist[#:style 'ordered
@item{You build up a declaration of the binary format from its parts —like integers, strings, arrays, and pointers.}
@item{You define a @deftech{template} describing the binary format using smaller ingredients —like integers, strings, arrays, pointers, and other templates.}
@item{This declaration can then be used as a binary parser, converting a binary file to Racket values.}
@item{This template can then be used as a binary parser, reading bytes and parsing them into Racket values. This function is called @racket[decode].}
@item{This @emph{same} declaration can also be used as a binary compiler, converting Racket values to a binary file.}
@item{This @emph{same} template can also be used as a binary compiler, compiling Racket values to binary and writing them out to a file. This function is called @racket[encode].}
]
Derived principally from Devon Govett's @link["https://github.com/devongovett/restructure"]{@tt{restructure}} library for Node. Thanks for figuring out the hard parts, dude.
Derived principally from Devon Govett's @link["https://github.com/devongovett/restructure"]{@tt{restructure}} library for Node. Thanks for doing the heavy lifting, dude.
@section{Installation}
At the command line:
@verbatim{raco pkg install xenomorph}
After that, you can update the package from the command line:
@verbatim{raco pkg update xenomorph}
Invoke the library in a source file by importing it in the usual way: @code{(require xenomorph)}.
Invoke the library in a source file by importing it in the usual way:
@verbatim{(require xenomorph)}
@section{What is a binary format?}
Suppose we have a file on disk. What's in the file? Without knowing anything else, we can at least say the file contains a sequence of @deftech{bytes}. A @deftech{byte} is the smallest unit of data storage. Though not the smallest unit of information storage —that would be a @deftech{bit}. But when we read (or write) from disk (or other source), we work with bytes.
Commonly, files on disk are classified as being either in @deftech{binary} format or @emph{text} format. (A distinction observed by Racket functions such as @racket[write-to-file].) When we speak of binary vs. text, we are saying something about the @deftech{encoding} of the file: what do the bytes represent?
A text format is really just a special kind of binary format where the result is a human readable text string. Moreover, for ease simplicity, text files typically rely on pre-defined encodings.
@section{Quick start}
But this is a custom, not a requirement.
@section{Quick tutorial}
@examples[#:eval my-eval
(define four-ints (+ArrayT uint8 4))
@ -54,7 +71,40 @@ Invoke the library in a source file by importing it in the usual way: @code{(req