|
|
|
#lang restructure/racket
|
|
|
|
(require "number.rkt" "utils.rkt" "stream.rkt")
|
|
|
|
(provide (all-defined-out))
|
|
|
|
|
|
|
|
#|
|
|
|
|
approximates
|
|
|
|
https://github.com/mbutterick/restructure/blob/master/src/String.coffee
|
|
|
|
|#
|
|
|
|
|
|
|
|
(struct $codec (encoder decoder) #:transparent)
|
|
|
|
|
|
|
|
(define-subclass Streamcoder (String [strlen #f] [encoding 'ascii])
|
|
|
|
(field [codec (caseq encoding
|
|
|
|
[(latin-1 ascii) ($codec string->bytes/latin-1 bytes->string/latin-1)]
|
|
|
|
[(utf-8 utf8) ($codec string->bytes/utf-8 bytes->string/utf-8)])])
|
|
|
|
|
|
|
|
(define/augment (decode stream [parent #f])
|
|
|
|
(define count (if strlen
|
|
|
|
(resolveLength strlen stream parent)
|
|
|
|
(send stream length)))
|
|
|
|
(define bytes (send stream read count))
|
|
|
|
(($codec-decoder codec) bytes))
|
|
|
|
|
|
|
|
(define/augment (encode stream val [parent #f])
|
|
|
|
(define bytes (($codec-encoder codec) (format "~a" val)))
|
|
|
|
|
|
|
|
(when (Number? strlen) ;; length-prefixed string
|
|
|
|
(send strlen encode stream (bytes-length bytes)))
|
|
|
|
|
|
|
|
(send stream write bytes))
|
|
|
|
|
|
|
|
(define/override (size [str-in #f])
|
|
|
|
(define str (or str-in (make-string strlen #\x)))
|
|
|
|
(define es (+EncodeStream))
|
|
|
|
(encode es str)
|
|
|
|
(bytes-length (send es dump))))
|
|
|
|
|
|
|
|
|
|
|
|
(test-module
|
|
|
|
(require "stream.rkt")
|
|
|
|
(define stream (+DecodeStream #"\2BCDEF"))
|
|
|
|
(define S (+String uint8 'utf8))
|
|
|
|
(check-equal? (send S decode stream) "BC")
|
|
|
|
(define os (+EncodeStream))
|
|
|
|
(send S encode os "Mike")
|
|
|
|
(check-equal? (send os dump) #"\4Mike")
|
|
|
|
(check-equal? (send (+String) size "foobar") 6))
|