From dcf32450a9b002657b52aa3fc619742dd96f67ac Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Mon, 15 Jul 2024 17:03:50 +0200 Subject: [PATCH 1/3] Add internal decompression buffers When warm it provides a nice speedup: ``` BEFORE: BenchmarkFindSerialized/100-32 84632 14027 ns/op 24.28 b/file 84632 files/s 5062 B/op 4 allocs/op BenchmarkFindSerialized/1000-32 13371 88087 ns/op 23.32 b/file 13371 files/s 49398 B/op 4 allocs/op BenchmarkFindSerialized/10000-32 1491 769408 ns/op 20.66 b/file 1491 files/s 451106 B/op 4 allocs/op BenchmarkFindSerialized/100000-32 163 7350855 ns/op 20.25 b/file 163.0 files/s 4499216 B/op 5 allocs/op BenchmarkFindSerialized/1000000-32 15 175437187 ns/op 20.16 b/file 7.500 files/s 44978624 B/op 6 allocs/op AFTER: BenchmarkFindSerialized/100-32 89673 13144 ns/op 24.28 b/file 89673 files/s 216 B/op 4 allocs/op BenchmarkFindSerialized/1000-32 15356 78862 ns/op 23.32 b/file 15356 files/s 220 B/op 4 allocs/op BenchmarkFindSerialized/10000-32 1663 719424 ns/op 20.66 b/file 1663 files/s 228 B/op 4 allocs/op BenchmarkFindSerialized/100000-32 170 6894286 ns/op 20.25 b/file 170.0 files/s 26760 B/op 4 allocs/op BenchmarkFindSerialized/1000000-32 16 67916169 ns/op 20.16 b/file 16.00 files/s 2812044 B/op 4 allocs/op ``` --- file.go | 32 +++++++++++++++++++++++--------- file_gen.go | 2 ++ go.mod | 6 +++--- go.sum | 12 ++++++------ 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/file.go b/file.go index 79d1d05..d7fab41 100644 --- a/file.go +++ b/file.go @@ -25,6 +25,7 @@ import ( "path/filepath" "sort" "strings" + "sync" "github.com/klauspost/compress/zstd" "github.com/tinylib/msgp/msgp" @@ -243,40 +244,50 @@ func (f Files) StripFlags(mask uint16) { } } +var decompBuffer sync.Pool + // unpackPayload unpacks and optionally decompresses the payload. -func unpackPayload(b []byte) ([]byte, bool, error) { +func unpackPayload(b []byte) (payload []byte, structs, newBuf bool, err error) { if len(b) < 1 { - return nil, false, io.ErrUnexpectedEOF + return nil, false, false, io.ErrUnexpectedEOF } if len(b) > MaxIndexSize { - return nil, false, ErrMaxSizeExceeded + return nil, false, false, ErrMaxSizeExceeded } var out []byte switch b[0] { case currentVerPlain: out = b[1:] case currentVerCompressed, currentVerCompressedStructs: - decoded, err := zstdDec.DecodeAll(b[1:], nil) + newBuf = true + dst, _ := decompBuffer.Get().([]byte) + // It is ok if we get a nil buffer, the decoder will allocate. + + decoded, err := zstdDec.DecodeAll(b[1:], dst[:0]) if err != nil { switch err { case zstd.ErrDecoderSizeExceeded, zstd.ErrWindowSizeExceeded: err = ErrMaxSizeExceeded } - return nil, false, err + decompBuffer.Put(dst) + return nil, false, false, err } out = decoded default: - return nil, false, errors.New("unknown version") + return nil, false, false, errors.New("unknown version") } - return out, b[0] == currentVerCompressedStructs, nil + return out, b[0] == currentVerCompressedStructs, newBuf, nil } // DeserializeFiles will de-serialize the files. func DeserializeFiles(b []byte) (Files, error) { - b, structs, err := unpackPayload(b) + b, structs, newBuf, err := unpackPayload(b) if err != nil { return nil, err } + if newBuf { + defer decompBuffer.Put(b) + } if !structs { var dst files // Check number of files. @@ -360,10 +371,13 @@ func readCustomData(bts []byte) (dst map[string]string, err error) { // Expected speed scales O(n) for n files. // Returns nil, io.EOF if not found. func FindSerialized(b []byte, name string) (*File, error) { - buf, structs, err := unpackPayload(b) + buf, structs, newBuf, err := unpackPayload(b) if err != nil { return nil, err } + if newBuf { + defer decompBuffer.Put(buf) + } if !structs { n, buf, err := msgp.ReadArrayHeaderBytes(buf) if err != nil { diff --git a/file_gen.go b/file_gen.go index f6b7eb9..a163381 100644 --- a/file_gen.go +++ b/file_gen.go @@ -66,6 +66,8 @@ func (z *File) DecodeMsg(dc *msgp.Reader) (err error) { delete(z.Custom, key) } } + var field []byte + _ = field for zb0002 > 0 { zb0002-- var za0001 string diff --git a/go.mod b/go.mod index 5d1da60..8795fc2 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/minio/zipindex go 1.20 require ( - github.com/klauspost/compress v1.17.8 - github.com/tinylib/msgp v1.1.9 + github.com/klauspost/compress v1.17.9 + github.com/tinylib/msgp v1.2.0 ) -require github.com/philhofer/fwd v1.1.2 // indirect +require github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect diff --git a/go.sum b/go.sum index bddbfed..cd21f91 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= -github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= -github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= -github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= +github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= From bda8c4dcf78d43350a8100f258e8cb5657501f40 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Fri, 16 Aug 2024 10:10:06 +0200 Subject: [PATCH 2/3] Tweak lint & update CI --- .github/workflows/go.yml | 4 ++-- .golangci.yml | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 3a09960..e5dacf7 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - go-version: [1.21.x,1.22.x] + go-version: [1.21.x,1.22.x,1.23.x] os: [ubuntu-latest] steps: - name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }} @@ -30,6 +30,6 @@ jobs: env: GO111MODULE: on run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.59.0 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.1 $(go env GOPATH)/bin/golangci-lint run --timeout=5m --config ./.golangci.yml go test -race ./... diff --git a/.golangci.yml b/.golangci.yml index 1991202..99142fd 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,8 @@ linters-settings: - golint: - min-confidence: 0 - + staticcheck: + checks: + - all + - '-SA6002' # disable the rule SA6002, slices are fine. misspell: locale: US @@ -24,5 +25,3 @@ issues: - comment on exported method - should have comment or be unexported - error strings should not be capitalized or end with punctuation or a newline -service: - golangci-lint-version: 1.59.0 # use the fixed version to not introduce new linters unexpectedly From a89f822b2a609ffb64fa1573301456749ab09b31 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Mon, 19 Aug 2024 18:34:41 +0200 Subject: [PATCH 3/3] Add new chunked format for faster FindSerialized. Kicks in at 25000 dir entries. Ensures that performance will be somewhat linear. Bumps index limit to 1B. ``` BenchmarkFindSerialized/100-32 88186 13926 ns/op 24.28 b/file 88186 files/s 216 B/op 4 allocs/op BenchmarkFindSerialized/1000-32 14157 82875 ns/op 23.32 b/file 14157 files/s 220 B/op 4 allocs/op BenchmarkFindSerialized/10000-32 1562 757547 ns/op 20.66 b/file 1562 files/s 225 B/op 4 allocs/op BenchmarkFindSerialized/100000-32 567 2101872 ns/op 21.66 b/file 567.0 files/s 1164419 B/op 10 allocs/op BenchmarkFindSerialized/1000000-32 583 2035905 ns/op 21.73 b/file 583.0 files/s 1181472 B/op 47 allocs/op ``` --- file.go | 220 +++++++++++++++++++++++-- file_gen.go | 178 ++++++++++++++++++++ file_gen_test.go | 113 +++++++++++++ testdata/fuzz/FuzzDeserializeFiles.zip | Bin 1654105 -> 1693196 bytes testdata/fuzz/FuzzRoundtrip.zip | Bin 925429 -> 995450 bytes zipindex.go | 2 +- 6 files changed, 494 insertions(+), 19 deletions(-) diff --git a/file.go b/file.go index d7fab41..1a0179a 100644 --- a/file.go +++ b/file.go @@ -93,6 +93,7 @@ type files []File const currentVerPlain = 1 const currentVerCompressed = 2 const currentVerCompressedStructs = 3 +const currentVerCompressedStructsChunked = 4 var zstdEnc, _ = zstd.NewWriter(nil, zstd.WithWindowSize(128<<10), zstd.WithEncoderConcurrency(2), zstd.WithEncoderLevel(zstd.SpeedBetterCompression)) var zstdDec, _ = zstd.NewReader(nil, zstd.WithDecoderLowmem(true), zstd.WithDecoderConcurrency(2), zstd.WithDecoderMaxMemory(MaxIndexSize), zstd.WithDecoderMaxWindow(8<<20)) @@ -133,7 +134,44 @@ func (f Files) Serialize() ([]byte, error) { res = append(res, currentVerCompressed) return zstdEnc.EncodeAll(payload, res), nil } + const chunkN = 25000 + if len(f) < chunkN { + return f.encodeAoS(nil) + } + f.SortByName() + res := append([]byte{}, currentVerCompressedStructsChunked) + left := f + var tmp []byte + for len(left) > 0 { + todo := left + if len(left) < chunkN*2 && len(left) > chunkN { + todo = left[:len(left)/2] + } else if len(left) > chunkN { + todo = left[:chunkN] + } + ch := chunk{ + Files: len(todo), + First: todo[0].Name, + Last: todo[len(todo)-1].Name, + } + // Sort each chunk for smaller offsets. + todo.Sort() + var err error + tmp, err = todo.encodeAoS(tmp[:0]) + if err != nil { + return nil, err + } + ch.Payload = tmp + res, err = ch.MarshalMsg(res) + if err != nil { + return nil, err + } + left = left[len(todo):] + } + return res, nil +} +func (f Files) encodeAoS(res []byte) ([]byte, error) { // Encode many files as struct of arrays... x := filesAsStructs{ Names: make([][]byte, len(f)), @@ -174,7 +212,6 @@ func (f Files) Serialize() ([]byte, error) { if err != nil { return nil, err } - res := make([]byte, 0, len(payload)) res = append(res, currentVerCompressedStructs) return zstdEnc.EncodeAll(payload, res), nil } @@ -210,6 +247,20 @@ func (f Files) Sort() { } } +// SortByName will sort files by file name in zip file. +func (f Files) SortByName() { + less := func(i, j int) bool { + a, b := f[i], f[j] + if a.Name != b.Name { + return a.Name < b.Name + } + return a.Offset < b.Offset + } + if !sort.SliceIsSorted(f, less) { + sort.Slice(f, less) + } +} + // Find the file with the provided name. // Search is linear. func (f Files) Find(name string) *File { @@ -247,16 +298,17 @@ func (f Files) StripFlags(mask uint16) { var decompBuffer sync.Pool // unpackPayload unpacks and optionally decompresses the payload. -func unpackPayload(b []byte) (payload []byte, structs, newBuf bool, err error) { +func unpackPayload(b []byte) (payload []byte, typ byte, newBuf bool, err error) { if len(b) < 1 { - return nil, false, false, io.ErrUnexpectedEOF + return nil, 0, false, io.ErrUnexpectedEOF } if len(b) > MaxIndexSize { - return nil, false, false, ErrMaxSizeExceeded + return nil, 0, false, ErrMaxSizeExceeded } var out []byte - switch b[0] { - case currentVerPlain: + typ = b[0] + switch typ { + case currentVerPlain, currentVerCompressedStructsChunked: out = b[1:] case currentVerCompressed, currentVerCompressedStructs: newBuf = true @@ -270,25 +322,25 @@ func unpackPayload(b []byte) (payload []byte, structs, newBuf bool, err error) { err = ErrMaxSizeExceeded } decompBuffer.Put(dst) - return nil, false, false, err + return nil, typ, false, err } out = decoded default: - return nil, false, false, errors.New("unknown version") + return nil, typ, false, errors.New("unknown version") } - return out, b[0] == currentVerCompressedStructs, newBuf, nil + return out, typ, newBuf, nil } // DeserializeFiles will de-serialize the files. func DeserializeFiles(b []byte) (Files, error) { - b, structs, newBuf, err := unpackPayload(b) + b, typ, newBuf, err := unpackPayload(b) if err != nil { return nil, err } if newBuf { defer decompBuffer.Put(b) } - if !structs { + if typ == currentVerCompressed || typ == currentVerPlain { var dst files // Check number of files. nFiles, _, err := msgp.ReadArrayHeaderBytes(b) @@ -301,15 +353,53 @@ func DeserializeFiles(b []byte) (Files, error) { _, err = dst.UnmarshalMsg(b) return Files(dst), err } + if typ == currentVerCompressedStructsChunked { + var dst Files + var c chunk + tmp, _ := decompBuffer.Get().([]byte) + defer func() { + if tmp != nil { + decompBuffer.Put(tmp) + } + }() + for len(b) > 0 { + b, err = c.UnmarshalMsgZC(b) + if err != nil { + return nil, err + } + if len(c.Payload) == 0 { + return nil, errors.New("missing payload") + } + switch c.Payload[0] { + case currentVerCompressedStructs: + tmp, err = zstdDec.DecodeAll(c.Payload[1:], tmp[:0]) + if err != nil { + return nil, err + } + dst, err = deserializeAoS(tmp, dst) + if err != nil { + return nil, err + } + default: + return nil, errors.New("unknown version") + } + } + return dst, nil + } + return deserializeAoS(b, nil) +} +func deserializeAoS(b []byte, files Files) (Files, error) { var dst filesAsStructs + var err error if _, err = dst.UnmarshalMsg(b); err != nil { return nil, err } - - files := make(Files, len(dst.Names)) + start := len(files) + files = append(files, make(Files, len(dst.Names))...) + add := files[start:] var cur File - for i := range files { + for i := range add { cur = File{ Name: string(dst.Names[i]), CompressedSize64: uint64(dst.CSizes[i] + int64(cur.CompressedSize64)), @@ -321,17 +411,18 @@ func DeserializeFiles(b []byte) (Files, error) { if i == 0 { cur.Offset = dst.Offsets[i] } else { - cur.Offset = dst.Offsets[i] + files[i-1].Offset + int64(files[i-1].CompressedSize64) + fileHeaderLen + int64(len(files[i-1].Name)) + dataDescriptorLen + cur.Offset = dst.Offsets[i] + add[i-1].Offset + int64(add[i-1].CompressedSize64) + fileHeaderLen + int64(len(add[i-1].Name)) + dataDescriptorLen } if len(dst.Custom[i]) > 0 { if cur.Custom, err = readCustomData(dst.Custom[i]); err != nil { return nil, err } } - files[i] = cur + add[i] = cur } return files, err + } func readCustomData(bts []byte) (dst map[string]string, err error) { @@ -371,14 +462,14 @@ func readCustomData(bts []byte) (dst map[string]string, err error) { // Expected speed scales O(n) for n files. // Returns nil, io.EOF if not found. func FindSerialized(b []byte, name string) (*File, error) { - buf, structs, newBuf, err := unpackPayload(b) + buf, typ, newBuf, err := unpackPayload(b) if err != nil { return nil, err } if newBuf { defer decompBuffer.Put(buf) } - if !structs { + if typ == currentVerCompressed || typ == currentVerPlain { n, buf, err := msgp.ReadArrayHeaderBytes(buf) if err != nil { return nil, err @@ -399,6 +490,38 @@ func FindSerialized(b []byte, name string) (*File, error) { return nil, io.EOF } + if typ == currentVerCompressedStructsChunked { + var c chunk + for len(buf) > 0 { + buf, err = c.UnmarshalMsgZC(buf) + if err != nil { + return nil, err + } + if name < c.First { + return nil, io.EOF + } + if name >= c.First && name <= c.Last { + if len(c.Payload) == 0 { + return nil, errors.New("missing payload") + } + buf = c.Payload + if buf[0] != currentVerCompressedStructs { + return nil, errors.New("unknown chunk") + } + dst, _ := decompBuffer.Get().([]byte) + defer decompBuffer.Put(dst) + buf, err = zstdDec.DecodeAll(buf[1:], dst[:0]) + if err != nil { + return nil, err + } + break + } + if len(buf) == 0 { + return nil, io.EOF + } + } + } + // Files are packed as an array of arrays... idx := -1 var zb0001 uint32 @@ -826,3 +949,64 @@ func (z *filesAsStructs) UnmarshalMsg(bts []byte) (o []byte, err error) { o = bts return } + +type chunk struct { + Files int + First string + Last string + Payload []byte +} + +// UnmarshalMsgZC unmarshals, but does a zero copy bytes +func (z *chunk) UnmarshalMsgZC(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Files": + z.Files, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Files") + return + } + case "First": + z.First, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "First") + return + } + case "Last": + z.Last, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Last") + return + } + case "Payload": + z.Payload, bts, err = msgp.ReadBytesZC(bts) + if err != nil { + err = msgp.WrapError(err, "Payload") + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} diff --git a/file_gen.go b/file_gen.go index a163381..ceb3b50 100644 --- a/file_gen.go +++ b/file_gen.go @@ -181,6 +181,184 @@ func (z *File) Msgsize() (s int) { return } +// DecodeMsg implements msgp.Decodable +func (z *chunk) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Files": + z.Files, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "Files") + return + } + case "First": + z.First, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "First") + return + } + case "Last": + z.Last, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Last") + return + } + case "Payload": + z.Payload, err = dc.ReadBytes(z.Payload) + if err != nil { + err = msgp.WrapError(err, "Payload") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *chunk) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 4 + // write "Files" + err = en.Append(0x84, 0xa5, 0x46, 0x69, 0x6c, 0x65, 0x73) + if err != nil { + return + } + err = en.WriteInt(z.Files) + if err != nil { + err = msgp.WrapError(err, "Files") + return + } + // write "First" + err = en.Append(0xa5, 0x46, 0x69, 0x72, 0x73, 0x74) + if err != nil { + return + } + err = en.WriteString(z.First) + if err != nil { + err = msgp.WrapError(err, "First") + return + } + // write "Last" + err = en.Append(0xa4, 0x4c, 0x61, 0x73, 0x74) + if err != nil { + return + } + err = en.WriteString(z.Last) + if err != nil { + err = msgp.WrapError(err, "Last") + return + } + // write "Payload" + err = en.Append(0xa7, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64) + if err != nil { + return + } + err = en.WriteBytes(z.Payload) + if err != nil { + err = msgp.WrapError(err, "Payload") + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *chunk) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // map header, size 4 + // string "Files" + o = append(o, 0x84, 0xa5, 0x46, 0x69, 0x6c, 0x65, 0x73) + o = msgp.AppendInt(o, z.Files) + // string "First" + o = append(o, 0xa5, 0x46, 0x69, 0x72, 0x73, 0x74) + o = msgp.AppendString(o, z.First) + // string "Last" + o = append(o, 0xa4, 0x4c, 0x61, 0x73, 0x74) + o = msgp.AppendString(o, z.Last) + // string "Payload" + o = append(o, 0xa7, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64) + o = msgp.AppendBytes(o, z.Payload) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *chunk) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Files": + z.Files, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Files") + return + } + case "First": + z.First, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "First") + return + } + case "Last": + z.Last, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Last") + return + } + case "Payload": + z.Payload, bts, err = msgp.ReadBytesBytes(bts, z.Payload) + if err != nil { + err = msgp.WrapError(err, "Payload") + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *chunk) Msgsize() (s int) { + s = 1 + 6 + msgp.IntSize + 6 + msgp.StringPrefixSize + len(z.First) + 5 + msgp.StringPrefixSize + len(z.Last) + 8 + msgp.BytesPrefixSize + len(z.Payload) + return +} + // DecodeMsg implements msgp.Decodable func (z *files) DecodeMsg(dc *msgp.Reader) (err error) { var zb0002 uint32 diff --git a/file_gen_test.go b/file_gen_test.go index ffb8764..642bd10 100644 --- a/file_gen_test.go +++ b/file_gen_test.go @@ -64,6 +64,119 @@ func BenchmarkDecodeFile(b *testing.B) { } } +func TestMarshalUnmarshalchunk(t *testing.T) { + v := chunk{} + bts, err := v.MarshalMsg(nil) + if err != nil { + t.Fatal(err) + } + left, err := v.UnmarshalMsg(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) + } + + left, err = msgp.Skip(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after Skip(): %q", len(left), left) + } +} + +func BenchmarkMarshalMsgchunk(b *testing.B) { + v := chunk{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalMsg(nil) + } +} + +func BenchmarkAppendMsgchunk(b *testing.B) { + v := chunk{} + bts := make([]byte, 0, v.Msgsize()) + bts, _ = v.MarshalMsg(bts[0:0]) + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts, _ = v.MarshalMsg(bts[0:0]) + } +} + +func BenchmarkUnmarshalchunk(b *testing.B) { + v := chunk{} + bts, _ := v.MarshalMsg(nil) + b.ReportAllocs() + b.SetBytes(int64(len(bts))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := v.UnmarshalMsg(bts) + if err != nil { + b.Fatal(err) + } + } +} + +func TestEncodeDecodechunk(t *testing.T) { + v := chunk{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + + m := v.Msgsize() + if buf.Len() > m { + t.Log("WARNING: TestEncodeDecodechunk Msgsize() is inaccurate") + } + + vn := chunk{} + err := msgp.Decode(&buf, &vn) + if err != nil { + t.Error(err) + } + + buf.Reset() + msgp.Encode(&buf, &v) + err = msgp.NewReader(&buf).Skip() + if err != nil { + t.Error(err) + } +} + +func BenchmarkEncodechunk(b *testing.B) { + v := chunk{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + en := msgp.NewWriter(msgp.Nowhere) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.EncodeMsg(en) + } + en.Flush() +} + +func BenchmarkDecodechunk(b *testing.B) { + v := chunk{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + rd := msgp.NewEndlessReader(buf.Bytes(), b) + dc := msgp.NewReader(rd) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := v.DecodeMsg(dc) + if err != nil { + b.Fatal(err) + } + } +} + func TestMarshalUnmarshalfiles(t *testing.T) { v := files{} bts, err := v.MarshalMsg(nil) diff --git a/testdata/fuzz/FuzzDeserializeFiles.zip b/testdata/fuzz/FuzzDeserializeFiles.zip index 90d45aca31306c878dab3144eafa4d7961206154..4087107b53442ac1c8a06dd598600a7c67adb2b1 100644 GIT binary patch delta 33134 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
6Mi&$p8KPP&I_f;QjwabUYG*(M zuCZf%yqO|W36Ft{Uxsc=#cL|vEj}7v+{_r@^&-!Ig zwGSUQtlP%Dq@+C{Y2n`~H&6@yv739dR@O^`U^Mf3tK;Yk{5#T%6!R5` z3I99A7Y&f(jByZ7VOSFnVGvegIP12g;P!3$hr#(8Qrv67GIG69z@pENJVO)z!0|)lT z&1U=jiMkMD|3(HbdXAM~AM{`=E8h_K9I1RmfToAvl)@Kv)omn?9*P>TULxVyjkixz zBMZDB>9u+j!)V}TgWk6NxovxnNFH&Ng+nP*TFw-EfrKY^DS{+xFia!EM~kunuk4rs zs?q)f^9o{%gEHo12hWq3?D({fqt_?+9y=U)@o@jJLwE8H`|qFRwWswM@&w=jvupn| z9KYD%uCcOF(C|h^i~k|9w)Z7|F>xsUlk2%yyv6tT4972a945UEu3xj!%m}h%<|`ME z{NfnO1;q(%xKfdhQuOvOHW`c@!$~}60)GHJF1s_}2vfi-F86G8EsOgw$mX|ocSzy& z;GMv&$w_c9!SY@8bgaHd;Jq#p{w~G-q5(Hg1NhfGUP}rxV0&IZ_R4R|igXdM=Sq;=( z1H6ayB7GBFolP(ERCv1>?V`Z378wZFi5vtfBx&B$1jpr47 zE=Dq%wGdho1lV*~aO)^-a6==0SXlC~vg*3MF{;(eSb)A`hnq!K1Kuz^kTs0Nz#c(R z!UlJ7|Ksrg-F|-}YRP+cJnV|h>0yfuTBBaDncZqScTzQ#@~lx(KC?`V+JZmaAzo(T zt#9HXP^M+gIy43i+gBdg$_0_=*9J=IbLz`*+-HZ*$q@cAb0#f3jdh~lx@|$bBV zl`%S-+DaMKt-`#(fKL$YSXS6v*`U>MCL<3QzwJ}1o?pX+&7_9xfEnCqHKwR12sj2m z+!viJnstycV&Q5v!b7qaJa7jN4pOIN3t3rrq^uiKcG->W>=B-!8fL7!@i=umt^|>3 zwW9`g2T_08MM9W}gWHkQ8^G7&dF!$@>J|{F3##2tc{I16R0id|Z9HNxt}y;^Y7mWK zA){rMVZSx7Pqrsr)e4u)&!ja5g~WeNQ)8CmCNFI1O;A;1s~+tbx}P1X9sL;dNSRc%{gz6_+Y1TrA6lz70H4cTpC~ z0k=cPm~MV)AzP2s^_?a-;mA4(Aglgxqv*P8|2V1maJoM?FY z+rLN3aJ44yytn=s&ctCYO-7xh6(kXYMBtKFJug6W!Q|G-m{Z+Y;!IZgPtSIC$ux{8 z>-7xBnm7U8f^Je!1RiMgG9c;VUCkx4t?k2mBT$CJN<#END;i{3uQ6!NEF2>6G^?zF zN8}Ho^(Y4%g)nbV^~5c9gdpJdF`CR8t&uV7z+l-faNJ^>+4e}I+*Fis?3<21I&Y0E znh)%$U=ZOFf!K;|Zxme%O|7nLH4esI z#`SO?0;4yrr)&nW&2yzh<6c;-_&=>j5(0>3j9LfgaIALxS{gL6S`hf70{btYCT^LmX?X##8;qr}Vjbn-IB znGCxB?HlKfF^Oi8mso*?g%!X(z@(ln7h+3gNFmiX=7jmwbNm*^#%PQ(#A5Ye*lh3M zZRX$zWoMHZ>L$lIJXm~p1s*uZq0{Oiye#mr!w?%{tir(>wjcv+3f_PAgs-d9d$7(e zFZ>w1*KtiCsH>G2RtuLh1S}xS4;BFCV!yuljOxpA{@S~_&Nc*M(}D<@FennxXu$xW z1pABiHm03j&7x>WP8(;>0F8P$8sF6vpFUP)Ku6Rp7M`yIez~8e2VjtgYy9| zI+23_mtJGd3lDBY9=L2*2X5z{$aAV!dQ`u4R;dxXr3{c>L3ZS7zFs5cm#G7T-<~%xXat{wfj#=eKx{gah$czs%AEg5L zv0aD>qPH@DN45}F}ouf7plFGI+= z?-`wzdn?{+U7b$rYj=C|CMbS&UWd7|`x%v32vNSw)X0THeDAETm+S8p6hF*oTV7;t zSoiQ|-`_~j^`PAB*)YSgFB*1wh|gz7B9$?Ug2=LZ9;_25$kwNmAuxI4+aSNRw8CY} z3KP;gZfE`KhlQ8c4+|@uQdCqB?$?Ss<|sF1uwYYXhns5P;2we}H7AL(1b!V}v8_>= za33jULi}bqeT4J*W{r?9)3E}tfs~m}Kxf;2yy0q{A59)_6fk{5c>$_`Ly<%VG9_k7 z!$V97GOm$VJ#FCyW(I`iRX^r<_i*tMeIozzL=%BOR3if;={ShtXyFPlakk8)axsUd zQsEn%#g_;C1JTQH%tCK8iLwT21~9g-H`&f5Mx>kqqhE0^+<>S1 zlzk##VT?wdh=D8!$ntnJTP`@Gu9Z--_(7(pf$}3sgCE0nz~k!{78ag&?97?jJ@WT^k-LL(#w_gM znE^5!!97T~2rLH?R8FhWLHyko+{2;@Yuj?Qe?pc=QIEEfs(UWX%j)H*KX(@n|CQIcsF+-K6rDJ~ z)kst&M}A0Td4q-pbpj&`dSDIO?%U9MGA^hVS3NUi``9hXb#U7px30u75al(pTF5m( zb{~U>HU|JLl#Wifp@0zsR5^GaaT2y$h7rI-!O4`(292z-U6|D2=2^@-Fw41`w|q?0&^1KCnac83UDh-$%VoXP8i@O$Wm;B0Uv zX0xb;Sf>`s)y$&CmVdN6A^09*hEpdSMP&F+*^PIGLj=#7^jO>i=ZJwvn$2L^oRIh< zRJIP$U!QIJJAQ)$4XJt~V_@}?Mh{Wk%4j)$gWXK}P-YTEB>(*T7H6%{@kU;&GfH4x zj0VOUG%7d(PNKsVqdZd-pih~9)mZ@Ki}WVF1W#SrthEMp4Q^yxMRcNEYSkiD?m4t; z4z1!C$X)S}DU!j1(aBYB6zR~8I!>Zf{g8FIjPdZpoq#w$gl9Ac&L~R;gW0y3 zwq>lCLKUY?0QB?KF`xAS)FV3@LMW_k5Ctebh0;Tl_3TS^i=O{`*mF_+LwAJc+bK;S z2ZFn|`F(vF2zA&O2{iz1Prm&*dS_&- zo}%cV2V=5ifN zxbDL;Vm>-K=Tq}?X0q|{w_&W0P=JMYAj=L!xOO0G zW@eetiF6OG(L8w<)3ev8m#=0)?mTo}TuAP-Bfe8V_l@5dJA0`&dsH>dZGL3UdkYUP zyxUrR(7OiTd2DH(G1=#cu42`c%+rArl*1dN!gA#yFyoHHZAX82#HMVWr&`gl#P)CTQ zNsOp9Vc7IwVj-rHD zEq5JtmH93{Zdug9eOOrsVEX|3yNmQ;a$x+daixRNW*xPU4^D#) zBWfmw1+UpwoM^j^bx+GesL)_Gz%%NFZN=&152w%RA@dL6R|Yceg4SS*Cgb!m#6b>@ z=!sGD-0{Pk+tJ|W!%L4hFdXE2z_MWB7`W;VvrXT^C}LgyTKA3sclc1E8486VwGM>? z26)k<4;5>DGd?)j^4*4M)AmPF`L)3y;_rz)e|9!TPzEhPrcMK1g#b@b{r{UWqHU4o z|FT z2FNf$HthdCg^&%KFeFu?VSf*n0z`5jk-Ne3Z(vkU=0tdTTTzC)`_2h`Gh z6mxdEf8Wyjxea`3kdJp1w>EOjm^2WVZC3~=V1ihxjx!rI8gOQj#(BwJdpF z$=A-PymQMrwYSD^y8ju#$EG)mM z+hA!sboc29`R0|ix!t}0+qj%TcDSJ`)ia=go$?W`MoA@+m0v)@(g*Ot#d z`Bn6jsLVOt#{`E){rvIWQA^YX-Rd;VZZ91z4hr;1z3s83#-e9YZ5yX)Gye&><9T>M zRDb={v(MQrs?{?RTX_Dbzw`CIjb4+Uj9vXp+#BP=FaET6R^2+PKJcmMer+Fl4nFmW zJq;@h0yt0bqJc;dWZw)YyC?L7Qp56BwMS$X9VlGTtmCP(r{0MvPF!^8+KqVCoRCI$ zx*uyfD@%SfeQeXqpMB>4!@pk@JlnVVW znw*jTd)c(1!ylYqoip*~wV(IY&geCG7dvR3|8V2lljFX8wQJ~$1=mmSo@i+KWT2P2 zcx&f&S-1MH=#cf^wXfs+0#`3s*=1hc=(#>|fm1_9J)XCA-1rS`0(?66oVWes36I}~ zt=jkR&b}>shc^kDo%mp)-!UI!qmi99AF`ae+hF?JDeT=(p4U>Apf@bR_e&ZK>IO^T zumq3-l{KI_CdghgGQ{;AA(0eYNF*;$D9Bruw>K{@At^gMdF}oi?xa4VOzZDoug0W| zL%rd0fe^h6?uyO?g&b976Sb`szo51>!K4)`)yNOlLlx;MBZ&vXMD-@ zXX8&z{%HF9gM*5K67L;)aOj^oh8Fv;4c^$I(O(VLrl#)c*?ZISRqYd{m;t{eEr@uh z)Z@gEDV>tve3&c$ZO&`I!u-{j|DN9Z&reR}+W3_b?GKNufh8&j?Mp0x<>evO3Y8bE z-hd_d)+aH+_1o&9+%I}|m`|XZa#S)wO7|fJSMb4G_2`9KN(mlUqGS+F(Efuh02pb2 zYc`R7&u0LB;-}Aa9RTlemP8E)0R~axpb0@@w3T%-Tj!~LtzF-$ee`NyPw$-`$rJ5Vxi%p3X)De-2$7ypoQO=be z+}G&49kt5=r%(?`4aO*d>twQJv#n1)QwLZXU9e{&R%!Sy@9Ljjt4aI_m5}J}OWs2$ z@sMH4aJ=XO?Dh}38I0H|2N^ky1db580sV?&-AhW{w&l&qo1D<3Sh#WL-km#ZbN!9^ zcg}8eUvhJ;`d43X@BErnytOBYzm}QY%Q?cL1s7R@CJX^0K1L`^cQo{=yFdkv?e&x8 zQ70wx<0KEScY;Gjk0Qe%a?a@>wEtdlj0kg{W?uy}WY4jbgn{f3g!u6AwJ_IIvBk-$ zQ)5fO)t&{9&#fPEjE2)Nn&Ka)y8EtdI%IvDq2VeyF1Nw+Asz_9cg+Kd9S-))=UKh7bf!zqz$5JapQWm*gcZ-yahhLai)HSvxW10}N!J zvQG@G7HjmjT z_tc&q2|m|<3tgJM;OvaRA;F(~-fnMF=D-tMuHQe9KC1ViGi_?_Eu1xC{rC!xK|lYf z`R?6ypKToadgaM;&!2pI;-97ANO8a;^;8 z`{5sL7o=|8ai#Rb^RHLGxAx@GEn_lgw7UG}&G>-2Zf`fJ+=IqWtI=#`m|Nb2F}HUz z*GhZOEo&B-yi(maqE_8o^TstXk6$;qf%??SW*`6lV*lf?ru=t48-5-6X|v|5Qb(68 zZPVq`ffN3Sfm)BY=>9;Y5V9d4g^ z%F#rLtLmn`LQ7_{OVrD(%rf9KX;^6Pz{hDzo1fW!4*HoDs^T)$a&>J=f4hUA8Ox4t zO93JG?1I4QFhZUf(%o>HwP4Gz0QPZxb&bww#)e?A*`9d!V~4%HJ9V3R>R!*gv%bB}V;QPRDlbAL4j zDN%MwP$Vk}ECVxyqHTD`V@jAuCxW^b5qsj+!!rqhbEqg3X~OdvItrmLR##b+RcX~) ztGv!ZF{z)omXgv9q~v~lvd47tHYf1U*MFXp1%h{tuyNE+3Opx zKAlo$Tz@=;i1k9>yO{{v&G5kCWXbQw(Z@Y~sMp3KP^H|fsL8uoh{Axnxky)ko>RLD2*985RrK%j!V{~3o$+E_0=C9;t_ls>d zaun%`b_KcZ`U{25pDXF1+*T67*yy292*T-h_q|raPHnxNVeWk= zFg5SOyff^sJQOfNL!w4tcq0dI0mI?+{arj+Xmsl{UoO1R?$Sp~yZ#ovF>;V}cwTwen zW=YBC^UEzC9IG|yjr4ogq6;T?HLkZj`rb2Ym?o}caFN+ZRha)mnyz! z?AdMR&3m^^yF+I9-D&y3#_O-ohOU3LxA2sIR{HOwvv)Cnw(t4(#dUv~?k66-7Nosc zk(T%Ae*qyyMa$+V^9=+3+Pz;l&XCzL!}MTS;JN)zcZ?jd&|}oD^NC^87vG=xq<@D7 z7snp>$vA26o20u(cXU@S(2lSwvyRR0@;p}x@s2iauZe;a}sAC3?5 z>BH78`aIp+yQJu@_XD~XLP$3O2hC*D|A6b*-YOj(CSkFO~ckpv^WnQ|v`8c1(u zH|$2y4C0|;!UP4=Q2POa+Zbz)*J>~8$kst#mdW15y^Ggv<)-U*&jNQ+4~b3A{npM& z>Zp1#qWAeBx56?6L7g#Ykvn%_ZSTMszgzv>KMuRL(2ae!rT=9Av`r(1O;7m<<8d22 zo2$Ast(U(u(4D#*a9ZP1r#<`*rWNOymR2xAK+wXloWwx^l;P8E2?3L#P5!xWhscDG zgI~D~nEAxJd*6_poOYk6yEc6t_~o4)OMZ15@ztY;Cq5eY?!}K@?l$_rl2aNrF@EuI z%uCtay}z21cD`k;>zDF(KAAZG*2p5msC8GDEUx&i zUtF2{p1XhkS86dFzh3A2pD+17Z_wK7u=kH8(Xqh=sg0YuP3!h!7vIAv?N--N9iO>- z;1vHub$m97&vVDRMIIjQzQ*lLraF7pqXsWW>)!s|=yJ2am59G85kA+mJZbbu_}p*p z`wV6IkbgD61;UxYK{2PE?h}*JvQ@hE``hX$Yxkx>-op-s9?lHwe38J& z`OC0w&vETAA{02wCQg>%mWKjZhvoFKxRrL(gt=2Cktkx_$MwFz$C%E(V-nBU~ z(B>{eJa5K~t|jj2eg&_-Se}#guUpq9i^eu>?mMXBaH){}=(Ej-3OBX&+H%WSo;&V| zq4(^|0~W8(-1lmGo9JE>HqIUS^`Lp$i$8t082U%~jA_wbr!7u6ZHgH^y+=d-NzBKo zZR&KsQ*gMvtmtruPk%i(zOb`tn_u=cKXufT1E!*izn?$-dds)h|5-R;V$JAzIrZDD zY}q~j!vU%ypQf9Kl+7yb^|m;3-4Aim*~R7>&x#i(q|c2>Ue?I)$<~M$ADo)8a$^3U z3vxRBeDj0XJ##j^`_fxEq4?R?R_^VLcg}tL&Oy*?!=8D7|Rio&}VHi6U!7%x&y^moaAO(L)Ev0JXuI$^eheKcb`K2%dQ7cn==t zQq`R*iBQG@bq3h@BUzzZF3zAz4)@qrvvdvV&mdatIP+>}Krgp{4U`W*yWS)~ai`5ye7E)F zQnZ2IiS8~|p#0vmt5|1_{h&6F!)z2KEx5#j*(3|rr;CGPETdTH(LL@_vQV`xk9t7h z9B$kQYl(NdgY^W`jF^ss*Mm{7F`7*$XR-nLOlab`Zb9s-3`>&^_e;)aWO>i^J`&J% z&JXwh-s=^yaqz^aFWIJ+Y5gomg|QdY#{6p?HlRnjm$)bY_W>5}`_z`1s*EWyb%VS7 z_oq5zVXFI-L8m9yi{Cwd+wnZ(^edeUXSROt(}_d7DH^yICieT_uT${WkFXy+gI?AM zvK}Ht0{Ebuc(`k-?*T@A{Z;6)(2X6~sl)qU9PxhffX*X-B(7<8|Jt%9HS34(_a9#?@aw>17ry)Q zZQ{NY?~zlNUJW}O4^y8FzYyFPs9wN&AS1L<1IZB(TWk$(kr=u9KohTMw_E+f;@x_r zZ+H8ca@TMXnysGtKK9!czz+pM(prKf9P|ZMhlOlY-FCSUk`+|G z^ZbtI&YTK2T-4dE6#pio9opj;12(SHr__uA8aC2%@i=B;!`gXnO zUKCO$_x9QnpbpKCIkIWwre;qI4tJPY^s3xCtn-O(Ez6cP@A=LI>#gy>_Af2--nOK{ z)Kt0s(UC3t&f8ZKonKn##fQx8%lB$18?XkJZSv_$J<;yR!w;7Y3bMdtn-~dn8ltZW z6N6&nS>}wJZ&>bDSh)hXQ0j1@kn_V+vzq`o(k=wJNnqWL&@2lfX}Pi;L`$0%1oq1> zJlYsQjqE@c%1ty79yfA&2yGf{#ZR7CXfY+*GX#F2@T(2KI`FFtzp&lep7pL9ENw;I1f{6m*-KAu5`n z$r)`UB(hM9L<)R@FD#scpQw_ah;xR!;vG`ZuK-Q55Q#=-w1ZyA!T@HC-DWB9v9)0C z1ly3JGPviic!d=7c|emaLz32ca3@wFOBJn<0*~_xQBfpA&MKpF#U!MlX9Ak!6*3WM zl03*#X}c8oGaQ`Y64DY!%@t>mg6`=LXox{MF$fWxR*fJC#<%^cG%{ZUoZ<^&ofpm( zEl?#s68;q)0P0GS1UaK!(f8QKuN-^}z$rE#V&VP*Vgs782M4c22L*@Zw})6bSM)r};Aa3$k@XN$cSXrliMB+-zgcw%#n2-Y7S0tHk23fyKx;{6 z9)t6;yQ1Q$LR(b70-R>%afTyB3(Y@M1y{8UhGkdSXpoGCr_nUojDp@CY(bSFxMzr6 zb44+uz=K0TV+g_-GqLQh*ku&-a6s!U1lbI4qUTQ2$|&$308Wz3aKzxQIAs)cbSRuO zsA0D#6f=y*d2m-;G73B&;Uu#RVc}eH$SCL=fVMNrSnQNCMxFEEt~g{Ac&FL`CmCgk z!Cf)ODCkvyR(NDAHX@m7aGEJbfk)MWWhZ%KWap_P{RvGEqoDHvO_0S{STkW>5l+*> zDDay&I6)EvAyg+P4AC?hjDk+63zr%}4P)XUlBoD_2&Xw<6!ev6Tc{E z_b|8fz^ml+JSzjCn)l%vEBAn)U zQQ+bAz{rq{FT~(a08KNyDCh}@CU{<)*3AOWgexK!1%4CY6s-$!C%U3=QPBOv(Mk}6 zE`*J-T!XpO%qg6N<(7Lu1mfomE7oMdSs97u%IWGo7LJ)lWy789}T#{g}k zVL|@`^Y8e8#6OkJgm*)@QVCWTJ+bGmxK|YPhk&M-Scpw?W?8W~XjT;XZG@AgE5w!R zidscM4~)Pk2SKz#Ec;jRYT-y$Aq*|I5^E#qQF-JoZ>F2cGPH= z5(Vwi6ihpEmRPDtO9aA=!og{J5(O?GoFFR^s~t6(mqbDD1GIys#A2r@skY}dBZ&eJ zZw5z=;3qLwn>tNLqM*kB+KHS5{9h=^adyIXz?aixBntclz)5Nn4PhU#kDKNlQP64c zfQcelNGv=tcZAb)BMSUDz$x+(!bBmO<{44YO=H0ECRsevQ;R6*>o_<;G*WrY!T+oD01-}eiYV|lv0x=gh7sbZA)00rQP7_Qn&cL#a$YUA zqD+L-G$IQ81;9yC5somwQPAapriep`m&x_Cy1unp3~GH%HWG^Xo3i& z8rqrm!$J=J9N-iSNHsXk_@NBm?OiZ3B>x9-ouk50d>{Dz4i9h@zzO;fAb4@U84yl0 zeJE%T2K*qB_oJG&(+nRNf3!b2vJg%Zeh_YyD{c>E@Nz(tOdmR8a96Y*Hnhc-T+*?y z>?F$vp|7*y%g4STDL0hC{{b{bz(Kg5h^Cn}9BBCdPc#r(Ac;1Jiv{5{v4#V#Qk?}f zMYBP8fQY79H57Dnix&2rAlYE54NenkDDWaclk^&7upS4e$ut!74M1BcZVf`=5KdEQ zDDZd=r|wLs0e|C(({+w$nm$88F9I|$SXi9cG_-_)L^w^Jp}?OboS@Pm??gn?tQiWr zhYs}(IW#O)BpTJ`PSa&5@J#@x$TNtk&w{~erVIsLgU5HGoj1c$Nt{7w`%Hk->=+6> z7vL0E2BGb)m@yReWk5UgWLSVGgMecnJWY(Dz!^O(97&TwOdZiQ9fpEl4QPrS!$LUT z2&cI(6!<#^7@T0j5QwvaXqw(aL2m&xMRox(XQ%wPZSEAig#!08f^8?bF36A!qG@Ui z1uX+wAc-z2Zw5#H8{ssgg#teWaEjl8i0B}iCbUq{;jO_wlJpi;(RN$@8{ssOg#sTB zaEjJ~crzfH=CDxEKLVO$v>=ik78Sy2{t5-&vJH5zB%1|cq7Y5q24`*tum$zMUd?p@JRD1(0sXp*FYjHx(LP*|!sC=|H< zJ#Z!{MhfSJbH(zYpo7}O)CtZ9miY1^uSJ00E%~f@&TWoFW#Gboq zOjqDZUErLPZR*5Xan+Zupces}=u)>pr>*m{yXs6=;Ew?gf1w1?r%t2khHnLZJ{1Nh z+P_T#k^gqp>aD<&)4;rvjo*Y5hJDapNH^S)#Zv`IM6||jf_a@d2 z(R5q4f-VF!+2rjA_1p8`2&a3v75FQFQytxe#<*(HR?ri=;owBWwz6)R|Hf`#x*1!6 zzXmwfnoTGiqUrW(1wE}hXbjnGO&Dhj!s%9O1zw{Ez{$qyYJ<}))C&3&KvNCXL?jHx zwp44ER^WdFoNAs{7S6tIbeFV(&PfL})idpUR(imPKdo;en~W9s;GWE>T$@a=%6 zT7ijs1<_=~uigKw^Z=uJgM}mee~D#BINkHB3_cdnR0l9Ib?jcHdwreq-@gK!Z2fiA z=u{?X5KedaDuZYB0sBbw`|`wvjA*)}7t!|o_a%T+4Zei;ig3DvR~bCDFPbQ#pO*+s zAe!#mwWD$U4+7jkw($~hSM9mV;BEV%*H1L-5?}7BAy+|Lwg8;!&n1kEtCm~^?$IBO z4AG!VC|ojpIo(;SpcnUt{5Rcb>ujSs1DtMdRp7k_z?Dk1x;mp>HGwMVoPjWP*+TS$ z655^wgVPA> zSG{x!IzWQKsm?k(x-$QbaOZwD(i=DiaH_eD@Zk_m_pm90^D_7nWJjCRbq@J&gwx$? z3cL*9bT6Cpm%Hi&Q_!=`;6)LAVJtEAH5M40?g3NauK-SUgb~h!t41&d-FYxxYD8NY aoE0x`{6G2z_6^J$;jQxi9R4Sj>VE*Wh^R~e delta 98 zcmeBKlYaA8N<#}{3sVbo3rh=Y3tJ0&3r7oQ3s(zw3r`Dg3ttO=i$IHDi_jL~Y?k&J s>B2xP0>q*~EC$5lKrFF+M!MuJ3lUZ}1|X>BtLD39!N!ouA`IjK0HDeq&j0`b diff --git a/testdata/fuzz/FuzzRoundtrip.zip b/testdata/fuzz/FuzzRoundtrip.zip index 2f31335fde90b98822bf964d927031234afe9cf6..e0312259eb2fac1757d470932a606edae42d4abf 100644 GIT binary patch delta 62419 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 delta 68 zcmezMz~<{-i-s1)7N!>F7M2#)7Pc1l7LFFqEnJ_Y+arv*ftUw~dACOx^SwJH!pg<~ T1P3_|a=bgl%