renames
parent
af8380e46d
commit
aa73861282
@ -0,0 +1,38 @@
|
||||
#lang racket/base
|
||||
(require racket/class "base.rkt" "number.rkt" "string.rkt")
|
||||
(provide (all-defined-out))
|
||||
|
||||
(define x:symbol%
|
||||
(class x:string%
|
||||
(super-new)
|
||||
|
||||
(define/override (pre-encode val)
|
||||
(unless (or (string? val) (symbol? val))
|
||||
(raise-argument-error 'x:symbol-encode "symbol or string" val))
|
||||
(if (symbol? val) (symbol->string val) val))
|
||||
|
||||
(define/override (post-decode val) (string->symbol val))))
|
||||
|
||||
(define (x:symbol [len-arg #f] [enc-arg #f]
|
||||
#:length [len-kwarg #f]
|
||||
#:encoding [enc-kwarg #f]
|
||||
#:pre-encode [pre-proc #f]
|
||||
#:post-decode [post-proc #f]
|
||||
#:base-class [base-class x:symbol%])
|
||||
(define len (or len-arg len-kwarg))
|
||||
(define encoding (or enc-arg enc-kwarg 'utf8))
|
||||
(new (generate-subclass base-class pre-proc post-proc) [len len] [encoding encoding]))
|
||||
|
||||
(module+ test
|
||||
(require rackunit "base.rkt")
|
||||
(define S-fixed (x:string 4 'utf8))
|
||||
(check-equal? (encode S-fixed "Mike" #f) #"Mike")
|
||||
(check-exn exn:fail? (λ () (encode S-fixed "Mikes" #f))) ; too long for fixed string
|
||||
(define S (x:string uint8 'utf8))
|
||||
(check-equal? (decode S #"\2BCDEF") "BC")
|
||||
(check-equal? (encode S "Mike" #f) #"\4Mike")
|
||||
(check-equal? (size (x:string) "foobar") 7) ; null terminated when no len
|
||||
(check-equal? (decode (x:symbol 4) #"Mike") 'Mike)
|
||||
(check-equal? (encode (x:symbol 4) 'Mike #f) #"Mike")
|
||||
(check-equal? (encode (x:symbol 4) "Mike" #f) #"Mike")
|
||||
(check-exn exn:fail:contract? (λ () (encode (x:symbol 4) 42 #f))))
|
@ -1,116 +0,0 @@
|
||||
#lang racket/base
|
||||
(require rackunit
|
||||
racket/class
|
||||
"../array.rkt"
|
||||
"../struct.rkt"
|
||||
"../number.rkt"
|
||||
"../pointer.rkt"
|
||||
"../base.rkt"
|
||||
sugar/unstable/dict)
|
||||
|
||||
#|
|
||||
approximates
|
||||
https://github.com/mbutterick/restructure/blob/master/test/Array.coffee
|
||||
|#
|
||||
|
||||
(test-case
|
||||
"array: decode fixed length"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint8 #:length 4)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"array: decode nested"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type (x:struct 'foo uint8) #:length 4))
|
||||
(list (mhasheq 'foo 1)
|
||||
(mhasheq 'foo 2)
|
||||
(mhasheq 'foo 3)
|
||||
(mhasheq 'foo 4)))))
|
||||
|
||||
(test-case
|
||||
"array: decode with post-decode"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(define xa (x:array #:type uint8 #:length 4 #:post-decode (λ (val) (map (λ (x) (* 2 x)) val))))
|
||||
(check-equal? (decode xa) '(2 4 6 8))))
|
||||
|
||||
(test-case
|
||||
"array: decode fixed number of bytes"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint16be #:length 4 #:count-bytes #t)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"array: decode length from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint8 #:length 'len) (current-input-port) #:parent (mhash 'len 4)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"array: decode byte count from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint16be #:length 'len #:count-bytes #t) (current-input-port) #:parent (mhash 'len 4)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"array: decode length as number before array"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 4 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint8 #:length uint8)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"array: decode byte count as number before array"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 4 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint16be #:length uint8 #:count-bytes #t)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"array: decode length from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint8 #:length (λ _ 4))) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"array: decode byte count from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint16be #:length (λ _ 4) #:count-bytes #t)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"array: decode to the end of parent if no length given"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint8) (current-input-port) #:parent (mhash x:length-key 4 x:start-offset-key 0)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"array: decode to the end of the stream if parent exists, but its length is 0"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:array #:type uint8) (current-input-port) #:parent (mhash x:length-key 0 x:start-offset-key 0)) '(1 2 3 4 5))))
|
||||
|
||||
(test-case
|
||||
"array: decode to the end of the stream if no parent and length is given"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4))])
|
||||
(check-equal? (decode (x:array #:type uint8)) '(1 2 3 4 ))))
|
||||
|
||||
(test-case
|
||||
"array: use array length"
|
||||
(check-equal? (size (x:array #:type uint8 #:length 10) '(1 2 3 4)) 4))
|
||||
|
||||
(test-case
|
||||
"array: add size of length field before string"
|
||||
(check-equal? (size (x:array #:type uint8 #:length uint8) '(1 2 3 4)) 5))
|
||||
|
||||
(test-case
|
||||
"array: use defined length if no value given"
|
||||
(check-equal? (size (x:array #:type uint8 #:length 10)) 10))
|
||||
|
||||
(test-case
|
||||
"array: encode using array length"
|
||||
(check-equal? (encode (x:array #:type uint8 #:length 10) '(1 2 3 4) #f) (bytes 1 2 3 4)))
|
||||
|
||||
(test-case
|
||||
"array: encode with pre-encode"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(define xa (x:array #:type uint8 #:length 4 #:pre-encode (λ (val) (map (λ (x) (* 2 x)) val))))
|
||||
(check-equal? (encode xa '(1 2 3 4) #f) (bytes 2 4 6 8))))
|
||||
|
||||
(test-case
|
||||
"array: encode length as number before array"
|
||||
(check-equal? (encode (x:array #:type uint8 #:length uint8) '(1 2 3 4) #f) (bytes 4 1 2 3 4)))
|
||||
|
||||
(test-case
|
||||
"array: add pointers after array if length is encoded at start"
|
||||
(check-equal? (encode (x:array #:type (x:pointer #:offset-type uint8
|
||||
#:type uint8)
|
||||
#:length uint8) '(1 2 3 4) #f) (bytes 4 5 6 7 8 1 2 3 4)))
|
@ -0,0 +1,116 @@
|
||||
#lang racket/base
|
||||
(require rackunit
|
||||
racket/class
|
||||
"../list.rkt"
|
||||
"../struct.rkt"
|
||||
"../number.rkt"
|
||||
"../pointer.rkt"
|
||||
"../base.rkt"
|
||||
sugar/unstable/dict)
|
||||
|
||||
#|
|
||||
approximates
|
||||
https://github.com/mbutterick/restructure/blob/master/test/Array.coffee
|
||||
|#
|
||||
|
||||
(test-case
|
||||
"list: decode fixed length"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint8 #:length 4)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"list: decode nested"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type (x:struct 'foo uint8) #:length 4))
|
||||
(list (mhasheq 'foo 1)
|
||||
(mhasheq 'foo 2)
|
||||
(mhasheq 'foo 3)
|
||||
(mhasheq 'foo 4)))))
|
||||
|
||||
(test-case
|
||||
"list: decode with post-decode"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(define xa (x:list #:type uint8 #:length 4 #:post-decode (λ (val) (map (λ (x) (* 2 x)) val))))
|
||||
(check-equal? (decode xa) '(2 4 6 8))))
|
||||
|
||||
(test-case
|
||||
"list: decode fixed number of bytes"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint16be #:length 4 #:count-bytes #t)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"list: decode length from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint8 #:length 'len) (current-input-port) #:parent (mhash 'len 4)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"list: decode byte count from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint16be #:length 'len #:count-bytes #t) (current-input-port) #:parent (mhash 'len 4)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"list: decode length as number before array"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 4 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint8 #:length uint8)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"list: decode byte count as number before array"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 4 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint16be #:length uint8 #:count-bytes #t)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"list: decode length from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint8 #:length (λ _ 4))) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"list: decode byte count from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint16be #:length (λ _ 4) #:count-bytes #t)) '(258 772))))
|
||||
|
||||
(test-case
|
||||
"list: decode to the end of parent if no length given"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint8) (current-input-port) #:parent (mhash x:length-key 4 x:start-offset-key 0)) '(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"list: decode to the end of the stream if parent exists, but its length is 0"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:list #:type uint8) (current-input-port) #:parent (mhash x:length-key 0 x:start-offset-key 0)) '(1 2 3 4 5))))
|
||||
|
||||
(test-case
|
||||
"list: decode to the end of the stream if no parent and length is given"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4))])
|
||||
(check-equal? (decode (x:list #:type uint8)) '(1 2 3 4 ))))
|
||||
|
||||
(test-case
|
||||
"list: use array length"
|
||||
(check-equal? (size (x:list #:type uint8 #:length 10) '(1 2 3 4)) 4))
|
||||
|
||||
(test-case
|
||||
"list: add size of length field before string"
|
||||
(check-equal? (size (x:list #:type uint8 #:length uint8) '(1 2 3 4)) 5))
|
||||
|
||||
(test-case
|
||||
"list: use defined length if no value given"
|
||||
(check-equal? (size (x:list #:type uint8 #:length 10)) 10))
|
||||
|
||||
(test-case
|
||||
"list: encode using array length"
|
||||
(check-equal? (encode (x:list #:type uint8 #:length 10) '(1 2 3 4) #f) (bytes 1 2 3 4)))
|
||||
|
||||
(test-case
|
||||
"list: encode with pre-encode"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(define xa (x:list #:type uint8 #:length 4 #:pre-encode (λ (val) (map (λ (x) (* 2 x)) val))))
|
||||
(check-equal? (encode xa '(1 2 3 4) #f) (bytes 2 4 6 8))))
|
||||
|
||||
(test-case
|
||||
"list: encode length as number before array"
|
||||
(check-equal? (encode (x:list #:type uint8 #:length uint8) '(1 2 3 4) #f) (bytes 4 1 2 3 4)))
|
||||
|
||||
(test-case
|
||||
"list: add pointers after array if length is encoded at start"
|
||||
(check-equal? (encode (x:list #:type (x:pointer #:offset-type uint8
|
||||
#:type uint8)
|
||||
#:length uint8) '(1 2 3 4) #f) (bytes 4 5 6 7 8 1 2 3 4)))
|
@ -1,14 +1,16 @@
|
||||
#lang racket/base
|
||||
|
||||
(require "array-test.rkt"
|
||||
"bitfield-test.rkt"
|
||||
"buffer-test.rkt"
|
||||
(require "bitfield-test.rkt"
|
||||
"bytes-test.rkt"
|
||||
"enum-test.rkt"
|
||||
"lazy-array-test.rkt"
|
||||
"list-test.rkt"
|
||||
"number-test.rkt"
|
||||
"optional-test.rkt"
|
||||
"pointer-test.rkt"
|
||||
"reserved-test.rkt"
|
||||
"stream-test.rkt"
|
||||
"string-test.rkt"
|
||||
"symbol-test.rkt"
|
||||
"struct-test.rkt"
|
||||
"vector-test.rkt"
|
||||
"versioned-struct-test.rkt")
|
||||
|
@ -0,0 +1,120 @@
|
||||
#lang racket/base
|
||||
(require rackunit
|
||||
racket/class
|
||||
"../base.rkt"
|
||||
"../symbol.rkt"
|
||||
"../number.rkt"
|
||||
"../base.rkt"
|
||||
sugar/unstable/dict)
|
||||
|
||||
|
||||
(test-case
|
||||
"symbol: decode fixed length"
|
||||
(parameterize ([current-input-port (open-input-bytes #"testing")])
|
||||
(check-equal? (decode (x:symbol 7)) 'testing)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode fixed length with post-decode"
|
||||
(parameterize ([current-input-port (open-input-bytes #"testing")])
|
||||
(define xs (x:symbol 7 #:post-decode (λ (val) '|ring a ding|)))
|
||||
(check-equal? (decode xs) '|ring a ding|)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode length from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes #"testing")])
|
||||
(check-equal? (decode (x:symbol 'len) (current-input-port) #:parent (mhash 'len 7)) 'testing)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode length as number before symbol"
|
||||
(parameterize ([current-input-port (open-input-bytes #"\x07testing")])
|
||||
(check-equal? (decode (x:symbol uint8) (current-input-port) #:parent (mhash 'len 7)) 'testing)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode utf8"
|
||||
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "🍻"))])
|
||||
(check-equal? (decode (x:symbol 4 'utf8)) '🍻)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode encoding computed from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "🍻"))])
|
||||
(check-equal? (decode (x:symbol 4 (λ _ 'utf8))) '🍻)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode null-terminated symbol and read past terminator"
|
||||
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "🍻\x00"))])
|
||||
(check-equal? (decode (x:symbol #f 'utf8)) '🍻)
|
||||
(check-equal? (pos (current-input-port)) 5)))
|
||||
|
||||
(test-case
|
||||
"symbol: decode remainder of buffer when null-byte missing"
|
||||
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "🍻"))])
|
||||
(check-equal? (decode (x:symbol #f 'utf8)) '🍻)))
|
||||
|
||||
(test-case
|
||||
"symbol: size should use symbol length"
|
||||
(check-equal? (size (x:symbol 7) 'testing) 7))
|
||||
|
||||
(test-case
|
||||
"symbol: size should use correct encoding"
|
||||
(check-equal? (size (x:symbol 10 'utf8) '🍻) 4))
|
||||
|
||||
(test-case
|
||||
"symbol: size should use encoding from function"
|
||||
(check-equal? (size (x:symbol 10 (λ _ 'utf8)) '🍻) 4))
|
||||
|
||||
(test-case
|
||||
"symbol: should add size of length field before symbol"
|
||||
(check-equal? (size (x:symbol uint8 'utf8) '🍻) 5))
|
||||
|
||||
; todo: it "should work with utf16be encoding"
|
||||
|
||||
(test-case
|
||||
"symbol: size should take null-byte into account"
|
||||
(check-equal? (size (x:symbol #f 'utf8) '🍻) 5))
|
||||
|
||||
(test-case
|
||||
"symbol: size should use defined length if no value given"
|
||||
(check-equal? (size (x:symbol 10)) 10))
|
||||
|
||||
(test-case
|
||||
"symbol: encode using symbol length"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(encode (x:symbol 7) 'testing)
|
||||
(check-equal? (get-output-bytes (current-output-port)) #"testing")))
|
||||
|
||||
(test-case
|
||||
"symbol: encode using symbol length and pre-encode"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(define xs (x:symbol 7 #:pre-encode (λ (val) (string->symbol (list->string (reverse (string->list (symbol->string val))))))))
|
||||
(encode xs 'testing)
|
||||
(check-equal? (get-output-bytes (current-output-port)) #"gnitset")))
|
||||
|
||||
(test-case
|
||||
"symbol: encode length as number before symbol"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(encode (x:symbol uint8) 'testing)
|
||||
(check-equal? (get-output-bytes (current-output-port)) #"\x07testing")))
|
||||
|
||||
(test-case
|
||||
"symbol: encode length as number before symbol utf8"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(encode (x:symbol uint8 'utf8) "testing 😜")
|
||||
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "\x0ctesting 😜"))))
|
||||
|
||||
(test-case
|
||||
"symbol: encode utf8"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(encode (x:symbol 4 'utf8) '🍻 )
|
||||
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "🍻"))))
|
||||
|
||||
(test-case
|
||||
"symbol: encode encoding computed from function"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(encode (x:symbol 4 (λ _ 'utf8)) '🍻)
|
||||
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "🍻"))))
|
||||
|
||||
(test-case
|
||||
"symbol: encode null-terminated symbol"
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(encode (x:symbol #f 'utf8) '🍻 )
|
||||
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "🍻\x00"))))
|
@ -0,0 +1,117 @@
|
||||
#lang racket/base
|
||||
(require rackunit
|
||||
racket/class
|
||||
racket/vector
|
||||
"../vector.rkt"
|
||||
"../struct.rkt"
|
||||
"../number.rkt"
|
||||
"../pointer.rkt"
|
||||
"../base.rkt"
|
||||
sugar/unstable/dict)
|
||||
|
||||
#|
|
||||
approximates
|
||||
https://github.com/mbutterick/restructure/blob/master/test/Array.coffee
|
||||
|#
|
||||
|
||||
(test-case
|
||||
"vector: decode fixed length"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint8 #:length 4)) '#(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"vector: decode nested"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type (x:struct 'foo uint8) #:length 4))
|
||||
(vector (mhasheq 'foo 1)
|
||||
(mhasheq 'foo 2)
|
||||
(mhasheq 'foo 3)
|
||||
(mhasheq 'foo 4)))))
|
||||
|
||||
(test-case
|
||||
"vector: decode with post-decode"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(define xa (x:vector #:type uint8 #:length 4 #:post-decode (λ (val) (vector-map (λ (x) (* 2 x)) val))))
|
||||
(check-equal? (decode xa) '#(2 4 6 8))))
|
||||
|
||||
(test-case
|
||||
"vector: decode fixed number of bytes"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint16be #:length 4 #:count-bytes #t)) '#(258 772))))
|
||||
|
||||
(test-case
|
||||
"vector: decode length from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint8 #:length 'len) (current-input-port) #:parent (mhash 'len 4)) '#(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"vector: decode byte count from parent key"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint16be #:length 'len #:count-bytes #t) (current-input-port) #:parent (mhash 'len 4)) '#(258 772))))
|
||||
|
||||
(test-case
|
||||
"vector: decode length as number before array"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 4 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint8 #:length uint8)) '#(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"vector: decode byte count as number before array"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 4 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint16be #:length uint8 #:count-bytes #t)) '#(258 772))))
|
||||
|
||||
(test-case
|
||||
"vector: decode length from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint8 #:length (λ _ 4))) '#(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"vector: decode byte count from function"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint16be #:length (λ _ 4) #:count-bytes #t)) '#(258 772))))
|
||||
|
||||
(test-case
|
||||
"vector: decode to the end of parent if no length given"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint8) (current-input-port) #:parent (mhash x:length-key 4 x:start-offset-key 0)) '#(1 2 3 4))))
|
||||
|
||||
(test-case
|
||||
"vector: decode to the end of the stream if parent exists, but its length is 0"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(check-equal? (decode (x:vector #:type uint8) (current-input-port) #:parent (mhash x:length-key 0 x:start-offset-key 0)) '#(1 2 3 4 5))))
|
||||
|
||||
(test-case
|
||||
"vector: decode to the end of the stream if no parent and length is given"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4))])
|
||||
(check-equal? (decode (x:vector #:type uint8)) '#(1 2 3 4 ))))
|
||||
|
||||
(test-case
|
||||
"vector: use array length"
|
||||
(check-equal? (size (x:vector #:type uint8 #:length 10) '#(1 2 3 4)) 4))
|
||||
|
||||
(test-case
|
||||
"vector: add size of length field before string"
|
||||
(check-equal? (size (x:vector #:type uint8 #:length uint8) '#(1 2 3 4)) 5))
|
||||
|
||||
(test-case
|
||||
"vector: use defined length if no value given"
|
||||
(check-equal? (size (x:vector #:type uint8 #:length 10)) 10))
|
||||
|
||||
(test-case
|
||||
"vector: encode using array length"
|
||||
(check-equal? (encode (x:vector #:type uint8 #:length 10) '#(1 2 3 4) #f) (bytes 1 2 3 4)))
|
||||
|
||||
(test-case
|
||||
"vector: encode with pre-encode"
|
||||
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 3 4 5))])
|
||||
(define xa (x:vector #:type uint8 #:length 4 #:pre-encode (λ (val) (vector-map (λ (x) (* 2 x)) val))))
|
||||
(check-equal? (encode xa '#(1 2 3 4) #f) (bytes 2 4 6 8))))
|
||||
|
||||
(test-case
|
||||
"vector: encode length as number before array"
|
||||
(check-equal? (encode (x:vector #:type uint8 #:length uint8) '#(1 2 3 4) #f) (bytes 4 1 2 3 4)))
|
||||
|
||||
(test-case
|
||||
"vector: add pointers after array if length is encoded at start"
|
||||
(check-equal? (encode (x:vector #:type (x:pointer #:offset-type uint8
|
||||
#:type uint8)
|
||||
#:length uint8) '#(1 2 3 4) #f) (bytes 4 5 6 7 8 1 2 3 4)))
|
@ -0,0 +1,40 @@
|
||||
#lang debug racket/base
|
||||
(require racket/class
|
||||
"base.rkt"
|
||||
"number.rkt"
|
||||
"util.rkt"
|
||||
"list.rkt"
|
||||
sugar/unstable/dict)
|
||||
(provide (all-defined-out))
|
||||
|
||||
(define x:vector%
|
||||
(class x:list%
|
||||
(super-new)
|
||||
|
||||
(define/override (pre-encode val)
|
||||
(unless (or (vector? val) (list? val))
|
||||
(raise-argument-error 'x:vector-encode "vector or list" val))
|
||||
(if (vector? val) (vector->list val) val))
|
||||
|
||||
(define/override (post-decode val) (list->vector val))))
|
||||
|
||||
(define (x:vector [type-arg #f] [len-arg #f] [length-type-arg 'count]
|
||||
#:type [type-kwarg #f]
|
||||
#:length [len-kwarg #f]
|
||||
#:count-bytes [count-bytes? #f]
|
||||
#:pre-encode [pre-proc #f]
|
||||
#:post-decode [post-proc #f]
|
||||
#:base-class [base-class x:vector%])
|
||||
(new (generate-subclass base-class pre-proc post-proc) [type (or type-arg type-kwarg)]
|
||||
[len (or len-arg len-kwarg)]
|
||||
[count-bytes? count-bytes?]))
|
||||
|
||||
(define (x:vector? x) (is-a? x x:vector%))
|
||||
|
||||
(module+ test
|
||||
(require rackunit)
|
||||
(check-equal? (decode (x:vector uint16be 3) #"ABCDEF") '#(16706 17220 17734))
|
||||
(check-equal? (encode (x:vector uint16be 3) '(16706 17220 17734) #f) #"ABCDEF")
|
||||
(check-equal? (encode (x:vector uint16be 3) '#(16706 17220 17734) #f) #"ABCDEF")
|
||||
(check-equal? (size (x:vector uint16be) '#(1 2 3)) 6)
|
||||
(check-equal? (size (x:vector doublebe) '#(1 2 3 4 5)) 40))
|
Loading…
Reference in New Issue