diff --git a/xenomorph/xenomorph/stream.rkt b/xenomorph/xenomorph/stream.rkt deleted file mode 100644 index 6f2c5a77..00000000 --- a/xenomorph/xenomorph/stream.rkt +++ /dev/null @@ -1,205 +0,0 @@ -#lang racket/base -(require "private/racket.rkt") -(require racket/generic racket/private/generic-methods) -(provide (all-defined-out)) - -;; helper class -(define-subclass object% (PortWrapper _port) - (unless (port? _port) - (raise-argument-error 'PortWrapper:constructor "port" _port)) - (define/public (pos [where #f]) - (when where (file-position _port where)) - (file-position _port)) - (define/public (dump) (void))) - -(test-module - (check-not-exn (λ () (make-object PortWrapper (open-input-bytes #"Foo")))) - (check-not-exn (λ () (make-object PortWrapper (open-output-bytes)))) - (check-exn exn:fail? (λ () (make-object PortWrapper -42)))) - - - -#| approximates -https://github.com/mbutterick/restructure/blob/master/src/EncodeStream.coffee -|# - -;; basically just a wrapper for a Racket output port -(define EncodeStream - (class* PortWrapper (dumpable<%>) - (init-field [[maybe-output-port maybe-output-port] (open-output-bytes)]) - - (unless (output-port? maybe-output-port) - (raise-argument-error 'EncodeStream:constructor "output port" maybe-output-port)) - - (super-make-object maybe-output-port) - (inherit-field _port) - - (define/override-final (dump) (get-output-bytes _port)) - - (define/public-final (write val) - (unless (bytes? val) - (raise-argument-error 'EncodeStream:write "bytes" val)) - (write-bytes val _port) - (void)) - - (define/public-final (writeBuffer buffer) - (write buffer)) - - (define/public-final (writeUInt8 int) - (write (bytes int))) - - (define/public (writeString string [encoding 'ascii]) - ;; todo: handle encodings correctly. - ;; right now just utf8 and ascii are correct - (caseq encoding - [(utf16le ucs2 utf8 ascii) (writeBuffer (string->bytes/utf-8 string)) - (when (eq? encoding 'utf16le) - (error 'swap-bytes-unimplemented))] - [else (error 'unsupported-string-encoding)])) - - (define/public (fill val len) - (write (make-bytes len val))))) - -(define-class-predicates EncodeStream) - -(test-module - (define es (+EncodeStream)) - (check-true (EncodeStream? es)) - (send es write #"AB") - (check-equal? (· es pos) 2) - (send es write #"C") - (check-equal? (· es pos) 3) - (send es write #"D") - (check-equal? (· es pos) 4) - (check-exn exn:fail? (λ () (send es write -42))) - (check-exn exn:fail? (λ () (send es write 1))) - (define op (open-output-bytes)) - (define es2 (+EncodeStream op)) - (send es2 write #"FOOBAR") - (check-equal? (dump es2) #"FOOBAR") - (check-equal? (dump es2) #"FOOBAR") ; dump can repeat - (check-equal? (get-output-bytes op) #"FOOBAR") - (define es3 (+EncodeStream)) - (send es3 fill 0 10) - (check-equal? (dump es3) (make-bytes 10 0))) - - -#| approximates -https://github.com/mbutterick/restructure/blob/master/src/DecodeStream.coffee -|# - -;; basically just a wrapper for a Racket port -;; but needs to start with a buffer so length can be found - -(require "sizes.rkt") -(define-macro (define-reader ID) - #'(define/public (ID) - (define bs (*ref type-sizes (string->symbol (string-downcase (string-replace (symbol->string 'ID) "read" ""))))) - (readBuffer bs))) - -(define countable<%> - (interface* () - ([(generic-property gen:countable) - (generic-method-table gen:countable - (define (length o) (get-field length_ o)))]))) - - - -(define DecodeStreamT - (class* PortWrapper - (codable<%> dumpable<%> countable<%> posable<%>) - (init-field [buffer #""]) - (unless (bytes? buffer) ; corresponds to a Node Buffer, not a restructure BufferT object - (raise-argument-error 'DecodeStream:constructor "bytes" buffer)) - (super-make-object (open-input-bytes buffer)) - (inherit-field _port) - - (field [_pos 0] - [length_ (length buffer)]) - - (define/override (pos [where #f]) - (when where - (set! _pos (super pos where))) - _pos) - - (define/public (count-nonzero-chars) - ;; helper function for String - ;; counts nonzero chars from current position - (length (car (regexp-match-peek "[^\u0]*" _port)))) - - (public [-length length]) - (define (-length) length_) - - (define/public (readString length__ [encoding 'ascii]) - (define proc (caseq encoding - [(utf16le) (error 'bah)] - [(ucs2) (error 'bleh)] - [(utf8) bytes->string/utf-8] - [(ascii) bytes->string/latin-1] - [else identity])) - (define start (pos)) - (define stop (+ start length__)) - (proc (subbytes buffer start (pos stop)))) - - (define/public-final (readBuffer count) - (unless (index? count) - (raise-argument-error 'DecodeStream:read "positive integer" count)) - (define bytes-remaining (- length_ (pos))) - (when (> count bytes-remaining) - (raise-argument-error 'DecodeStream:read (format "byte count not more than bytes remaining = ~a" bytes-remaining) count)) - (increment-field! _pos this count) ; don't use `pos` method here because `read-bytes` will increment the port position - (define bs (read-bytes count _port)) - (unless (= _pos (file-position _port)) (raise-result-error 'DecodeStream "positions askew" (list _pos (file-position _port)))) - bs) - - (define/public (read count) (readBuffer count)) - - (define/public (readUInt8) (bytes-ref (readBuffer 1) 0)) - (define/public (readUInt16BE) (+ (arithmetic-shift (readUInt8) 8) (readUInt8))) - (define/public (readInt16BE) (unsigned->signed (readUInt16BE) 16)) - (define/public (readUInt16LE) (+ (readUInt8) (arithmetic-shift (readUInt8) 8))) - (define/public (readUInt24BE) (+ (arithmetic-shift (readUInt16BE) 8) (readUInt8))) - (define/public (readUInt24LE) (+ (readUInt16LE) (arithmetic-shift (readUInt8) 16))) - (define/public (readInt24BE) (unsigned->signed (readUInt24BE) 24)) - (define/public (readInt24LE) (unsigned->signed (readUInt24LE) 24)) - - (define/override-final (dump) - (define current-position (port-position _port)) - (set-port-position! _port 0) - (define bs (port->bytes _port)) - (set-port-position! _port current-position) - bs))) - - -(define-subclass DecodeStreamT (DecodeStream)) - -(test-module - (define ds (+DecodeStream #"ABCD")) - (check-true (DecodeStream? ds)) - (check-equal? (length ds) 4) - (check-equal? (dump ds) #"ABCD") - (check-equal? (dump ds) #"ABCD") ; dump can repeat - (check-equal? (send ds readUInt16BE) 16706) - (check-equal? (dump ds) #"ABCD") - (check-equal? (· ds pos) 2) - (check-equal? (send ds readUInt8) 67) - (check-equal? (· ds pos) 3) - (check-equal? (send ds readUInt8) 68) - (check-equal? (· ds pos) 4) - (check-exn exn:fail? (λ () (send ds read -42))) - (check-exn exn:fail? (λ () (send ds read 1)))) - - - -(test-module - (define-subclass xenomorph-base% (Dummy) - (define/augment (decode stream parent) "foo") - (define/augment (encode stream val parent) "bar") - (define/augment (size) 42)) - - (define d (+Dummy)) - (check-true (Dummy? d)) - (check-exn exn:fail:contract? (λ () (decode d 42))) - (check-not-exn (λ () (decode d #"foo"))) - (check-exn exn:fail:contract? (λ () (encode d 42 21))) - (check-not-exn (λ () (encode d 42 (open-output-bytes) )))) \ No newline at end of file