main
Matthew Butterick 6 years ago
parent c8af0c2cea
commit 677b41e833

@ -58,18 +58,26 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee
(d:dict-set! sdr '_currentOffset (- (pos port) (d:dict-ref sdr '_startOffset)))
sdr))
(define (sdr-to-hash sdr)
(for/hasheq ([(k v) (d:in-dict sdr)]
#:unless (memq k private-keys))
(values k v)))
(define-syntax-rule (decode/hash . ARGS)
(sdr-to-hash (decode . ARGS)))
(define (xstruct-decode 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
(define res
(let* ([sdr (_setup port parent len)] ; returns StructDictRes
[sdr (_parse-fields port sdr (xstruct-fields xs))])
sdr))
(let* ([res (post-decode xs res)]
#;[res (inner res post-decode res . args)])
(unless (d:dict? res) (raise-result-error 'xstruct-decode "dict" res))
res)))
(post-decode xs
(let* ([sdr (_setup port parent len)] ; returns StructDictRes
[sdr (_parse-fields port sdr (xstruct-fields xs))])
sdr)))
(unless (d:dict? res)
(raise-result-error 'xstruct-decode "dict" res))
res))
(define/finalize-size (xstruct-size xs [val #f] #:parent [parent-arg #f] [include-pointers #t])
(define parent (mhasheq 'parent parent-arg

@ -16,32 +16,27 @@ 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?
(dump (decode (+xstruct 'name (+xstring #:length uint8)
'age uint8)))
'((name . "roxyb") (age . 21)))))
(decode/hash (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(hasheq '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))
(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? (dump (decode struct))
'((name . "roxyb") (canDrink . #t) (age . 32)))))
(check-equal? (decode/hash struct)
(hasheq '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? (dump (decode struct))
'((name . "roxyb") (canDrink . #t) (age . 32)))))
(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))))
(test-case
"compute the correct size"
(check-equal? (size (+xstruct 'name (+xstring #:length uint8)
'age uint8)
(check-equal? (size (+xstruct 'name (+xstring #:length uint8) 'age uint8)
(hasheq 'name "roxyb" 'age 32)) 7))
(test-case
@ -57,15 +52,13 @@ https://github.com/mbutterick/restructure/blob/master/test/Struct.coffee
(test-case
"throw when getting non-fixed length size and no value is given"
(check-exn exn:fail:contract? (λ () (size (+xstruct 'name (+xstring #:length uint8)
'age uint8)))))
(check-exn exn:fail:contract? (λ () (size (+xstruct 'name (+xstring #:length uint8) 'age uint8)))))
(test-case
"encode objects to buffers"
(parameterize ([current-input-port (open-input-bytes #"\x05roxyb\x15")])
(check-equal? (dump (decode (+xstruct 'name (+xstring #:length uint8)
'age uint8)))
'((name . "roxyb") (age . 21)))))
(check-equal? (decode/hash (+xstruct 'name (+xstring #:length uint8) 'age uint8))
(hasheq 'name "roxyb" 'age 21))))
(test-case
"support pre-encode hook"

@ -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? (dump (decode vstruct)) '((version . 0) (age . 21) (name . "roxyb"))))
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb" 'age 21 'version 0)))
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "\x01\x0aroxyb 🤘\x15\x00"))])
(check-equal? (dump (decode vstruct)) '((version . 1) (age . 21) (name . "roxyb 🤘") (gender . 0))))))
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb 🤘" 'age 21 'version 1 'gender 0)))))
(test-case
"decode should throw for unknown version"
@ -49,13 +49,16 @@ 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? (dump (decode vstruct)) '((version . 0) (name . "roxyb") (age . 21) (alive . 1))))
(check-equal? (decode/hash vstruct) (hasheq '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? (dump (decode vstruct)) '((version . 1)
(gender . 0)
(name . "roxyb 🤘")
(age . 21)
(alive . 1))))))
(check-equal? (decode/hash vstruct) (hasheq 'name "roxyb 🤘"
'age 21
'version 1
'alive 1
'gender 0)))))
(test-case
"decode should support parent version key"
@ -67,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? (dump (decode vstruct #:parent (mhash 'version 0)))
'((version . 0) (age . 21) (name . "roxyb"))))
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "roxyb" 'age 21 'version 0)))
(parameterize ([current-input-port (open-input-bytes (string->bytes/utf-8 "\x0aroxyb 🤘\x15\x00"))])
(check-equal? (dump (decode vstruct #:parent (mhash 'version 1)))
'((version . 1) (age . 21) (name . "roxyb 🤘") (gender . 0))))))
(check-equal? (decode/hash vstruct #:parent (mhash 'version 1))
(hasheq 'name "roxyb 🤘" 'age 21 'version 1 'gender 0)))))
(test-case
"decode should support sub versioned structs"
@ -85,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? (dump (decode vstruct #:parent (mhash 'version 0)))
'((version . 0) (age . 21) (name . "roxyb"))))
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "roxyb" 'age 21 'version 0)))
(parameterize ([current-input-port (open-input-bytes #"\x01\x00\x05pasta")])
(check-equal? (dump (decode vstruct #:parent (mhash 'version 0)))
'((version . 0) (name . "pasta"))))
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "pasta" 'version 0)))
(parameterize ([current-input-port (open-input-bytes #"\x01\x01\x09ice cream\x01")])
(check-equal? (dump (decode vstruct #:parent (mhash 'version 0)))
'((version . 1) (isDessert . 1) (name . "ice cream"))))))
(check-equal? (decode/hash vstruct #:parent (mhash 'version 0))
(hasheq 'name "ice cream" 'isDessert 1 'version 1)))))
(test-case
"decode should support process hook"
@ -105,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? (dump (decode vstruct))
'((processed . "true") (version . 0) (age . 21) (name . "roxyb"))))))
(check-equal? (decode/hash vstruct)
(hasheq 'name "roxyb" 'processed "true" 'age 21 'version 0)))))
(test-case
"size should compute the correct size"
@ -134,9 +137,7 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
1 (dictify 'name (+xstring #:length uint8 #:encoding 'utf8)
'age uint8
'gender uint8)))])
(check-exn exn:fail:contract? (λ () (size vstruct (mhasheq 'name "roxyb"
'age 21
'version 5))))))
(check-exn exn:fail:contract? (λ () (size vstruct (mhasheq 'name "roxyb" 'age 21 'version 5))))))
(test-case
"size should support common header block"
@ -147,15 +148,8 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
0 (dictify 'name (+xstring #:length uint8 #:encoding 'ascii))
1 (dictify 'name (+xstring #:length uint8 #:encoding 'utf8)
'gender uint8)))])
(check-equal? (size struct (mhasheq 'name "roxyb"
'age 21
'alive 1
'version 0)) 9)
(check-equal? (size struct (mhasheq 'name "roxyb 🤘"
'gender 0
'age 21
'alive 1
'version 1)) 15)))
(check-equal? (size struct (mhasheq 'name "roxyb" 'age 21 'alive 1 'version 0)) 9)
(check-equal? (size struct (mhasheq 'name "roxyb 🤘" 'gender 0 'age 21 'alive 1 'version 1)) 15)))
(test-case
"size should compute the correct size with pointers"
@ -193,13 +187,8 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'age uint8
'gender uint8)))]
[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)
(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"))))
(test-case
@ -212,9 +201,7 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'age uint8
'gender uint8)))]
[op (open-output-bytes)])
(check-exn exn:fail:contract? (λ () (encode vstruct op (mhasheq 'name "roxyb"
'age 21
'version 5))))))
(check-exn exn:fail:contract? (λ () (encode vstruct op (mhasheq 'name "roxyb" 'age 21 'version 5))))))
(test-case
"encode should support common header block"
@ -226,15 +213,8 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
1 (dictify 'name (+xstring #:length uint8 #:encoding 'utf8)
'gender uint8)))]
[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)
(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"))))
(test-case
@ -248,10 +228,7 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'ptr (+xpointer #:offset-type uint8
#:type (+xstring uint8)))))]
[op (open-output-bytes)])
(encode vstruct (mhasheq 'version 1
'name "roxyb"
'age 21
'ptr "hello") op)
(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"))))
@ -266,10 +243,6 @@ https://github.com/mbutterick/restructure/blob/master/test/VersionedStruct.coffe
'gender uint8)))]
[stream (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)
(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"))))

@ -2,7 +2,7 @@
(require "helper.rkt" "struct.rkt"
racket/dict
sugar/unstable/dict)
(provide (all-defined-out))
(provide (all-defined-out) decode/hash)
#|
approximates

Loading…
Cancel
Save