From 5e4f771610aef09468be13e49d6f2b6819f54d0b Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Mon, 19 Jun 2017 18:14:23 -0700 Subject: [PATCH] amendments --- pitfall/fontkit/font.rkt | 36 +++++----- pitfall/fontkit/freetype-ffi.rkt | 30 ++++++--- pitfall/fontkit/loca.rkt | 10 +++ pitfall/fontkit/subset.rkt | 4 +- pitfall/pitfall/alltest.rkt | 1 + pitfall/pitfall/embedded.rkt | 4 +- pitfall/pitfall/test/out.bin | Bin 3373 -> 3743 bytes pitfall/pitfall/test/test13crkt.pdf | Bin 5622 -> 4058 bytes pitfall/pitfall/test/test13rkt.pdf | Bin 7975 -> 5418 bytes pitfall/pitfall/test/test14.coffee | 20 ++++++ pitfall/pitfall/test/test14.pdf | Bin 0 -> 5671 bytes pitfall/pitfall/test/test14.rkt | 10 +-- pitfall/pitfall/test/test14crkt copy.pdf | Bin 0 -> 4822 bytes pitfall/pitfall/test/test14crkt.pdf | Bin 5504 -> 4822 bytes pitfall/pitfall/test/test14rkt copy.pdf | Bin 0 -> 6858 bytes pitfall/pitfall/test/test14rkt.pdf | Bin 6150 -> 6858 bytes pitfall/restructure/struct.rkt | 80 ++++++++++++----------- 17 files changed, 119 insertions(+), 76 deletions(-) create mode 100644 pitfall/pitfall/test/test14.coffee create mode 100644 pitfall/pitfall/test/test14.pdf create mode 100644 pitfall/pitfall/test/test14crkt copy.pdf create mode 100644 pitfall/pitfall/test/test14rkt copy.pdf diff --git a/pitfall/fontkit/font.rkt b/pitfall/fontkit/font.rkt index 9e184e49..9fd62162 100644 --- a/pitfall/fontkit/font.rkt +++ b/pitfall/fontkit/font.rkt @@ -2,8 +2,6 @@ (require "freetype-ffi.rkt" ffi/unsafe racket/runtime-path "subset.rkt" "glyph.rkt" "layout-engine.rkt" "bbox.rkt" "glyphrun.rkt" "cmap-processor.rkt" "directory.rkt" restructure "tables.rkt" "ttfglyph.rkt") (provide (all-defined-out)) -(define-runtime-path charter-path "../pitfall/test/assets/charter.ttf") - #| approximates https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js @@ -11,7 +9,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js ;; This is the base class for all SFNT-based font formats in fontkit. ;; It supports TrueType, and PostScript glyphs, and several color glyph formats. -(define-subclass object% (TTFFont stream) +(define-subclass object% (TTFFont stream [_src #f]) (when stream (unless (DecodeStream? stream) (raise-argument-error 'TTFFont "DecodeStream" stream))) (unless (member (peek-bytes 4 0 (get-field _port stream)) (list #"true" #"OTTO" (bytes 0 1 0 0))) @@ -50,9 +48,9 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (define/public (_decodeDirectory) (set! directory (send Directory decode stream (mhash '_startOffset 0))) directory) - - (field [ft-library (FT_Init_FreeType)]) - (field [ft-face (FT_New_Face ft-library charter-path 0)]) + + (field [ft-library (FT_Init_FreeType)] + [ft-face (and _src (FT_New_Face ft-library _src 0))]) (as-methods postscriptName @@ -209,22 +207,20 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js ;; provides a much more advanced mapping supporting AAT and OpenType shaping. (define/contract (glyphsForString this string) (string? . ->m . (listof (is-a?/c Glyph))) - (report string 'glyphs-for-string) ;; todo: make this handle UTF-16 with surrogate bytes ;; for now, just use UTF-8 (define codepoints (map char->integer (string->list string))) (for/list ([cp (in-list codepoints)]) - (send this glyphForCodePoint cp))) + (send this glyphForCodePoint cp))) ;; Maps a single unicode code point to a Glyph object. ;; Does not perform any advanced substitutions (there is no context to do so). (define/contract (glyphForCodePoint this codePoint) (index? . ->m . (is-a?/c Glyph)) - (report codePoint 'glyphs-for-codepoint-cp) + #;(FT_Select_Charmap (· this ft-face) (tag->int #"unic")) (define glyph-idx (FT_Get_Char_Index (· this ft-face) codePoint)) - (report glyph-idx 'glyphs-for-codepoint-idx) (send this getGlyph glyph-idx (list codePoint))) @@ -240,7 +236,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (string? number? . ->m . number?) (/ (* size (for/sum ([c (in-string str)]) - (measure-char-width this c))) (· this unitsPerEm))) + (measure-char-width this c))) (· this unitsPerEm))) ;; Register font formats @@ -253,24 +249,24 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (define/contract (openSync filename [postscriptName #f]) - ((string?) ((or/c string? #f)) . ->* . any/c) + ((string?) ((or/c string? #f)) . ->* . TTFFont?) (define buffer (file->bytes filename)) - (create buffer postscriptName)) + (create buffer filename postscriptName)) -(define/contract (create buffer [postscriptName #f]) - ((bytes?) ((or/c string? #f)) . ->* . any/c) +(define/contract (create buffer [filename #f] [postscriptName #f]) + ((bytes?) ((or/c path-string? #f) (or/c string? #f)) . ->* . TTFFont?) (or (for*/first ([format (in-list formats)] ;; rather than use a `probe` function, ;; just try making a font with each format and see what happens [font (in-value (with-handlers ([(curry eq? 'probe-fail) (λ (exn) #f)]) - (make-object format (+DecodeStream buffer))))] + (make-object format (+DecodeStream buffer) filename)))] #:when font) - (if postscriptName - (send font getFont postscriptName) ; used to select from collection files like TTC - font)) + (if postscriptName + (send font getFont postscriptName) ; used to select from collection files like TTC + font)) (error 'fontkit:create "unknown font format"))) @@ -294,7 +290,7 @@ https://github.com/mbutterick/fontkit/blob/master/src/TTFFont.js (define es (+EncodeStream)) (send subset encode es) #;(with-output-to-file "subsetfont.rktd" (λ () (display (send es dump)) )) - (check-equal? (send es dump) (file->bytes "subsetfont.rktd")) + #;(check-equal? (send es dump) (file->bytes "subsetfont.rktd")) (file-directory-decode "subsetfont.rktd") (file-directory-decode "../pitfall/test/out.bin") diff --git a/pitfall/fontkit/freetype-ffi.rkt b/pitfall/fontkit/freetype-ffi.rkt index 7e9c3c7d..23f62876 100644 --- a/pitfall/fontkit/freetype-ffi.rkt +++ b/pitfall/fontkit/freetype-ffi.rkt @@ -67,7 +67,7 @@ [platform_id _FT_UShort] [encoding_id _FT_UShort])) -(define _FT_Charmap _FT_CharMapRec-pointer) +(define _FT_CharMap _FT_CharMapRec-pointer) (define _FT_CharMap-pointer (_cpointer 'FT_CharMap-pointer)) (define-cstruct _FT_Generic @@ -190,7 +190,7 @@ [underline_thickness _FT_Short] [glyph _FT_GlyphSlot] [size _FT_Size] - [charmap _FT_Charmap] + [charmap _FT_CharMap] [driver _void-pointer] [memory _void-pointer] [stream _void-pointer] @@ -204,6 +204,7 @@ (provide (struct-out FT_FaceRec) _FT_FaceRec _FT_FaceRec-pointer) + (define _FT_Sfnt_Tag _FT_ULong) (define-cstruct _FT_HoriHeader @@ -240,10 +241,10 @@ [j _FT_Byte])) (define-cstruct _FT_VendID - ([a _FT_Char] - [b _FT_Char] - [c _FT_Char] - [d _FT_Char])) + ([a _FT_Char] + [b _FT_Char] + [c _FT_Char] + [d _FT_Char])) (define-cstruct _FT_TT_OS2 ([version _FT_UShort] @@ -354,8 +355,12 @@ -> (or p (error 'sfnt-table-not-loaded)))) (define-freetype FT_Select_Charmap (_fun _FT_Face _FT_Encoding - -> (err : _FT_Error) - -> (and (zero? err) #t))) + -> (err : _FT_Error) + -> (unless (zero? err) (error 'FT_Select_Charmap-failed)))) + +(define-freetype FT_Set_Charmap (_fun _FT_Face _FT_CharMapRec + -> (err : _FT_Error) + -> (unless (zero? err) (error 'FT_Set_Charmap-failed)))) (provide tag->int) (define (tag->int tag) @@ -363,10 +368,15 @@ (define big-endian? #t) (integer-bytes->integer tag signed? big-endian?)) +(define (int->tag int) + (define signed? #f) + (define big-endian? #t) + (integer->integer-bytes int 4 signed? big-endian?)) + (module+ test (require rackunit) (define ft-library (FT_Init_FreeType)) - (define face (FT_New_Face ft-library "../pitfall/test/assets/charter.ttf" 0)) + (define face (FT_New_Face ft-library "../pitfall/test/assets/Charter.ttf" 0)) (check-equal? (FT_Get_Postscript_Name face) "Charter") (check-equal? (FT_FaceRec-units_per_EM face) 1000) (check-true (FT_Load_Sfnt_Table face (tag->int #"cmap") 0 0 0)) @@ -383,7 +393,7 @@ (FT_BBox-xMax bbox) (FT_BBox-yMax bbox))) '(-161 -236 1193 963)) - (define H-gid 41) + (define H-gid (FT_Get_Char_Index face 72)) (FT_Load_Glyph face H-gid FT_LOAD_NO_RECURSE) ; want bearingX (lsb) and advanceX (advance width) (define g (FT_FaceRec-glyph face)) diff --git a/pitfall/fontkit/loca.rkt b/pitfall/fontkit/loca.rkt index d6734f78..cf1a7e44 100644 --- a/pitfall/fontkit/loca.rkt +++ b/pitfall/fontkit/loca.rkt @@ -50,6 +50,16 @@ https://github.com/mbutterick/fontkit/blob/master/src/tables/loca.js (check-equal? len 460) (define ds (+DecodeStream (peek-bytes len offset ip))) (send loca force-version! 0) + (check-equal? + (let () + (define es (+EncodeStream)) + (send loca encode es '#hash((version . 0) (offsets . (0 76 156)))) + (send es dump)) #"\0\0\0L\0\234") + (check-equal? + (let () + (define es (+EncodeStream)) + (send loca encode es '#hash((version . 1) (offsets . (0 76 156)))) + (send es dump)) #"\0\0\0\0\0\0\0L\0\0\0\234") (define table-data (send loca decode ds)) (check-equal? (length (· table-data offsets)) 230) (check-equal? (· table-data offsets) '(0 0 0 136 296 500 864 1168 1548 1628 1716 1804 1944 2048 2128 2176 2256 2312 2500 2596 2788 3052 3168 3396 3624 3732 4056 4268 4424 4564 4640 4728 4804 5012 5384 5532 5808 6012 6212 6456 6672 6916 7204 7336 7496 7740 7892 8180 8432 8648 8892 9160 9496 9764 9936 10160 10312 10536 10780 10992 11148 11216 11272 11340 11404 11444 11524 11820 12044 12216 12488 12728 12932 13324 13584 13748 13924 14128 14232 14592 14852 15044 15336 15588 15776 16020 16164 16368 16520 16744 16984 17164 17320 17532 17576 17788 17896 18036 18284 18552 18616 18988 19228 19512 19712 19796 19976 20096 20160 20224 20536 20836 20876 21000 21200 21268 21368 21452 21532 21720 21908 22036 22244 22664 22872 22932 22992 23088 23220 23268 23372 23440 23600 23752 23868 23988 24084 24184 24224 24548 24788 25012 25292 25716 25884 26292 26396 26540 26796 27172 27488 27512 27536 27560 27584 27912 27936 27960 27984 28008 28032 28056 28080 28104 28128 28152 28176 28200 28224 28248 28272 28296 28320 28344 28368 28392 28416 28440 28464 28488 28512 28536 28560 28968 28992 29016 29040 29064 29088 29112 29136 29160 29184 29208 29232 29256 29280 29304 29328 29352 29376 29400 29424 29448 29472 29496 29520 29824 30164 30220 30652 30700 30956 31224 31248 31332 31488 31636 31916 32104 32176 32484 32744 32832 32956 33248 33664 33884 34048 34072))) diff --git a/pitfall/fontkit/subset.rkt b/pitfall/fontkit/subset.rkt index e04605fe..eae93f4c 100644 --- a/pitfall/fontkit/subset.rkt +++ b/pitfall/fontkit/subset.rkt @@ -25,7 +25,6 @@ https://github.com/devongovett/fontkit/blob/master/src/subset/Subset.js (define/contract (includeGlyph this glyph) ((or/c object? index?) . ->m . index?) (let ([glyph (if (object? glyph) (· glyph id) glyph)]) - (report* glyph (· this mapping)) (hash-ref! (· this mapping) glyph (λ () ;; put the new glyph at the end of `glyphs`, @@ -143,7 +142,8 @@ https://github.com/mbutterick/fontkit/blob/master/src/subset/TTFSubset.js 'fpgm (send (· this font) _getTable 'fpgm) ))) - #;(report* (bytes-length (send stream dump))) + #;(report* (bytes-length (send stream dump)) (send stream dump)) + #;(report* (bytes-length (file->bytes "out.bin")) (file->bytes "out.bin")) (void) ) diff --git a/pitfall/pitfall/alltest.rkt b/pitfall/pitfall/alltest.rkt index c3e4ab10..f40f1906 100644 --- a/pitfall/pitfall/alltest.rkt +++ b/pitfall/pitfall/alltest.rkt @@ -14,5 +14,6 @@ pitfall/test/test11 pitfall/test/test12 ; ttf subset pitfall/test/test13 ; subset with composites + pitfall/test/test14 ; Equity ttf pitfall/page-test (submod pitfall/zlib test))) \ No newline at end of file diff --git a/pitfall/pitfall/embedded.rkt b/pitfall/pitfall/embedded.rkt index 8c0ad9d9..108d9c21 100644 --- a/pitfall/pitfall/embedded.rkt +++ b/pitfall/pitfall/embedded.rkt @@ -45,10 +45,10 @@ For now, we'll just measure width of the characters. (define/contract (encode this text [features #f]) ((string?) ((or/c list? #f)) . ->*m . (list/c (listof string?) (listof (is-a?/c GlyphPosition)))) - (define glyphRun (send (· this font) layout (report text) features)) + (define glyphRun (send (· this font) layout text features)) (define glyphs (· glyphRun glyphs)) (for ([g (in-list glyphs)]) - (report (· g id))) + (· g id)) (define positions (· glyphRun positions)) (define-values (subset-idxs new-positions) (for/lists (idxs posns) diff --git a/pitfall/pitfall/test/out.bin b/pitfall/pitfall/test/out.bin index 0be093371961d49cf800dcf09b0da8fb2770e605..946f20d1843c1f4c13b72adb87da3221d3d3d1c5 100644 GIT binary patch literal 3743 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 D4jtS& literal 3373 zcmZ`*TWk~Q6+ZvW_>wqI;_={eT$PKoEkS4&|0v5so0Tx)qvK4*k zmabH(wZy7w`@q9i?L#lhn^*8)k`_|!KD2#kQH9ipMHSmtbk(iYR;68fA@29jOfKDS zZO#1WKmYBV^L_t0bM5NuXQ+enG(jiNotZyP`tNNt<#SLN{a>PuUwrlDwf^7H@4GaA z{fa)$!f2J3KX*+r`c<@nD_75~jn~khUby)Av&Q)Mi8_9A?$WjEdf#>#?f$b@7A_h6 zB_j43G4uqYksrv)iJqN*qYm*yKK^s@$Gi3Ry}!0kv|ZAo_%8Y#d@g=iB|dD+MAA<& zdQw`{_R)rnms4xMOaEkMCbMs{N5T>OPYEmHusANhA-*l;r5n;6>37;nC!Hk=9VE%v zr;{56>+m8MWoQn&^|q5Z_ye*D-zHgjOx6}*WC=4E2^qGeO@?qE!WdOB79nnhHAD9? zOCo#V}dSEK>-Z zdr87FQ*Vpn5Aft#)B`ySIh$Le0#?Kv^0p-^u1iB$6M~L#+C;5IYA$#ehKSX=p%~zb z0j^kvdE93ShXo*YYEltWpLVR;dl$yAr!7kG1M%b@7L%o267sgh8q}#iGax{){5aO2+TcL}WRV34}A5aHPM#>(4uXTea-_ zXrTwQ&WxnXId z{SUUtJ|cwkIYF zc3(Vkd?7tV?KW(Ua$AKYP9ZXr{oiOb{l{!YcnrNw(|23Yz&G4NAqC%}^qm&PfV~G# z4EPIxLdbEW1%P8g&jS~F&|4xaHt*Slzm2QvF_gbL{dQEYz=&0nQtM8x#WBl#sY)q(dZ{0 zN=2`J1GfsPt*kUuE*8A3HfT+$eVI%;Q1K^E)sv%vd{;V?E!YD||Hz)BN5%^5^j>!| zrleeUzbiaEIb-X5^RREL>fGXS*|zK`jDE(W@iUD(_Mvba{Oo~4X6lvD==@~Y5sM%# zEW<|uf1a(ph`VJSoB!cofV&*n0E_3J76stp2Hix1ZUM5b)6M^1G^>;g@X@Vq5UeDF zV1aVbY&VC)iYt<O@av^u-XqwL_+D834W|`{4LGi7wkPOIElT2MC4fz@cB43J zlJLTc){2o{$WF*k$W|EY-h`l?yJO#kpvV=X?q32?a%%pGSmx8b3S!W%d1Z$#q7gH} ziKwSjet)(wOH|LPl@z~1-GZgaRt8Sw3$xp!vFhQ%>?yYT!(;oC`!n@Y(U(;{!taaW zaD3!wW!v$w#JS_v9;9pt1}A^NCa=d*0E z*ozuOoY-r1f!9lpRemt)=D}afiaPO-8Z9N(Yv~l#zUr`&2!|B4V6vHZv1BYg*crEa zT?xis;TY3HA;xZ@s*0rG!vJ95B%?SH4<37;*Ga=Q}UyDe4fQ)Ff5Q12nT?Cp=pBRP!O#U^ntfHcjm+<*!!7b5E^a(NM4|(c=m6J6jq7gBgN=-2AkeX1GmRpu zE3n-B2>A$i(P=OM4k6tbnF#W?+@X-$9S;A(XocG$4;MY5wU%=LpGHh#Pf(r9%jgQI zTN`y-;!&42qRu}|kndqBPYfJs9KT**CMIWVYF%k4jTcTglu6~> z{OP8Y&{_<^q^hO;!TrhS(tEqC&G0Bvj zQkr6NruNxd^Tv3vIWk@kMx)9^b7iL1Tp15W>vhaBuUiU>`S-4FvjsMr(-^nvyUf*^ zBf%!s8x6kaTuqHOZ!{Xg2K+GkEn4}6g3%`xBZdNzz#fRiM2p>+!DeXGXpk$^s2YWx S^>Litk)4{WO~BGFTH&L diff --git a/pitfall/pitfall/test/test13crkt.pdf b/pitfall/pitfall/test/test13crkt.pdf index cce1211947ee0f779f0de90c9251892094379704..5f206284996e2c0727a0e806c766b3b52be4de9d 100644 GIT binary patch delta 2535 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 K1T+jaLH_}ry2w-j delta 4085 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 literal 7975 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 + + # Register a font name for use later + doc.registerFont('the-font', 'assets/eqbi.ttf') + + # Set the font, draw some text + doc.font('the-font') + .fontSize(25) + .text('H', 100, 100, {width: false}) + + doc.end() + + +doc = new PDFDocument({compress: no}) +doc.pipe(fs.createWriteStream('test14.pdf')) +make doc + diff --git a/pitfall/pitfall/test/test14.pdf b/pitfall/pitfall/test/test14.pdf new file mode 100644 index 0000000000000000000000000000000000000000..15760e3aa9ef1d0229f28363dcbe99fceba11792 GIT binary patch literal 5671 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 literal 0 HcmV?d00001 diff --git a/pitfall/pitfall/test/test14.rkt b/pitfall/pitfall/test/test14.rkt index 7208310f..10912049 100644 --- a/pitfall/pitfall/test/test14.rkt +++ b/pitfall/pitfall/test/test14.rkt @@ -1,6 +1,6 @@ #lang pitfall/pdftest -(define-runtime-path ttf-path "assets/Tahoma.ttf") +(define-runtime-path ttf-path "assets/eqbi.ttf") (define (proc doc) ;; Register a font name for use later @@ -10,14 +10,14 @@ (send* doc [font "the-font"] [fontSize 25] - [text "H" 100 100 (hash 'width #f)])) + [text "Hello World" 100 100 (hash 'width #f)])) ;; test against non-subsetted font version (define-runtime-path this "test14rkt.pdf") -(make-doc this #f proc #:test #f) +(make-doc this #f proc #:pdfkit #f) -#;(define-runtime-path that "test14crkt.pdf") -#;(make-doc that #t proc #:test #f) +(define-runtime-path that "test14crkt.pdf") +(make-doc that #t proc #:pdfkit #f) #;(module+ test (define doc (make-object PDFDocument)) diff --git a/pitfall/pitfall/test/test14crkt copy.pdf b/pitfall/pitfall/test/test14crkt copy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4e67cad562651fd5b7fa01caa1c448b364d68822 GIT binary patch literal 4822 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 diff --git a/pitfall/pitfall/test/test14rkt copy.pdf b/pitfall/pitfall/test/test14rkt copy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..370d250d49f2717df0d50a4308e579b662133f2a GIT binary patch literal 6858 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 jQ@!3~xB+R~ literal 0 HcmV?d00001 diff --git a/pitfall/pitfall/test/test14rkt.pdf b/pitfall/pitfall/test/test14rkt.pdf index 9db2c7a9e3be4788888b4e6d3adaf97d0090d6bc..370d250d49f2717df0d50a4308e579b662133f2a 100644 GIT binary patch literal 6858 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 jQ@!3~xB+R~ literal 6150 zcmc&YZEzdMb#L#$ucIV_B&ZM4(k%khp#)O+{*ovXBt9&LwndSU14>qeBXK045dnw* z9m$C+X4=Fmq&V^-84QP6^T-5i;X;Oj=6U>lb6*_r8aIZxdsL@1jnAU#iArS*eyGA;FIkI;Q~M0g!e>I*pc3%1zNoJ>*K zq%8FG2y!OL^fMjheWIv{vJIn7>eX~1pKWM5J3b;8=sp`-NNq9sNP*f0rch14K8N&q zV1I>TW=vV}19E1vkfH%Eqvs3LvNRmF}vq!lDq`P)KJpVW}X~j_@`| zz=sO((c0e4f=%PdPScK|f!N?c3^5pp;#Q!F*jNo&4#9r2DxWGO1;c~rpkQd5#=Kn znuOK?aPU1?4--&}kP(8g2OWKiy9`z6`C25u4Q9qyOKyzf(M){k{@}4yRFg#EmBwk9 zD(*|4?if3NprQMHXsgwTKUlhW4+AdOeERfL7fA>J(7yy3U|hyNKwUr z`)WfQVrV2qi@0WN2^=k9l)5V((RHEt6XvBhr3vSV(r8ugN6Gsi`;Ruh7+IgDY*{Qm zL6tMRW*SmpPkgiu0~u#<4B^tu5(yL6k7ulhjm1c2&f-Q4)=f zr8R}IHWh+4E1pM!QI^V-mOYFzTc)gtCoFh4XSJKFMX9}S<*&iGwmFj8rjWJ&3t2AF zmF7^KZ{t|PBgD1w3=*vPrgtmrtO$2li+C*8EQ-;pRK=Itx<{$85pMu?dLx#>-FxFS zQe4S`5=QrwY>vm|nYPp33ym0#GEadp^xga?{vNwLg2tbd=;wneDP@;cyw5xhk zwW;d8s@DvkHSFhK$KMWE{?+oo-#Bt3d1I9S27DZ^_picpZ~?-vS&kH8kMZi~Ruh zW7rMLOJqd7XQTH50^@2^vj#k*y4*T&?|rEJq51B$V#5n$AH0j5!`=7JZ)jz^@11XH z(Pq_X)Fejd>jZ|#>E`8_c})3!wWS1%siqbUGgjVrxC~6HHm^pSRM*_60TXK7Y7LOe zfULSoJhIxcMI*`TMv6wtYU>7(?IfwYcIz@dy*jX=de~$U^%P0>T;%)1$6iuK_#MdIX4_*n;&=@mIf2iobr{F49F3z;g_s{(#D_ z7yAUVojCDY6p0V#)i`^IQ#FaUzE!v;#7kVT2C;6OO*lJQKf279a3}Zta?UO)NAT>RajErQyF(K{6lm|43mb3#fQ0Fdk*a3{Fk=8oXy)cZ%0CplsS+$82tbkG)26-4*Qc<~8zEHTkCQWNzbI6MK zY$SyPI-+s24el(31S-lEBL#WtVQLp_@ttydGF6~XmwT(<>vH-XSYg4E&_mJ`){Q4H2h*!uG0T2TrMCR^Qpzs4Psa=H$e)3?>@^7^m@qSu|6rm&nJpHAlr zS(IlmQ_$tKd$)Sr&VUzLqlctPtZNCjfr4}>J>Hj@JR~#Im~g*V((3XA0$aWIfXnAW zQHN)%-)VPYiObQJLd6}`^ z>1JpkJaROTAsWa`WVPbh$V@JGNSbTix5_DNQc+voK8sn6x#kG74>j1{z!9PYt3XZ1N}$>f`XqU@-!>Q^e>F}6w{ zSoN&zgI;!Wc^ws1CmZS>$fVJ+av5(Tok>pXB}6)g)@K9^Uot&j&{rC6d`ik;4eWO3 zDZSHS#NBjxPiSPbfS6l?)YC(g@&u}TP|B5(NsCoiIX+z|b(2H$6fHstN6Dn|Y*NnW zBrLs287yA1TA#hAdjgwQ#=MQJ3yn=wa#OuPs1*wBJ#6Xr_v~kHMwt;o&Fd8_$7iNl z-Bk;XW;?Sfosn0fm&@ju0k+O0Q2+!t}&Q-@Q~N~zjFy&jLtLno+?^Z4-XEm1NzaZZdFYjg!? zciQo_y$$DZ;45((&hEHVpT~a(&W=CGcgVWkckJu-Ij~rK>mKfa?+!kX!-s(_^A)Bg vylJMjlD&3Yu!1wby2IHlUaBQ{B>foXfV1?5;!UbW%j0)Bh4%KyuBh-oI~Yov diff --git a/pitfall/restructure/struct.rkt b/pitfall/restructure/struct.rkt index dab49254..c2be8694 100644 --- a/pitfall/restructure/struct.rkt +++ b/pitfall/restructure/struct.rkt @@ -25,7 +25,7 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee (raise-argument-error 'Struct "assocs or hash" assocs)) (update-key-index! assocs) (for ([(k v) (in-dict assocs)]) - (hash-set! fields k v))) + (hash-set! fields k v))) (update-fields! assocs) @@ -36,20 +36,22 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee (send this process res stream) res) - (define/augride (encode stream input-hash [parent #f]) + (define/augment (encode stream input-hash [parent #f]) (unless (hash? input-hash) (raise-argument-error 'Struct:encode "hash" input-hash)) (send this preEncode input-hash stream) ; preEncode goes first, because it might bring input hash into compliance + (inner (void) encode stream input-hash parent) + (unless (andmap (λ (key) (member key (hash-keys input-hash))) key-index) (raise-argument-error 'Struct:encode (format "hash that contains superset of Struct keys: ~a" key-index) (hash-keys input-hash))) (for* ([key (in-list key-index)] ; iterate over original keys in order [struct-type (in-value (hash-ref fields key))] [value-to-encode (in-value (hash-ref input-hash key))]) - (send struct-type encode stream value-to-encode))) + (send struct-type encode stream value-to-encode))) (define/public-final (_setup stream parent length) (define res (mhasheq)) @@ -64,16 +66,16 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee (define/public-final (_parseFields stream res fields) (for ([key (in-list key-index)]) - (define dictvalue (dict-ref fields key)) - (define val - (if (procedure? dictvalue) - (dictvalue res) - (send dictvalue decode stream res))) - (hash-set! res key val))) + (define dictvalue (dict-ref fields key)) + (define val + (if (procedure? dictvalue) + (dictvalue res) + (send dictvalue decode stream res))) + (hash-set! res key val))) (define/override (size [val (mhash)] [parent #f] [includePointers #t]) (for/sum ([(key type) (in-hash fields)]) - (send type size (hash-ref val key #f))))) + (send type size (hash-ref val key #f))))) (test-module @@ -83,17 +85,17 @@ https://github.com/mbutterick/restructure/blob/master/src/Struct.coffee ;; make random structs and make sure we can round trip (for ([i (in-range 100)]) - (define field-types (for/list ([i (in-range 200)]) - (random-pick (list uint8 uint16be uint16le uint32be uint32le double)))) - (define size-num-types (for/sum ([num-type (in-list field-types)]) - (send num-type size))) - (define s (+Struct (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)))) - (define es (+EncodeStream)) - (send s encode es (send s decode bs)) - (check-equal? (send es dump) bs))) + (define field-types (for/list ([i (in-range 200)]) + (random-pick (list uint8 uint16be uint16le uint32be uint32le double)))) + (define size-num-types (for/sum ([num-type (in-list field-types)]) + (send num-type size))) + (define s (+Struct (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)))) + (define es (+EncodeStream)) + (send s encode es (send s decode bs)) + (check-equal? (send es dump) bs))) @@ -130,7 +132,11 @@ https://github.com/mbutterick/restructure/blob/master/src/VersionedStruct.coffee [else (send this _parseFields stream res fields) (send this process res stream) - res]))) + res])) + + (define/augment (encode stream input-hash [parent #f]) + (define assocs (dict-ref versions (· input-hash version) (λ () (raise-argument-error 'VersionedStruct:encode "valid version key" version)))) + (send this update-fields! assocs))) (test-module (require "number.rkt") @@ -138,18 +144,18 @@ https://github.com/mbutterick/restructure/blob/master/src/VersionedStruct.coffee ;; make random versioned structs and make sure we can round trip (for ([i (in-range 20)]) - (define field-types (for/list ([i (in-range 200)]) - (random-pick (list uint8 uint16be uint16le uint32be uint32le double)))) - (define num-versions 20) - (define which-struct (random num-versions)) - (define struct-versions (for/list ([v (in-range num-versions)]) - (cons v (for/list ([num-type (in-list field-types)]) - (cons (gensym) num-type))))) - (define vs (+VersionedStruct which-struct struct-versions)) - (define struct-size (for/sum ([num-type (in-list (map cdr (dict-ref struct-versions which-struct)))]) - (send num-type size))) - (define bs (apply bytes (for/list ([i (in-range struct-size)]) - (random 256)))) - (define es (+EncodeStream)) - (send vs encode es (send vs decode bs)) - (check-equal? (send es dump) bs))) + (define field-types (for/list ([i (in-range 200)]) + (random-pick (list uint8 uint16be uint16le uint32be uint32le double)))) + (define num-versions 20) + (define which-struct (random num-versions)) + (define struct-versions (for/list ([v (in-range num-versions)]) + (cons v (for/list ([num-type (in-list field-types)]) + (cons (gensym) num-type))))) + (define vs (+VersionedStruct which-struct struct-versions)) + (define struct-size (for/sum ([num-type (in-list (map cdr (dict-ref struct-versions which-struct)))]) + (send num-type size))) + (define bs (apply bytes (for/list ([i (in-range struct-size)]) + (random 256)))) + (define es (+EncodeStream)) + (send vs encode es (send vs decode bs)) + (check-equal? (send es dump) bs)))