main
Matthew Butterick 6 years ago
parent 79b3cbae73
commit 4c50c422a1

@ -11,22 +11,12 @@
[else (raise-argument-error '->input-port "byte string or input port" arg)]))
(define private-keys '(parent _startOffset _currentOffset _length))
(define (dump-mutable x)
(define (dict->mutable-hash x)
(define h (make-hasheq))
(for ([(k v) (in-dict (dump x))])
(for ([(k v) (in-dict x)])
(hash-set! h k v))
h)
(define (dump x)
(cond
[(input-port? x) (port->bytes x)]
[(output-port? x) (get-output-bytes x)]
[(dict? x) (for/hasheq ([(k v) (in-dict x)]
#:unless (memq k private-keys))
(values k v))]
[(list? x) (map dump x)]
[else x]))
(define (pos p [new-pos #f])
(when new-pos
(file-position p new-pos))

@ -57,10 +57,10 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee
(d:dict-set! sdr '_currentOffset (- (pos port) (d:dict-ref sdr '_startOffset)))
sdr))
(define-syntax-rule (decode/hash . ARGS)
(dump (xdecode . ARGS)))
(define (xstruct-decode . args)
(dict->mutable-hash (apply xstruct-xdecode args)))
(define (xstruct-decode xs [port-arg (current-input-port)] #:parent [parent #f] [len 0])
(define (xstruct-xdecode xs [port-arg (current-input-port)] #:parent [parent #f] [len 0])
(define port (->input-port port-arg))
(parameterize ([current-input-port port])
;; _setup and _parse-fields are separate to cooperate with VersionedStruct
@ -79,7 +79,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee
'pointerSize 0))
(define fields-size (for/sum ([(key type) (d:in-dict (xstruct-fields xs))]
#:when (xenomorphic? type))
(size type (and val (d:dict-ref val key)) #:parent parent)))
(size type (and val (d:dict-ref val key)) #:parent parent)))
(define pointers-size (if include-pointers (d:dict-ref parent 'pointerSize) 0))
(+ fields-size pointers-size))
@ -107,16 +107,16 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee
(d:dict-set! parent 'pointerOffset (+ (pos port) (xstruct-size xs val #:parent parent #f)))
(for ([(key type) (d:in-dict (xstruct-fields xs))])
(encode type (d:dict-ref val key) #:parent parent))
(encode type (d:dict-ref val key) #:parent parent))
(for ([ptr (in-list (d:dict-ref parent 'pointers))])
(encode (d:dict-ref ptr 'type) (d:dict-ref ptr 'val) #:parent (d:dict-ref ptr 'parent)))
(encode (d:dict-ref ptr 'type) (d:dict-ref ptr 'val) #:parent (d:dict-ref ptr 'parent)))
(unless port-arg (get-output-bytes port))))
(struct structish xbase () #:transparent)
(struct xstruct structish (fields) #:transparent #:mutable
#:methods gen:xenomorphic
[(define decode xstruct-decode)
(define xdecode xstruct-decode)
(define xdecode xstruct-xdecode)
(define encode xstruct-encode)
(define size xstruct-size)])
@ -125,9 +125,9 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee
(unless (even? (length args))
(raise-argument-error '+xstruct "equal keys and values" dicts))
(define fields (for/list ([kv (in-slice 2 args)])
(unless (symbol? (car kv))
(raise-argument-error '+xstruct "symbol" (car kv)))
(apply cons kv)))
(unless (symbol? (car kv))
(raise-argument-error '+xstruct "symbol" (car kv)))
(apply cons kv)))
(unless (d:dict? fields)
(raise-argument-error '+xstruct "dict" fields))
(xstruct fields))
@ -137,15 +137,15 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee
(define (random-pick xs) (list-ref xs (random (length xs))))
(check-exn exn:fail:contract? (λ () (+xstruct 42)))
(for ([i (in-range 20)])
;; make random structs and make sure we can round trip
(define field-types
(for/list ([i (in-range 40)])
(random-pick (list uint8 uint16be uint16le uint32be uint32le double))))
(define size-num-types
(for/sum ([num-type (in-list field-types)])
(size num-type)))
(define xs (+xstruct (for/list ([num-type (in-list field-types)])
(cons (gensym) num-type))))
(define bs (apply bytes (for/list ([i (in-range size-num-types)])
(random 256))))
(check-equal? (encode xs (decode xs bs) #f) bs)))
;; make random structs and make sure we can round trip
(define field-types
(for/list ([i (in-range 40)])
(random-pick (list uint8 uint16be uint16le uint32be uint32le double))))
(define size-num-types
(for/sum ([num-type (in-list field-types)])
(size num-type)))
(define xs (+xstruct (for/list ([num-type (in-list field-types)])
(cons (gensym) num-type))))
(define bs (apply bytes (for/list ([i (in-range size-num-types)])
(random 256))))
(check-equal? (encode xs (decode xs bs) #f) bs)))

@ -46,7 +46,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Enum.coffee
(encode e "bar")
(encode e "baz")
(encode e "foo")
(check-equal? (dump (current-output-port)) (bytes 1 2 0))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 1 2 0))))
(test-case
"encode should encode with pre-encode"
@ -55,7 +55,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Enum.coffee
(encode e "bar")
(encode e "baz")
(encode e "foo")
(check-equal? (dump (current-output-port)) (bytes 0 0 0))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 0 0 0))))
(test-case
"should throw on unknown option"

@ -15,7 +15,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Number.coffee
(let ([port (open-output-bytes)])
(encode uint8 #xab port)
(encode uint8 #xff port)
(check-equal? (dump port) (bytes #xab #xff))))
(check-equal? (get-output-bytes port) (bytes #xab #xff))))
(test-case
"uint8: decode with post-decode, size, encode with pre-encode"
@ -29,7 +29,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Number.coffee
(set-pre-encode! myuint8 (λ (b) #xcc))
(encode myuint8 #xab port)
(encode myuint8 #xff port)
(check-equal? (dump port) (bytes #xcc #xcc))))
(check-equal? (get-output-bytes port) (bytes #xcc #xcc))))
(test-case
"uint16 is the same endianness as the platform"
@ -89,7 +89,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Number.coffee
(let ([port (open-output-bytes)])
(encode int8 127 port)
(encode int8 -1 port)
(check-equal? (dump port) (bytes #x7f #xff))))
(check-equal? (get-output-bytes port) (bytes #x7f #xff))))
(test-case
"int32 is the same endianness as the platform"
@ -102,7 +102,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Number.coffee
(check-equal? (size int16be) 2)
(let ([port (open-output-bytes)])
(encode int16be -85 port)
(check-equal? (dump port) (bytes #xff #xab))))
(check-equal? (get-output-bytes port) (bytes #xff #xab))))
(test-case
"int16le: decode, size, encode"

@ -77,7 +77,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Optional.coffee
(parameterize ([current-output-port (open-output-bytes)])
(define optional (+xoptional #:type uint8 #:condition #f))
(encode optional 128)
(check-equal? (dump (current-output-port)) (bytes))))
(check-equal? (get-output-bytes (current-output-port)) (bytes))))
(test-case
"encode with pre-encode"
@ -85,32 +85,32 @@ https://github.com/mbutterick/restructure/blob/master/test/Optional.coffee
(define optional (+xoptional #:type uint8))
(set-pre-encode! optional (λ (val) 42))
(encode optional 128)
(check-equal? (dump (current-output-port)) (bytes 42))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 42))))
(test-case
"encode should not encode when condition is a function and falsy"
(parameterize ([current-output-port (open-output-bytes)])
(define optional (+xoptional #:type uint8 #:condition (λ _ #f)))
(encode optional 128)
(check-equal? (dump (current-output-port)) (bytes))))
(check-equal? (get-output-bytes (current-output-port)) (bytes))))
(test-case
"encode should encode when condition is omitted"
(parameterize ([current-output-port (open-output-bytes)])
(define optional (+xoptional #:type uint8))
(encode optional 128)
(check-equal? (dump (current-output-port)) (bytes 128))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 128))))
(test-case
"encode should encode when condition is truthy"
(parameterize ([current-output-port (open-output-bytes)])
(define optional (+xoptional #:type uint8 #:condition #t))
(encode optional 128)
(check-equal? (dump (current-output-port)) (bytes 128))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 128))))
(test-case
"encode should encode when condition is a function and truthy"
(parameterize ([current-output-port (open-output-bytes)])
(define optional (+xoptional #:type uint8 #:condition (λ _ #t)))
(encode optional 128)
(check-equal? (dump (current-output-port)) (bytes 128))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 128))))

@ -52,7 +52,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
(test-case
"decode should support decoding pointers lazily"
(parameterize ([current-input-port (open-input-bytes (bytes 1 53))])
(define res (decode (+xstruct 'ptr (+xpointer #:lazy #t))))
(define res (xdecode (+xstruct 'ptr (+xpointer #:lazy #t))))
(check-true (promise? (dict-ref (struct-dict-res-_kv res) 'ptr)))
(check-equal? (dict-ref res 'ptr) 53)))
@ -104,7 +104,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
'pointers null))
(encode (+xpointer) #f #:parent parent)
(check-equal? (dict-ref parent 'pointerSize) 0)
(check-equal? (dump (current-output-port)) (bytes 0))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 0))))
(test-case
"encode should handle local offsets"
@ -118,7 +118,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
(check-equal? (dict-ref parent 'pointers) (list (mhasheq 'type uint8
'val 10
'parent parent)))
(check-equal? (dump (current-output-port)) (bytes 1))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 1))))
(test-case
"encode should handle immediate offsets"
@ -132,7 +132,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
(check-equal? (dict-ref parent 'pointers) (list (mhasheq 'type uint8
'val 10
'parent parent)))
(check-equal? (dump (current-output-port)) (bytes 0))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 0))))
(test-case
"encode should handle offsets relative to parent"
@ -146,7 +146,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
(check-equal? (dict-ref (dict-ref parent 'parent) 'pointers) (list (mhasheq 'type uint8
'val 10
'parent parent)))
(check-equal? (dump (current-output-port)) (bytes 2))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 2))))
(test-case
"encode should handle global offsets"
@ -163,7 +163,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
(list (mhasheq 'type uint8
'val 10
'parent parent)))
(check-equal? (dump (current-output-port)) (bytes 5))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 5))))
(test-case
"encode should support void pointers"
@ -177,7 +177,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Pointer.coffee
(check-equal? (dict-ref parent 'pointers) (list (mhasheq 'type uint8
'val 55
'parent parent)))
(check-equal? (dump (current-output-port)) (bytes 1))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 1))))
(test-case
"encode should throw if not a void pointer instance"

@ -37,7 +37,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Reserved.coffee
(parameterize ([current-output-port (open-output-bytes)])
(define reserved (+xreserved uint16be))
(encode reserved #f)
(check-equal? (dump (current-output-port)) (bytes 0 0))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 0 0))))
(test-case
"should encode with pre-encode"
@ -45,4 +45,4 @@ https://github.com/mbutterick/restructure/blob/master/test/Reserved.coffee
(define reserved (+xreserved uint32be))
(set-pre-encode! reserved (λ (val) 42))
(encode reserved #f)
(check-equal? (dump (current-output-port)) (bytes 0 0 0 0))))
(check-equal? (get-output-bytes (current-output-port)) (bytes 0 0 0 0))))

@ -83,7 +83,7 @@ https://github.com/mbutterick/restructure/blob/master/test/String.coffee
"encode using string length"
(parameterize ([current-output-port (open-output-bytes)])
(encode (+xstring 7) "testing")
(check-equal? (dump (current-output-port)) #"testing")))
(check-equal? (get-output-bytes (current-output-port)) #"testing")))
(test-case
"encode using string length and pre-encode"
@ -91,34 +91,34 @@ https://github.com/mbutterick/restructure/blob/master/test/String.coffee
(define xs (+xstring 7))
(set-pre-encode! xs (compose1 list->string reverse string->list))
(encode xs "testing")
(check-equal? (dump (current-output-port)) #"gnitset")))
(check-equal? (get-output-bytes (current-output-port)) #"gnitset")))
(test-case
"encode length as number before string"
(parameterize ([current-output-port (open-output-bytes)])
(encode (+xstring uint8) "testing")
(check-equal? (dump (current-output-port)) #"\x07testing")))
(check-equal? (get-output-bytes (current-output-port)) #"\x07testing")))
(test-case
"encode length as number before string utf8"
(parameterize ([current-output-port (open-output-bytes)])
(encode (+xstring uint8 'utf8) "testing 😜")
(check-equal? (dump (current-output-port)) (string->bytes/utf-8 "\x0ctesting 😜"))))
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "\x0ctesting 😜"))))
(test-case
"encode utf8"
(parameterize ([current-output-port (open-output-bytes)])
(encode (+xstring 4 'utf8) "🍻" )
(check-equal? (dump (current-output-port)) (string->bytes/utf-8 "🍻"))))
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "🍻"))))
(test-case
"encode encoding computed from function"
(parameterize ([current-output-port (open-output-bytes)])
(encode (+xstring 4 (λ _ 'utf8)) "🍻")
(check-equal? (dump (current-output-port)) (string->bytes/utf-8 "🍻"))))
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "🍻"))))
(test-case
"encode null-terminated string"
(parameterize ([current-output-port (open-output-bytes)])
(encode (+xstring #f 'utf8) "🍻" )
(check-equal? (dump (current-output-port)) (string->bytes/utf-8 "🍻\x00"))))
(check-equal? (get-output-bytes (current-output-port)) (string->bytes/utf-8 "🍻\x00"))))

@ -16,23 +16,23 @@ https://github.com/mbutterick/restructure/blob/master/test/Struct.coffee
"decode into an object"
(parameterize ([current-input-port (open-input-bytes #"\x05roxyb\x15")])
(check-equal?
(decode/hash (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(hasheq 'name "roxyb" 'age 21))))
(decode (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(mhasheq 'name "roxyb" 'age 21))))
(test-case
"decode with process hook"
(parameterize ([current-input-port (open-input-bytes #"\x05roxyb\x20")])
(define struct (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(set-post-decode! struct (λ (o . _) (dict-set! o 'canDrink (>= (dict-ref o 'age) 21)) o))
(check-equal? (decode/hash struct)
(hasheq 'name "roxyb" 'age 32 'canDrink #t))))
(check-equal? (decode struct)
(mhasheq 'name "roxyb" 'age 32 'canDrink #t))))
(test-case
"decode supports function keys"
(parameterize ([current-input-port (open-input-bytes #"\x05roxyb\x20")])
(define struct (+xstruct 'name (+xstring #:length uint8) 'age uint8 'canDrink (λ (o) (>= (dict-ref o 'age) 21))))
(check-equal? (decode/hash struct)
(hasheq 'name "roxyb" 'age 32 'canDrink #t))))
(check-equal? (decode struct)
(mhasheq 'name "roxyb" 'age 32 'canDrink #t))))
(test-case
"compute the correct size"
@ -57,8 +57,8 @@ https://github.com/mbutterick/restructure/blob/master/test/Struct.coffee
(test-case
"encode objects to buffers"
(parameterize ([current-input-port (open-input-bytes #"\x05roxyb\x15")])
(check-equal? (decode/hash (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(hasheq 'name "roxyb" 'age 21))))
(check-equal? (decode (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(mhasheq 'name "roxyb" 'age 21))))
(test-case
"support pre-encode hook"
@ -68,7 +68,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Struct.coffee
'age uint8))
(set-pre-encode! struct (λ (val) (dict-set! val 'nameLength (string-length (dict-ref val 'name))) val))
(encode struct (mhasheq 'name "roxyb" 'age 21))
(check-equal? (dump (current-output-port)) #"\x05roxyb\x15")))
(check-equal? (get-output-bytes (current-output-port)) #"\x05roxyb\x15")))
(test-case
"encode pointer data after structure"
@ -77,4 +77,4 @@ https://github.com/mbutterick/restructure/blob/master/test/Struct.coffee
'age uint8
'ptr (+xpointer #:type (+xstring #:length uint8))))
(encode struct (hasheq 'name "roxyb" 'age 21 'ptr "hello"))
(check-equal? (dump (current-output-port)) #"\x05roxyb\x15\x08\x05hello")))
(check-equal? (get-output-bytes (current-output-port)) #"\x05roxyb\x15\x08\x05hello")))

@ -23,9 +23,9 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'age uint8
'gender uint8)))])
(parameterize ([current-input-port (open-input-bytes #"\x00\x05roxyb\x15")])
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb" 'age 21 'version 0)))
(check-equal? (decode vstruct) (mhasheq 'name "roxyb" 'age 21 'version 0)))
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "\x01\x0aroxyb 🤘\x15\x00"))])
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb 🤘" 'age 21 'version 1 'gender 0)))))
(check-equal? (decode vstruct) (mhasheq 'name "roxyb 🤘" 'age 21 'version 1 'gender 0)))))
(test-case
"decode should throw for unknown version"
@ -49,12 +49,12 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
1 (dictify 'name (+xstring #:length uint8 #:encoding 'utf8)
'gender uint8)))])
(parameterize ([current-input-port (open-input-bytes #"\x00\x15\x01\x05roxyb")])
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb"
(check-equal? (decode vstruct) (mhasheq 'name "roxyb"
'age 21
'alive 1
'version 0)))
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "\x01\x15\x01\x0aroxyb 🤘\x00"))])
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb 🤘"
(check-equal? (decode vstruct) (mhasheq 'name "roxyb 🤘"
'age 21
'version 1
'alive 1
@ -70,11 +70,11 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'age uint8
'gender uint8)))])
(parameterize ([current-input-port (open-input-bytes #"\x05roxyb\x15")])
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "roxyb" 'age 21 'version 0)))
(check-equal? (dict->mutable-hash (xdecode vstruct #:parent (mhash 'version 0)))
(mhasheq 'name "roxyb" 'age 21 'version 0)))
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "\x0aroxyb 🤘\x15\x00"))])
(check-equal? (decode/hash vstruct #:parent (mhash 'version 1))
(hasheq 'name "roxyb 🤘" 'age 21 'version 1 'gender 0)))))
(check-equal? (dict->mutable-hash (xdecode vstruct #:parent (mhash 'version 1)))
(mhasheq 'name "roxyb 🤘" 'age 21 'version 1 'gender 0)))))
(test-case
"decode should support sub versioned structs"
@ -88,14 +88,14 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
1 (dictify 'name (+xstring uint8)
'isDessert uint8)))))])
(parameterize ([current-input-port (open-input-bytes #"\x00\x05roxyb\x15")])
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "roxyb" 'age 21 'version 0)))
(check-equal? (dict->mutable-hash (xdecode vstruct #:parent (mhash 'version 0)))
(mhasheq 'name "roxyb" 'age 21 'version 0)))
(parameterize ([current-input-port (open-input-bytes #"\x01\x00\x05pasta")])
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "pasta" 'version 0)))
(check-equal? (dict->mutable-hash (xdecode vstruct #:parent (mhash 'version 0)))
(mhasheq 'name "pasta" 'version 0)))
(parameterize ([current-input-port (open-input-bytes #"\x01\x01\x09ice cream\x01")])
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "ice cream" 'isDessert 1 'version 1)))))
(check-equal? (dict->mutable-hash (xdecode vstruct #:parent (mhash 'version 0)))
(mhasheq 'name "ice cream" 'isDessert 1 'version 1)))))
(test-case
"decode should support process hook"
@ -108,8 +108,8 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'gender uint8)))])
(set-post-decode! vstruct (λ (val) (dict-set! val 'processed "true") val))
(parameterize ([current-input-port (open-input-bytes #"\x00\x05roxyb\x15")])
(check-equal? (decode/hash vstruct)
(hasheq 'name "roxyb" 'processed "true" 'age 21 'version 0)))))
(check-equal? (decode vstruct)
(mhasheq 'name "roxyb" 'processed "true" 'age 21 'version 0)))))
(test-case
"size should compute the correct size"
@ -189,7 +189,7 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
[op (open-output-bytes)])
(encode vstruct (mhasheq 'name "roxyb" 'age 21 'version 0) op)
(encode vstruct (mhasheq 'name "roxyb 🤘" 'age 21 'gender 0 'version 1) op)
(check-equal? (dump op) (string->bytes/utf-8 "\x00\x05roxyb\x15\x01\x0aroxyb 🤘\x15\x00"))))
(check-equal? (get-output-bytes op) (string->bytes/utf-8 "\x00\x05roxyb\x15\x01\x0aroxyb 🤘\x15\x00"))))
(test-case
"encode should throw for unknown version"
@ -215,7 +215,7 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
[op (open-output-bytes)])
(encode vstruct (mhasheq 'name "roxyb" 'age 21 'alive 1 'version 0) op)
(encode vstruct (mhasheq 'name "roxyb 🤘" 'gender 0 'age 21 'alive 1 'version 1) op)
(check-equal? (dump op) (string->bytes/utf-8 "\x00\x15\x01\x05roxyb\x01\x15\x01\x0aroxyb 🤘\x00"))))
(check-equal? (get-output-bytes op) (string->bytes/utf-8 "\x00\x15\x01\x05roxyb\x01\x15\x01\x0aroxyb 🤘\x00"))))
(test-case
"encode should encode pointer data after structure"
@ -230,7 +230,7 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
[op (open-output-bytes)])
(encode vstruct (mhasheq 'version 1 'name "roxyb" 'age 21 'ptr "hello") op)
(check-equal? (dump op) (string->bytes/utf-8 "\x01\x05roxyb\x15\x09\x05hello"))))
(check-equal? (get-output-bytes op) (string->bytes/utf-8 "\x01\x05roxyb\x15\x09\x05hello"))))
(test-case
"encode should support preEncode hook"
@ -241,8 +241,8 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
1 (dictify 'name (+xstring #:length uint8 #:encoding 'utf8)
'age uint8
'gender uint8)))]
[stream (open-output-bytes)])
[op (open-output-bytes)])
(set-pre-encode! vstruct (λ (val) (dict-set! val 'version (if (dict-ref val 'gender #f) 1 0)) val))
(encode vstruct (mhasheq 'name "roxyb" 'age 21 'version 0) stream)
(encode vstruct (mhasheq 'name "roxyb 🤘" 'age 21 'gender 0) stream)
(check-equal? (dump stream) (string->bytes/utf-8 "\x00\x05roxyb\x15\x01\x0aroxyb 🤘\x15\x00"))))
(encode vstruct (mhasheq 'name "roxyb" 'age 21 'version 0) op)
(encode vstruct (mhasheq 'name "roxyb 🤘" 'age 21 'gender 0) op)
(check-equal? (get-output-bytes op) (string->bytes/utf-8 "\x00\x05roxyb\x15\x01\x0aroxyb 🤘\x15\x00"))))

@ -2,14 +2,17 @@
(require "helper.rkt" "struct.rkt"
racket/dict
sugar/unstable/dict)
(provide (all-defined-out) decode/hash)
(provide (all-defined-out))
#|
approximates
https://github.com/mbutterick/restructure/blob/master/src/VersionedStruct.coffee
|#
(define/post-decode (xversioned-struct-decode xvs [port-arg (current-input-port)] #:parent [parent #f] [length 0])
(define (xversioned-struct-decode . args)
(dict->mutable-hash (apply xversioned-struct-xdecode args)))
(define/post-decode (xversioned-struct-xdecode xvs [port-arg (current-input-port)] #:parent [parent #f] [length 0])
(define port (->input-port port-arg))
(define res (_setup port parent length))
@ -89,7 +92,7 @@ https://github.com/mbutterick/restructure/blob/master/src/VersionedStruct.coffee
(struct xversioned-struct structish (type versions version-getter version-setter) #:transparent #:mutable
#:methods gen:xenomorphic
[(define decode xversioned-struct-decode)
(define xdecode xversioned-struct-decode)
(define xdecode xversioned-struct-xdecode)
(define encode xversioned-struct-encode)
(define size xversioned-struct-size)])

Loading…
Cancel
Save