From 77cd7fdbda778a6404091616e68a5d16abb660a4 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Sat, 26 Aug 2017 22:38:17 -0700 Subject: [PATCH] continue docs --- pitfall/xenomorph/private/array.rkt | 20 +++++++---- pitfall/xenomorph/private/racket.rkt | 6 ++++ pitfall/xenomorph/scribblings/xenomorph.scrbl | 33 +++++++++++++++---- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/pitfall/xenomorph/private/array.rkt b/pitfall/xenomorph/private/array.rkt index dcef1476..b67c7a7c 100644 --- a/pitfall/xenomorph/private/array.rkt +++ b/pitfall/xenomorph/private/array.rkt @@ -29,10 +29,10 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee [else +inf.0])) (for/list ([i (in-naturals)] #:break (or (eof-object? (peek-byte port)) (= (pos port) end-pos))) - (send type decode port ctx))] + (send type decode port ctx))] ;; we have decoded-len, which is treated as count of items [else (for/list ([i (in-range decoded-len)]) - (send type decode port ctx))])) + (send type decode port ctx))])) (define/augride (size [val #f] [ctx #f]) @@ -43,7 +43,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee (values (mhasheq 'parent ctx) (send len size)) (values ctx 0))]) (+ len-size (for/sum ([item (in-list (countable->list val))]) - (send type size item ctx))))] + (send type size item ctx))))] [else (let ([item-count (resolve-length len #f ctx)] [item-size (send type size #f ctx)]) (* item-size item-count))])) @@ -54,8 +54,13 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee (raise-argument-error 'Array:encode "list or countable" array))) (define (encode-items ctx) - (for ([item (in-list (countable->list array))]) - (send type encode port item ctx))) + (let* ([items (countable->list array)] + [item-count (length items)] + [max-items (if (number? len) len item-count)]) + (unless (= item-count max-items) + (raise-argument-error 'Array:encode (format "list or countable with ~a items" max-items) items)) + (for ([item (in-list items)]) + (send type encode port item ctx)))) (cond [(NumberT? len) (define ctx (mhash 'pointers null @@ -65,10 +70,11 @@ https://github.com/mbutterick/restructure/blob/master/src/Array.coffee (send len encode port (length array)) ; encode length at front (encode-items ctx) (for ([ptr (in-list (· ctx pointers))]) ; encode pointer data at end - (send (· ptr type) encode port (· ptr val)))] + (send (· ptr type) encode port (· ptr val)))] [else (encode-items parent)]))) -(define-values (Array Array? +Array) (values ArrayT ArrayT? +ArrayT)) +(define-procedures (Array Array? +Array) (ArrayT ArrayT? +ArrayT)) +(define-procedures (array% array? array) (ArrayT ArrayT? +ArrayT)) (test-module (check-equal? (decode (+Array uint16be 3) #"ABCDEF") '(16706 17220 17734)) diff --git a/pitfall/xenomorph/private/racket.rkt b/pitfall/xenomorph/private/racket.rkt index d7a6bd3d..4c319ee3 100644 --- a/pitfall/xenomorph/private/racket.rkt +++ b/pitfall/xenomorph/private/racket.rkt @@ -22,6 +22,12 @@ sugar/port sugar/case) +(provide define-procedures) +(define-macro (define-procedures (NEW ...) (OLD ...)) + #'(define-values (NEW ...) + (values (if (procedure? OLD) + (procedure-rename OLD 'NEW) + OLD) ...))) (module reader syntax/module-reader #:language 'xenomorph/private/racket) \ No newline at end of file diff --git a/pitfall/xenomorph/scribblings/xenomorph.scrbl b/pitfall/xenomorph/scribblings/xenomorph.scrbl index 864b98d0..2cf2218b 100644 --- a/pitfall/xenomorph/scribblings/xenomorph.scrbl +++ b/pitfall/xenomorph/scribblings/xenomorph.scrbl @@ -8,17 +8,25 @@ @title{Xenomorph: binary decoding & encoding} -@author[(author+email "Matthew Butterick" "mb@mbtype.com")] +@author[(author+email "Matthew Butterick" "mb@mbtype.com") "Devon Govett"] @defmodule[xenomorph] -Hands up: who likes reading and writing binary structures? +Hands up: who likes parsing and writing binary structures? -OK, great. All of you are free to go. +OK, just a few of you, in the back. You're free to go. -Everyone else: keep reading. This library is for you. +Everyone else: Xenomorph eases the pain of working with binary formats. Instead of fiddling with counting bytes: -@italic{Derived principally from Devon Govett's @link["https://github.com/devongovett/restructure"]{@tt{restructure}} library for Node.} +@itemlist[#:style 'ordered +@item{You build up a declaration of the binary format from its parts — like integers, strings, arrays, and pointers.} + +@item{This declaration can then be used as a binary parser, converting a binary file to Racket values.} + +@item{This same declaration can @emph{also} be used as a binary compiler, converting Racket values to a binary file.} +] + +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. @section{Installation} @@ -31,7 +39,20 @@ After that, you can update the package from the command line: Invoke the library in a source file by importing it in the usual way: @code{(require xenomorph)}. -@section{Quick demo} +@section{Quick start} + +@examples[#:eval my-eval +(define four-ints (+ArrayT uint8 4)) + +(decode four-ints #"\1\2\3\4") +(decode four-ints #"\1\2\3") +(decode four-ints #"\1\2\3\4\5\6") + +(define op (open-output-string)) +(encode four-ints '(1 2 3 4) op) +(get-output-bytes op) + ] + @section{The big idea}