You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/xenomorph/xenomorph/lazy-array.rkt

64 lines
2.4 KiB
Racket

6 years ago
#lang debug racket/base
6 years ago
(require racket/class
6 years ago
"helper.rkt" "util.rkt" "number.rkt" "array.rkt" racket/stream sugar/unstable/dict)
6 years ago
(provide (all-defined-out))
6 years ago
#|
approximates
https://github.com/mbutterick/restructure/blob/master/src/LazyArray.coffee
|#
6 years ago
6 years ago
(define xlazy-array%
6 years ago
(class xarray%
6 years ago
(super-new)
6 years ago
(inherit-field [@type type] [@len len])
6 years ago
(define/override (xxdecode port parent)
(define starting-pos (pos port)) ; ! placement matters. `resolve-length` will change `pos`
6 years ago
(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))))))
6 years ago
(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])
6 years ago
(super xxsize (if (stream? val) (stream->list val) val) parent))))
6 years ago
6 years ago
(define (+xlazy-array [type-arg #f] [len-arg #f]
6 years ago
#:type [type-kwarg #f]
#:length [len-kwarg #f]
#:subclass [class xlazy-array%])
6 years ago
(define type (or type-arg type-kwarg))
(define len (or len-arg len-kwarg))
6 years ago
(new class [type type]
[len len]
[length-type 'count]))
6 years ago
(module+ test
6 years ago
(require rackunit "number.rkt" "generic.rkt")
6 years ago
(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)))