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/pitfall/restructure/lazy-array.rkt

74 lines
2.7 KiB
Racket

#lang restructure/racket
8 years ago
(require "utils.rkt" "array.rkt" "number.rkt")
(provide (all-defined-out))
#|
approximates
https://github.com/mbutterick/restructure/blob/master/src/LazyArray.coffee
|#
8 years ago
(define-subclass object% (InnerLazyArray type [len #f] [stream #f] [ctx #f])
(unless stream (raise-argument-error 'LazyArray "stream" stream))
(define starting-pos (· stream pos))
(define item-cache (mhasheqv)) ; integer-keyed hash, rather than list
(define/public-final (get index)
8 years ago
(unless (<= 0 index (sub1 len))
(raise-argument-error 'LazyArray:get (format "index in range 0 to ~a" len) index))
(ref! item-cache index (λ ()
(define orig-pos (· stream pos))
(send stream pos (+ starting-pos (* (send type size #f ctx) index)))
(define new-item (send type decode stream ctx))
(send stream pos orig-pos)
new-item)))
8 years ago
(define/public-final (to-list)
(for/list ([i (in-range len)])
(get i))))
(define-subclass ArrayT (LazyArray)
8 years ago
(inherit-field len type)
(define/override (decode stream [parent #f])
8 years ago
(define pos (· stream pos)) ; ! placement matters. `resolve-length` will change `pos`
8 years ago
(define decoded-len (resolve-length len stream parent))
(let ([parent (if (NumberT? len)
(mhasheq 'parent parent
8 years ago
'_startOffset pos
8 years ago
'_currentOffset 0
'_length len)
parent)])
(define res (+InnerLazyArray type decoded-len stream parent))
(send stream pos (+ (· stream pos) (* decoded-len (send type size #f parent))))
res))
(define/override (size [val #f] [ctx #f])
(super size (if (InnerLazyArray? val)
8 years ago
(send val to-list)
val) ctx))
(define/override (encode stream val [ctx #f])
(super encode stream (if (InnerLazyArray? val)
8 years ago
(send val to-list)
val) ctx)))
8 years ago
(test-module
(require "stream.rkt")
(define bstr #"ABCD1234")
(define ds (+DecodeStream bstr))
(define la (+LazyArray uint8 4))
(define ila (send la decode ds))
(check-equal? (send ds pos) 4)
(check-equal? (send ila get 1) 66)
(check-equal? (send ila get 3) 68)
(check-equal? (send ds pos) 4)
(check-equal? (send ila to-list) '(65 66 67 68))
8 years ago
(define la2 (+LazyArray int16be (λ (t) 4)))
(define es (+EncodeStream))
(send la2 encode es '(1 2 3 4))
(check-equal? (send es dump) #"\0\1\0\2\0\3\0\4")
(check-equal? (send (send la2 decode (+DecodeStream #"\0\1\0\2\0\3\0\4")) to-list) '(1 2 3 4)))