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

75 lines
2.7 KiB
Racket

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#lang reader (submod "racket.rkt" reader)
(require "utils.rkt" "array.rkt" "number.rkt")
(provide (all-defined-out))
#|
approximates
https://github.com/mbutterick/restructure/blob/master/src/LazyArray.coffee
|#
(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)
(unless (<= 0 index (sub1 len))
#;(raise-argument-error 'LazyArray:get (format "index in range 0 to ~a" len) index)
(void))
(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)))
(define/public-final (to-list)
(for/list ([i (in-range len)])
(get i))))
(define-subclass ArrayT (LazyArray)
(inherit-field len type)
(define/override (decode stream [parent #f])
(define pos (· stream pos)) ; ! placement matters. `resolve-length` will change `pos`
(define decoded-len (resolve-length len stream parent))
(let ([parent (if (NumberT? len)
(mhasheq 'parent parent
'_startOffset pos
'_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)
(send val to-list)
val) ctx))
(define/override (encode stream val [ctx #f])
(super encode stream (if (InnerLazyArray? val)
(send val to-list)
val) ctx)))
(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))
(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)))