#lang debug racket/base (require racket/class "helper.rkt" "util.rkt" "number.rkt" "array.rkt" racket/stream sugar/unstable/dict) (provide (all-defined-out)) #| approximates https://github.com/mbutterick/restructure/blob/master/src/LazyArray.coffee |# (define xlazy-array% (class xarray% (super-new) (inherit-field [@type type] [@len len]) (define/override (xxdecode port parent) (define starting-pos (pos port)) ; ! placement matters. `resolve-length` will change `pos` (define len (resolve-length @len #:parent parent)) (define new-parent (if (xint? @len) (mhasheq 'parent parent '_startOffset starting-pos '_currentOffset 0 '_length @len) parent)) (define stream-starting-pos (pos port)) (begin0 (for/stream ([index (in-range len)]) (define orig-pos (pos port)) (pos port (+ stream-starting-pos (* (send @type xxsize #f new-parent) index))) (begin0 (send @type xxdecode port new-parent) (pos port orig-pos))) (pos port (+ (pos port) (* len (send @type xxsize #f new-parent)))))) (define/override (xxencode val port [parent #f]) (super xxencode (if (stream? val) (stream->list val) val) port parent)) (define/override (xxsize [val #f] [parent #f]) (super xxsize (if (stream? val) (stream->list val) val) parent)))) (define (+xlazy-array [type-arg #f] [len-arg #f] #:type [type-kwarg #f] #:length [len-kwarg #f] #:subclass [class xlazy-array%]) (define type (or type-arg type-kwarg)) (define len (or len-arg len-kwarg)) (new class [type type] [len len] [length-type 'count])) (module+ test (require rackunit "number.rkt" "generic.rkt") (define bstr #"ABCD1234") (define ds (open-input-bytes bstr)) (define la (+xlazy-array uint8 4)) (define ila (decode la ds)) (check-equal? (pos ds) 4) (check-equal? (stream-ref ila 1) 66) (check-equal? (stream-ref ila 3) 68) (check-equal? (pos ds) 4) (check-equal? (stream->list ila) '(65 66 67 68)) (define la2 (+xlazy-array int16be (λ (t) 4))) (check-equal? (encode la2 '(1 2 3 4) #f) #"\0\1\0\2\0\3\0\4") (check-equal? (stream->list (decode la2 (open-input-bytes #"\0\1\0\2\0\3\0\4"))) '(1 2 3 4)))