From 677b41e83318e177db6102631c13a33f5c601e27 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Thu, 13 Dec 2018 21:53:45 -0800 Subject: [PATCH] hashier --- xenomorph/xenomorph/redo/struct.rkt | 22 +++-- xenomorph/xenomorph/redo/test/struct-test.rkt | 31 +++--- .../redo/test/versioned-struct-test.rkt | 95 +++++++------------ xenomorph/xenomorph/redo/versioned-struct.rkt | 2 +- 4 files changed, 62 insertions(+), 88 deletions(-) diff --git a/xenomorph/xenomorph/redo/struct.rkt b/xenomorph/xenomorph/redo/struct.rkt index 7f0c688b..0457409f 100644 --- a/xenomorph/xenomorph/redo/struct.rkt +++ b/xenomorph/xenomorph/redo/struct.rkt @@ -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 diff --git a/xenomorph/xenomorph/redo/test/struct-test.rkt b/xenomorph/xenomorph/redo/test/struct-test.rkt index 7f481a3f..22d6c2e8 100644 --- a/xenomorph/xenomorph/redo/test/struct-test.rkt +++ b/xenomorph/xenomorph/redo/test/struct-test.rkt @@ -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" diff --git a/xenomorph/xenomorph/redo/test/versioned-struct-test.rkt b/xenomorph/xenomorph/redo/test/versioned-struct-test.rkt index 3fefb874..61de216b 100644 --- a/xenomorph/xenomorph/redo/test/versioned-struct-test.rkt +++ b/xenomorph/xenomorph/redo/test/versioned-struct-test.rkt @@ -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")))) \ No newline at end of file diff --git a/xenomorph/xenomorph/redo/versioned-struct.rkt b/xenomorph/xenomorph/redo/versioned-struct.rkt index b3ef3c81..7ed56e59 100644 --- a/xenomorph/xenomorph/redo/versioned-struct.rkt +++ b/xenomorph/xenomorph/redo/versioned-struct.rkt @@ -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